diff --git a/code/addons/docs/ember/README.md b/code/addons/docs/ember/README.md index 29af33a3b433..e1d907435883 100644 --- a/code/addons/docs/ember/README.md +++ b/code/addons/docs/ember/README.md @@ -51,7 +51,7 @@ Next, add the following to your `.storybook/preview.js` to load the generated js ```js import { setJSONDoc } from '@storybook/addon-docs/ember'; -import docJson from '../storybook-docgen/index.json'; +import docJson from '../dist/storybook-docgen/index.json'; setJSONDoc(docJson); ``` diff --git a/code/frameworks/ember/package.json b/code/frameworks/ember/package.json index 43954dc5e6d5..d72d9de238a4 100644 --- a/code/frameworks/ember/package.json +++ b/code/frameworks/ember/package.json @@ -38,6 +38,7 @@ "@storybook/global": "^5.0.0", "@storybook/preview-api": "workspace:*", "@storybook/types": "workspace:*", + "find-up": "^5.0.0", "ts-dedent": "^2.0.0" }, "devDependencies": { @@ -46,10 +47,11 @@ }, "peerDependencies": { "@babel/core": "*", - "@types/ember__component": "4.0.8", - "babel-plugin-ember-modules-api-polyfill": "^2.12.0", - "babel-plugin-htmlbars-inline-precompile": "2 || 3", - "ember-source": "~3.28.1" + "babel-plugin-ember-modules-api-polyfill": "^3.5.0", + "babel-plugin-htmlbars-inline-precompile": "^5.3.1", + "ember-source": "~3.28.1 || ^4.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" }, "engines": { "node": ">=16.0.0" diff --git a/code/frameworks/ember/src/client/docs/index.js b/code/frameworks/ember/src/client/docs/index.js deleted file mode 100644 index fab7166db9d7..000000000000 --- a/code/frameworks/ember/src/client/docs/index.js +++ /dev/null @@ -1 +0,0 @@ -export { setJSONDoc } from './jsondoc'; diff --git a/code/frameworks/ember/src/client/docs/jsondoc.js b/code/frameworks/ember/src/client/docs/jsondoc.js deleted file mode 100644 index 9e7269af8d45..000000000000 --- a/code/frameworks/ember/src/client/docs/jsondoc.js +++ /dev/null @@ -1,50 +0,0 @@ -/* eslint-disable no-underscore-dangle */ -import { global } from '@storybook/global'; - -export const setJSONDoc = (jsondoc) => { - global.__EMBER_GENERATED_DOC_JSON__ = jsondoc; -}; -export const getJSONDoc = () => { - return global.__EMBER_GENERATED_DOC_JSON__; -}; - -export const extractArgTypes = (componentName) => { - const json = getJSONDoc(); - if (!(json && json.included)) { - return null; - } - const componentDoc = json.included.find((doc) => doc.attributes.name === componentName); - - if (!componentDoc) { - return null; - } - return componentDoc.attributes.arguments.reduce((acc, prop) => { - acc[prop.name] = { - name: prop.name, - defaultValue: prop.defaultValue, - description: prop.description, - table: { - defaultValue: { summary: prop.defaultValue }, - type: { - summary: prop.type, - required: prop.tags.length ? prop.tags.some((tag) => tag.name === 'required') : false, - }, - }, - }; - return acc; - }, {}); -}; - -export const extractComponentDescription = (componentName) => { - const json = getJSONDoc(); - if (!(json && json.included)) { - return null; - } - const componentDoc = json.included.find((doc) => doc.attributes.name === componentName); - - if (!componentDoc) { - return null; - } - - return componentDoc.attributes.description; -}; diff --git a/code/frameworks/ember/src/client/preview/config.ts b/code/frameworks/ember/src/client/preview/config.ts index c3ad2801c19a..85a89d8e241c 100644 --- a/code/frameworks/ember/src/client/preview/config.ts +++ b/code/frameworks/ember/src/client/preview/config.ts @@ -1,3 +1,5 @@ +import './globals'; + export { renderToCanvas } from './render'; export const parameters = { renderer: 'ember' as const }; diff --git a/code/frameworks/ember/src/client/preview/docs/config.js b/code/frameworks/ember/src/client/preview/docs/config.js deleted file mode 100644 index a4868993b8c7..000000000000 --- a/code/frameworks/ember/src/client/preview/docs/config.js +++ /dev/null @@ -1,9 +0,0 @@ -import { extractArgTypes, extractComponentDescription } from './jsondoc'; - -export const parameters = { - docs: { - story: { iframeHeight: '80px' }, - extractArgTypes, - extractComponentDescription, - }, -}; diff --git a/code/frameworks/ember/src/client/docs/config.js b/code/frameworks/ember/src/client/preview/docs/config.ts similarity index 59% rename from code/frameworks/ember/src/client/docs/config.js rename to code/frameworks/ember/src/client/preview/docs/config.ts index 22fdb2cd80e3..c1ac3a894012 100644 --- a/code/frameworks/ember/src/client/docs/config.js +++ b/code/frameworks/ember/src/client/preview/docs/config.ts @@ -1,7 +1,9 @@ +import type { ArgTypesEnhancer } from '@storybook/types'; import { enhanceArgTypes } from '@storybook/docs-tools'; + import { extractArgTypes, extractComponentDescription } from './jsondoc'; -export const parameters = { +export const parameters: {} = { docs: { story: { iframeHeight: '80px' }, extractArgTypes, @@ -9,4 +11,4 @@ export const parameters = { }, }; -export const argTypesEnhancers = [enhanceArgTypes]; +export const argTypesEnhancers: ArgTypesEnhancer[] = [enhanceArgTypes]; diff --git a/code/frameworks/ember/src/client/preview/docs/index.js b/code/frameworks/ember/src/client/preview/docs/index.js deleted file mode 100644 index fab7166db9d7..000000000000 --- a/code/frameworks/ember/src/client/preview/docs/index.js +++ /dev/null @@ -1 +0,0 @@ -export { setJSONDoc } from './jsondoc'; diff --git a/code/frameworks/ember/src/client/preview/docs/jsondoc.js b/code/frameworks/ember/src/client/preview/docs/jsondoc.ts similarity index 58% rename from code/frameworks/ember/src/client/preview/docs/jsondoc.js rename to code/frameworks/ember/src/client/preview/docs/jsondoc.ts index 9e7269af8d45..a714fa5365a7 100644 --- a/code/frameworks/ember/src/client/preview/docs/jsondoc.js +++ b/code/frameworks/ember/src/client/preview/docs/jsondoc.ts @@ -1,24 +1,21 @@ /* eslint-disable no-underscore-dangle */ import { global } from '@storybook/global'; -export const setJSONDoc = (jsondoc) => { - global.__EMBER_GENERATED_DOC_JSON__ = jsondoc; -}; export const getJSONDoc = () => { return global.__EMBER_GENERATED_DOC_JSON__; }; -export const extractArgTypes = (componentName) => { +export const extractArgTypes = (componentName: string) => { const json = getJSONDoc(); if (!(json && json.included)) { return null; } - const componentDoc = json.included.find((doc) => doc.attributes.name === componentName); + const componentDoc = json.included.find((doc: any) => doc.attributes.name === componentName); if (!componentDoc) { return null; } - return componentDoc.attributes.arguments.reduce((acc, prop) => { + return componentDoc.attributes.arguments.reduce((acc: any, prop: any) => { acc[prop.name] = { name: prop.name, defaultValue: prop.defaultValue, @@ -27,7 +24,9 @@ export const extractArgTypes = (componentName) => { defaultValue: { summary: prop.defaultValue }, type: { summary: prop.type, - required: prop.tags.length ? prop.tags.some((tag) => tag.name === 'required') : false, + required: prop.tags.length + ? prop.tags.some((tag: any) => tag.name === 'required') + : false, }, }, }; @@ -35,12 +34,12 @@ export const extractArgTypes = (componentName) => { }, {}); }; -export const extractComponentDescription = (componentName) => { +export const extractComponentDescription = (componentName: string) => { const json = getJSONDoc(); if (!(json && json.included)) { return null; } - const componentDoc = json.included.find((doc) => doc.attributes.name === componentName); + const componentDoc = json.included.find((doc: any) => doc.attributes.name === componentName); if (!componentDoc) { return null; diff --git a/code/frameworks/ember/src/client/preview/render.ts b/code/frameworks/ember/src/client/preview/render.ts index 84121a6cd7bf..030314d910f8 100644 --- a/code/frameworks/ember/src/client/preview/render.ts +++ b/code/frameworks/ember/src/client/preview/render.ts @@ -1,21 +1,24 @@ import { global } from '@storybook/global'; import { dedent } from 'ts-dedent'; import type { RenderContext } from '@storybook/types'; -// @ts-expect-error (Converted from ts-ignore) -import Component from '@ember/component'; // eslint-disable-line import/no-unresolved import type { OptionsArgs, EmberRenderer } from './types'; const { document } = global; +declare let Ember: any; + const rootEl = document.getElementById('storybook-root'); -const config = global.require(`${global.STORYBOOK_NAME}/config/environment`); -const app = global.require(`${global.STORYBOOK_NAME}/app`).default.create({ - autoboot: false, - rootElement: rootEl, - ...config.APP, -}); +function loadEmberApp() { + const config = global.require(`${global.STORYBOOK_NAME}/config/environment`); + return global.require(`${global.STORYBOOK_NAME}/app`).default.create({ + autoboot: false, + rootElement: rootEl, + ...config.APP, + }); +} +const app = loadEmberApp(); let lastPromise = app.boot(); let hasRendered = false; let isRendering = false; @@ -38,7 +41,7 @@ function render(options: OptionsArgs, el: EmberRenderer['canvasElement']) { .then((instance: any) => { instance.register( 'component:story-mode', - Component.extend({ + Ember.Component.extend({ layout: template || options, ...context, }) diff --git a/code/frameworks/ember/src/index.ts b/code/frameworks/ember/src/index.ts index fc8faa13668a..30a9049586ce 100644 --- a/code/frameworks/ember/src/index.ts +++ b/code/frameworks/ember/src/index.ts @@ -1,6 +1,6 @@ /// -import './client/preview'; +export * from './types'; // optimization: stop HMR propagation in webpack if (typeof module !== 'undefined') module?.hot?.decline(); diff --git a/code/frameworks/ember/src/server/framework-preset-babel-ember.ts b/code/frameworks/ember/src/server/framework-preset-babel-ember.ts index 54f31c0fd739..cdb83bf6dbfa 100644 --- a/code/frameworks/ember/src/server/framework-preset-babel-ember.ts +++ b/code/frameworks/ember/src/server/framework-preset-babel-ember.ts @@ -1,6 +1,6 @@ import { precompile } from 'ember-source/dist/ember-template-compiler'; -import { findDistEsm } from '@storybook/core-common'; import type { PresetProperty } from '@storybook/types'; +import { findDistFile } from '../util'; let emberOptions: any; @@ -50,5 +50,5 @@ export const babel: PresetProperty<'babel'> = (config, options) => { }; export const previewAnnotations: PresetProperty<'previewAnnotations'> = (entry = []) => { - return [...entry, findDistEsm(__dirname, 'client/preview/config')]; + return [...entry, findDistFile(__dirname, 'client/preview/config')]; }; diff --git a/code/frameworks/ember/src/server/framework-preset-ember-docs.ts b/code/frameworks/ember/src/server/framework-preset-ember-docs.ts index 24e1a97a1cc9..577978ef8652 100644 --- a/code/frameworks/ember/src/server/framework-preset-ember-docs.ts +++ b/code/frameworks/ember/src/server/framework-preset-ember-docs.ts @@ -1,8 +1,8 @@ import type { PresetProperty } from '@storybook/types'; -import { findDistEsm } from '@storybook/core-common'; import { hasDocsOrControls } from '@storybook/docs-tools'; +import { findDistFile } from '../util'; export const previewAnnotations: PresetProperty<'previewAnnotations'> = (entry = [], options) => { if (!hasDocsOrControls(options)) return entry; - return [...entry, findDistEsm(__dirname, 'client/docs/config')]; + return [...entry, findDistFile(__dirname, 'client/preview/docs/config')]; }; diff --git a/code/frameworks/ember/src/types.ts b/code/frameworks/ember/src/types.ts index e75995bf27a7..a00e2741a03f 100644 --- a/code/frameworks/ember/src/types.ts +++ b/code/frameworks/ember/src/types.ts @@ -43,3 +43,8 @@ export type StorybookConfig = Omit< > & StorybookConfigWebpack & StorybookConfigFramework; + +declare global { + // eslint-disable-next-line no-underscore-dangle, @typescript-eslint/naming-convention, no-var, vars-on-top + var __EMBER_GENERATED_DOC_JSON__: any; +} diff --git a/code/lib/core-common/src/utils/findDistEsm.ts b/code/frameworks/ember/src/util.ts similarity index 69% rename from code/lib/core-common/src/utils/findDistEsm.ts rename to code/frameworks/ember/src/util.ts index 51a34e1669fb..eeecd1e91c9d 100644 --- a/code/lib/core-common/src/utils/findDistEsm.ts +++ b/code/frameworks/ember/src/util.ts @@ -1,12 +1,12 @@ import path from 'path'; import { sync as findUpSync } from 'find-up'; -export const findDistEsm = (cwd: string, relativePath: string) => { +export const findDistFile = (cwd: string, relativePath: string) => { const nearestPackageJson = findUpSync('package.json', { cwd }); if (!nearestPackageJson) { throw new Error(`Could not find package.json in: ${cwd}`); } const packageDir = path.dirname(nearestPackageJson); - return path.join(packageDir, 'dist', 'esm', relativePath); + return path.join(packageDir, 'dist', relativePath); }; diff --git a/code/frameworks/ember/template/cli/Button.stories.js b/code/frameworks/ember/template/cli/Button.stories.js index c32f8a065659..61de1a4f9cc9 100644 --- a/code/frameworks/ember/template/cli/Button.stories.js +++ b/code/frameworks/ember/template/cli/Button.stories.js @@ -6,13 +6,13 @@ import { linkTo } from '@storybook/addon-links'; export default { title: 'Example/Button', render: (args) => ({ - template: hbs``, + template: hbs``, context: args, }), argTypes: { label: { control: 'text' }, }, - // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/ember/writing-docs/autodocs tags: ['autodocs'], }; @@ -27,13 +27,14 @@ export const Text = { export const Emoji = { args: { label: '😀 😎 👍 💯', + onClick: action('onClick'), }, }; export const TextWithAction = { render: () => ({ template: hbs` - `, @@ -50,12 +51,12 @@ export const TextWithAction = { export const ButtonWithLinkToAnotherStory = { render: () => ({ template: hbs` - `, context: { - onClick: linkTo('example-introduction--page'), + onClick: linkTo('example-button--docs'), }, }), name: 'button with link to another story', diff --git a/code/frameworks/ember/template/components/index.js b/code/frameworks/ember/template/components/index.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/code/frameworks/ember/template/stories/.gitkeep b/code/frameworks/ember/template/stories/.gitkeep new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/code/lib/cli/src/detect.ts b/code/lib/cli/src/detect.ts index 733ed65e2974..f8fe7eb9903d 100644 --- a/code/lib/cli/src/detect.ts +++ b/code/lib/cli/src/detect.ts @@ -131,6 +131,7 @@ export async function detectBuilder(packageManager: JsPackageManager, projectTyp case ProjectType.ANGULAR: case ProjectType.REACT_NATIVE: // technically react native doesn't use webpack, we just want to set something case ProjectType.NEXTJS: + case ProjectType.EMBER: return CoreBuilder.Webpack5; default: // eslint-disable-next-line no-case-declarations diff --git a/code/lib/cli/src/generators/EMBER/index.ts b/code/lib/cli/src/generators/EMBER/index.ts index 313dcf8691fd..98c041c952f7 100644 --- a/code/lib/cli/src/generators/EMBER/index.ts +++ b/code/lib/cli/src/generators/EMBER/index.ts @@ -16,7 +16,8 @@ const generator: Generator = async (packageManager, npmOptions, options) => { 'babel-plugin-htmlbars-inline-precompile', ], staticDir: 'dist', - } + }, + 'ember' ); }; diff --git a/code/lib/cli/src/project_types.ts b/code/lib/cli/src/project_types.ts index 8f1f07b3ae0f..0a0073d84664 100644 --- a/code/lib/cli/src/project_types.ts +++ b/code/lib/cli/src/project_types.ts @@ -22,7 +22,7 @@ export const externalFrameworks: ExternalFramework[] = [ ]; // Should match @storybook/ -export type SupportedFrameworks = 'nextjs' | 'angular' | 'sveltekit' | 'qwik' | 'solid'; +export type SupportedFrameworks = 'nextjs' | 'angular' | 'sveltekit' | 'qwik' | 'solid' | 'ember'; // Should match @storybook/ export type SupportedRenderers = diff --git a/code/lib/cli/src/sandbox-templates.ts b/code/lib/cli/src/sandbox-templates.ts index cea75614ae81..ba9a54e6c000 100644 --- a/code/lib/cli/src/sandbox-templates.ts +++ b/code/lib/cli/src/sandbox-templates.ts @@ -471,6 +471,27 @@ const baseTemplates = { // TODO: The community template does not provide standard stories, which is required for e2e tests. skipTasks: ['e2e-tests', 'e2e-tests-dev', 'bench'], }, + 'ember/3-js': { + name: 'Ember v3 (Webpack | JavaScript)', + script: 'npx --package ember-cli@3.28.1 ember new {{beforeDir}}', + inDevelopment: true, + expected: { + framework: '@storybook/ember', + renderer: '@storybook/ember', + builder: '@storybook/builder-webpack5', + }, + }, + 'ember/default-js': { + name: 'Ember v4 (Webpack | JavaScript)', + script: + 'npx --package ember-cli@4.12.1 ember new {{beforeDir}} --yarn && cd {{beforeDir}} && yarn add --dev @storybook/ember-cli-storybook && yarn build', + inDevelopment: true, + expected: { + framework: '@storybook/ember', + renderer: '@storybook/ember', + builder: '@storybook/builder-webpack5', + }, + }, } satisfies Record; /** @@ -589,6 +610,7 @@ export const normal: TemplateKey[] = [ 'bench/react-vite-default-ts-nodocs', 'bench/react-vite-default-ts-test-build', 'bench/react-webpack-18-ts-test-build', + 'ember/default-js', ]; export const merged: TemplateKey[] = [ diff --git a/code/lib/core-common/src/index.ts b/code/lib/core-common/src/index.ts index 7296dc814a2c..2af1d1100798 100644 --- a/code/lib/core-common/src/index.ts +++ b/code/lib/core-common/src/index.ts @@ -5,7 +5,6 @@ export * from './presets'; export * from './utils/cache'; export * from './utils/check-addon-order'; export * from './utils/envs'; -export * from './utils/findDistEsm'; export * from './utils/common-glob-options'; export * from './utils/get-builder-options'; export * from './utils/get-framework-name'; diff --git a/code/yarn.lock b/code/yarn.lock index b20f98adbe2a..f60a4cfaf723 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -5722,14 +5722,16 @@ __metadata: "@storybook/preview-api": "workspace:*" "@storybook/types": "workspace:*" ember-source: "npm:~3.28.1" + find-up: "npm:^5.0.0" ts-dedent: "npm:^2.0.0" typescript: "npm:^5.3.2" peerDependencies: "@babel/core": "*" - "@types/ember__component": 4.0.8 - babel-plugin-ember-modules-api-polyfill: ^2.12.0 - babel-plugin-htmlbars-inline-precompile: 2 || 3 - ember-source: ~3.28.1 + babel-plugin-ember-modules-api-polyfill: ^3.5.0 + babel-plugin-htmlbars-inline-precompile: ^5.3.1 + ember-source: ~3.28.1 || ^4.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 languageName: unknown linkType: soft diff --git a/scripts/verdaccio.yaml b/scripts/verdaccio.yaml index 89bb067a5d39..e0139f305f0b 100644 --- a/scripts/verdaccio.yaml +++ b/scripts/verdaccio.yaml @@ -120,6 +120,10 @@ packages: access: $all publish: $all proxy: npmjs + '@storybook/ember-cli-storybook': + access: $all + publish: $all + proxy: npmjs # storybook packages are NOT proxied to global registry # allowing us to republish any version during tests