diff --git a/code/frameworks/vue3-vite/package.json b/code/frameworks/vue3-vite/package.json index 456ba9beb140..ce0b076af2ab 100644 --- a/code/frameworks/vue3-vite/package.json +++ b/code/frameworks/vue3-vite/package.json @@ -50,10 +50,14 @@ "@storybook/builder-vite": "workspace:*", "@storybook/core-server": "workspace:*", "@storybook/vue3": "workspace:*", + "find-package-json": "^1.2.0", "magic-string": "^0.30.0", - "vue-docgen-api": "^4.40.0" + "typescript": "^5.0.0", + "vue-component-meta": "^1.8.27", + "vue-docgen-api": "^4.75.1" }, "devDependencies": { + "@types/find-package-json": "^1.2.6", "@types/node": "^18.0.0", "typescript": "^5.3.2", "vite": "^4.0.0" diff --git a/code/frameworks/vue3-vite/src/plugins/vue-component-meta.ts b/code/frameworks/vue3-vite/src/plugins/vue-component-meta.ts new file mode 100644 index 000000000000..bd6a22fe338a --- /dev/null +++ b/code/frameworks/vue3-vite/src/plugins/vue-component-meta.ts @@ -0,0 +1,253 @@ +import findPackageJson from 'find-package-json'; +import fs from 'fs/promises'; +import MagicString from 'magic-string'; +import path from 'path'; +import type { PluginOption } from 'vite'; +import { + TypeMeta, + createComponentMetaChecker, + createComponentMetaCheckerByJsonConfig, + type ComponentMeta, + type MetaCheckerOptions, +} from 'vue-component-meta'; +import { parseMulti } from 'vue-docgen-api'; + +type MetaSource = { + exportName: string; + displayName: string; + sourceFiles: string; +} & ComponentMeta & + MetaCheckerOptions['schema']; + +export async function vueComponentMeta(): Promise { + const { createFilter } = await import('vite'); + + // exclude stories, virtual modules and storybook internals + const exclude = + /\.stories\.(ts|tsx|js|jsx)$|^\/virtual:|^\/sb-preview\/|\.storybook\/.*\.(ts|js)$/; + const include = /\.(vue|ts|js|tsx|jsx)$/; + const filter = createFilter(include, exclude); + + const checker = await createChecker(); + + return { + name: 'storybook:vue-component-meta-plugin', + async transform(src, id) { + if (!filter(id)) return undefined; + + try { + const exportNames = checker.getExportNames(id); + let componentsMeta = exportNames.map((name) => checker.getComponentMeta(id, name)); + componentsMeta = await applyTempFixForEventDescriptions(id, componentsMeta); + + const metaSources: MetaSource[] = []; + + componentsMeta.forEach((meta, index) => { + // filter out empty meta + const isEmpty = + !meta.props.length && !meta.events.length && !meta.slots.length && !meta.exposed.length; + if (isEmpty || meta.type === TypeMeta.Unknown) return; + + const exportName = exportNames[index]; + + const exposed = + // the meta also includes duplicated entries in the "exposed" array with "on" + // prefix (e.g. onClick instead of click), so we need to filter them out here + meta.exposed + .filter((expose) => { + let nameWithoutOnPrefix = expose.name; + + if (nameWithoutOnPrefix.startsWith('on')) { + nameWithoutOnPrefix = lowercaseFirstLetter(expose.name.replace('on', '')); + } + + const hasEvent = meta.events.find((event) => event.name === nameWithoutOnPrefix); + return !hasEvent; + }) + // remove unwanted duplicated "$slots" expose + .filter((expose) => { + if (expose.name === '$slots') { + const slotNames = meta.slots.map((slot) => slot.name); + return !slotNames.every((slotName) => expose.type.includes(slotName)); + } + return true; + }); + + metaSources.push({ + exportName, + displayName: exportName === 'default' ? getFilenameWithoutExtension(id) : exportName, + ...meta, + exposed, + sourceFiles: id, + }); + }); + + // if there is no component meta, return undefined + if (metaSources.length === 0) return undefined; + + const s = new MagicString(src); + + metaSources.forEach((meta) => { + const isDefaultExport = meta.exportName === 'default'; + const name = isDefaultExport ? '_sfc_main' : meta.exportName; + + // we can only add the "__docgenInfo" to variables that are actually defined in the current file + // so e.g. re-exports like "export { default as MyComponent } from './MyComponent.vue'" must be ignored + // to prevent runtime errors + if (new RegExp(`export {.*${name}.*}`).test(src)) { + return; + } + + if (!id.endsWith('.vue') && isDefaultExport) { + // we can not add the __docgenInfo if the component is default exported directly + // so we need to safe it to a variable instead and export default it instead + s.replace('export default ', 'const _sfc_main = '); + s.append('\nexport default _sfc_main;'); + } + + s.append(`\n;${name}.__docgenInfo = ${JSON.stringify(meta)}`); + }); + + return { + code: s.toString(), + map: s.generateMap({ hires: true, source: id }), + }; + } catch (e) { + return undefined; + } + }, + }; +} + +/** + * Creates the vue-component-meta checker to use for extracting component meta/docs. + */ +async function createChecker() { + const checkerOptions: MetaCheckerOptions = { + forceUseTs: true, + noDeclarations: true, + printer: { newLine: 1 }, + }; + + const projectRoot = getProjectRoot(); + const projectTsConfigPath = path.join(projectRoot, 'tsconfig.json'); + + const defaultChecker = createComponentMetaCheckerByJsonConfig( + projectRoot, + { include: ['**/*'] }, + checkerOptions + ); + + // prefer the tsconfig.json file of the project to support alias resolution etc. + if (await fileExists(projectTsConfigPath)) { + // tsconfig that uses references is currently not supported by vue-component-meta + // see: https://github.com/vuejs/language-tools/issues/3896 + // so we return the no-tsconfig defaultChecker if tsconfig references are found + // remove this workaround once the above issue is fixed + const references = await getTsConfigReferences(projectTsConfigPath); + if (references.length > 0) { + // TODO: paths/aliases are not resolvable, find workaround for this + return defaultChecker; + } + return createComponentMetaChecker(projectTsConfigPath, checkerOptions); + } + + return defaultChecker; +} + +/** + * Gets the absolute path to the project root. + */ +function getProjectRoot() { + const projectRoot = findPackageJson().next().value?.path ?? ''; + + const currentFileDir = path.dirname(__filename); + const relativePathToProjectRoot = path.relative(currentFileDir, projectRoot); + + return path.resolve(currentFileDir, relativePathToProjectRoot); +} + +/** + * Gets the filename without file extension. + */ +function getFilenameWithoutExtension(filename: string) { + return path.parse(filename).name; +} + +/** + * Lowercases the first letter. + */ +function lowercaseFirstLetter(string: string) { + return string.charAt(0).toLowerCase() + string.slice(1); +} + +/** + * Checks whether the given file path exists. + */ +async function fileExists(fullPath: string) { + try { + await fs.stat(fullPath); + return true; + } catch { + return false; + } +} + +/** + * Applies a temporary workaround/fix for missing event descriptions because + * Volar is currently not able to extract them. + * Will modify the events of the passed meta. + * Performance note: Based on some quick tests, calling "parseMulti" only takes a few milliseconds (8-20ms) + * so it should not decrease performance that much. Especially because it is only execute if the component actually + * has events. + * + * Check status of this Volar issue: https://github.com/vuejs/language-tools/issues/3893 + * and update/remove this workaround once Volar supports it: + * - delete this function + * - uninstall vue-docgen-api dependency + */ +async function applyTempFixForEventDescriptions(filename: string, componentMeta: ComponentMeta[]) { + // do not apply temp fix if no events exist for performance reasons + const hasEvents = componentMeta.some((meta) => meta.events.length); + if (!hasEvents) return componentMeta; + + try { + const parsedComponentDocs = await parseMulti(filename); + + // add event descriptions to the existing Volar meta if available + componentMeta.map((meta, index) => { + const eventsWithDescription = parsedComponentDocs[index].events; + if (!meta.events.length || !eventsWithDescription?.length) return meta; + + meta.events = meta.events.map((event) => { + const description = eventsWithDescription.find((i) => i.name === event.name)?.description; + if (description) { + (event as typeof event & { description: string }).description = description; + } + return event; + }); + + return meta; + }); + } catch { + // noop + } + + return componentMeta; +} + +/** + * Gets a list of tsconfig references for the given tsconfig path. + * This is only needed for the temporary workaround/fix for: + * https://github.com/vuejs/language-tools/issues/3896 + */ +async function getTsConfigReferences(tsConfigPath: string) { + try { + const content = JSON.parse(await fs.readFile(tsConfigPath, 'utf-8')); + if (!('references' in content) || !Array.isArray(content.references)) return []; + return content.references as unknown[]; + } catch { + // invalid project tsconfig + return []; + } +} diff --git a/code/frameworks/vue3-vite/src/plugins/vue-docgen.ts b/code/frameworks/vue3-vite/src/plugins/vue-docgen.ts index f8008fc3a4bd..33a1d1b44a0a 100644 --- a/code/frameworks/vue3-vite/src/plugins/vue-docgen.ts +++ b/code/frameworks/vue3-vite/src/plugins/vue-docgen.ts @@ -1,22 +1,22 @@ -import { parse } from 'vue-docgen-api'; -import type { PluginOption } from 'vite'; import MagicString from 'magic-string'; +import type { PluginOption } from 'vite'; +import { parse } from 'vue-docgen-api'; export async function vueDocgen(): Promise { - const include = /\.(vue)$/; const { createFilter } = await import('vite'); + + const include = /\.(vue)$/; const filter = createFilter(include); return { name: 'storybook:vue-docgen-plugin', - - async transform(src: string, id: string) { + async transform(src, id) { if (!filter(id)) return undefined; const metaData = await parse(id); - const metaSource = JSON.stringify(metaData); + const s = new MagicString(src); - s.append(`;_sfc_main.__docgenInfo = ${metaSource}`); + s.append(`;_sfc_main.__docgenInfo = ${JSON.stringify(metaData)}`); return { code: s.toString(), diff --git a/code/frameworks/vue3-vite/src/preset.ts b/code/frameworks/vue3-vite/src/preset.ts index 58ceb6afb846..69173e6e767c 100644 --- a/code/frameworks/vue3-vite/src/preset.ts +++ b/code/frameworks/vue3-vite/src/preset.ts @@ -1,8 +1,9 @@ import type { PresetProperty } from '@storybook/types'; -import type { PluginOption } from 'vite'; import { dirname, join } from 'path'; -import type { StorybookConfig } from './types'; +import type { PluginOption } from 'vite'; +import { vueComponentMeta } from './plugins/vue-component-meta'; import { vueDocgen } from './plugins/vue-docgen'; +import type { FrameworkOptions, StorybookConfig } from './types'; const getAbsolutePath = (input: I): I => dirname(require.resolve(join(input, 'package.json'))) as any; @@ -12,11 +13,21 @@ export const core: PresetProperty<'core'> = { renderer: getAbsolutePath('@storybook/vue3'), }; -export const viteFinal: StorybookConfig['viteFinal'] = async (config, { presets }) => { +export const viteFinal: StorybookConfig['viteFinal'] = async (config, options) => { const plugins: PluginOption[] = []; - // Add docgen plugin - plugins.push(await vueDocgen()); + const framework = await options.presets.apply('framework'); + const frameworkOptions: FrameworkOptions = + typeof framework === 'string' ? {} : framework.options ?? {}; + + const docgenPlugin = frameworkOptions.docgen ?? 'vue-docgen-api'; + + // add docgen plugin depending on framework option + if (docgenPlugin === 'vue-component-meta') { + plugins.push(await vueComponentMeta()); + } else { + plugins.push(await vueDocgen()); + } const { mergeConfig } = await import('vite'); return mergeConfig(config, { diff --git a/code/frameworks/vue3-vite/src/types.ts b/code/frameworks/vue3-vite/src/types.ts index 1461f586aeed..c6ee52bf144a 100644 --- a/code/frameworks/vue3-vite/src/types.ts +++ b/code/frameworks/vue3-vite/src/types.ts @@ -1,11 +1,20 @@ +import type { BuilderOptions, StorybookConfigVite } from '@storybook/builder-vite'; import type { StorybookConfig as StorybookConfigBase } from '@storybook/types'; -import type { StorybookConfigVite, BuilderOptions } from '@storybook/builder-vite'; type FrameworkName = '@storybook/vue3-vite'; type BuilderName = '@storybook/builder-vite'; export type FrameworkOptions = { builder?: BuilderOptions; + /** + * Plugin to use for generation docs for component props, events, slots and exposes. + * Since Storybook 8, the official vue plugin "vue-component-meta" (Volar) can be used which supports + * more complex types, better type docs, support for js(x)/ts(x) components and more. + * + * "vue-component-meta" will become the new default in the future and "vue-docgen-api" will be removed. + * @default "vue-docgen-api" + */ + docgen?: 'vue-docgen-api' | 'vue-component-meta'; }; type StorybookConfigFramework = { diff --git a/code/renderers/vue3/src/docs/__snapshots__/extractArgTypes.test.ts.snap b/code/renderers/vue3/src/docs/__snapshots__/extractArgTypes.test.ts.snap new file mode 100644 index 000000000000..b4a5c410991a --- /dev/null +++ b/code/renderers/vue3/src/docs/__snapshots__/extractArgTypes.test.ts.snap @@ -0,0 +1,277 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`extractArgTypes > should extract events for Vue component 1`] = ` +{ + "bar": { + "control": { + "disabled": false, + }, + "defaultValue": { + "summary": undefined, + }, + "description": "", + "name": "bar", + "table": { + "category": "props", + "defaultValue": { + "summary": undefined, + }, + "jsDocTags": [], + "type": { + "summary": "[value: { year: number; title?: any; }]", + }, + }, + "type": { + "name": [ + { + "kind": "object", + "schema": { + "title": { + "declarations": [ + { + "file": "/storybook/sandbox/vue3-vite-default-ts/src/stories/renderers/vue3/component-meta/reference-type-events/component.vue", + "range": [ + 269, + 280, + ], + }, + ], + "description": "", + "global": false, + "name": "title", + "required": false, + "schema": "any", + "tags": [], + "type": "any", + }, + "year": { + "declarations": [ + { + "file": "/storybook/sandbox/vue3-vite-default-ts/src/stories/renderers/vue3/component-meta/reference-type-events/component.vue", + "range": [ + 255, + 268, + ], + }, + ], + "description": "", + "global": false, + "name": "year", + "required": true, + "schema": "number", + "tags": [], + "type": "number", + }, + }, + "type": "{ year: number; title?: any; }", + }, + ], + "required": false, + }, + }, + "baz": { + "control": { + "disabled": false, + }, + "defaultValue": { + "summary": undefined, + }, + "description": "", + "name": "baz", + "table": { + "category": "props", + "defaultValue": { + "summary": undefined, + }, + "jsDocTags": [], + "type": { + "summary": "[]", + }, + }, + "type": { + "name": [], + "required": false, + }, + }, + "foo": { + "control": { + "disabled": false, + }, + "defaultValue": { + "summary": undefined, + }, + "description": "", + "name": "foo", + "table": { + "category": "props", + "defaultValue": { + "summary": undefined, + }, + "jsDocTags": [], + "type": { + "summary": "[data?: { foo: string; }]", + }, + }, + "type": { + "name": [ + { + "kind": "enum", + "schema": [ + "undefined", + { + "kind": "object", + "schema": { + "foo": { + "declarations": [ + { + "file": "/storybook/sandbox/vue3-vite-default-ts/src/stories/renderers/vue3/component-meta/reference-type-events/component.vue", + "range": [ + 207, + 218, + ], + }, + ], + "description": "", + "global": false, + "name": "foo", + "required": true, + "schema": "string", + "tags": [], + "type": "string", + }, + }, + "type": "{ foo: string; }", + }, + ], + "type": "{ foo: string; } | undefined", + }, + ], + "required": false, + }, + }, +} +`; + +exports[`extractArgTypes > should extract slots type for Vue component 1`] = ` +{ + "default": { + "control": { + "disabled": false, + }, + "defaultValue": { + "summary": undefined, + }, + "description": "", + "name": "default", + "table": { + "category": "props", + "defaultValue": { + "summary": undefined, + }, + "jsDocTags": [], + "type": { + "summary": "{ num: number; }", + }, + }, + "type": { + "name": "object", + "required": false, + "value": { + "num": { + "name": "number", + "required": true, + }, + }, + }, + }, + "named": { + "control": { + "disabled": false, + }, + "defaultValue": { + "summary": undefined, + }, + "description": "", + "name": "named", + "table": { + "category": "props", + "defaultValue": { + "summary": undefined, + }, + "jsDocTags": [], + "type": { + "summary": "{ str: string; }", + }, + }, + "type": { + "name": "object", + "required": false, + "value": { + "str": { + "name": "string", + "required": true, + }, + }, + }, + }, + "no-bind": { + "control": { + "disabled": false, + }, + "defaultValue": { + "summary": undefined, + }, + "description": "", + "name": "no-bind", + "table": { + "category": "props", + "defaultValue": { + "summary": undefined, + }, + "jsDocTags": [], + "type": { + "summary": "{}", + }, + }, + "type": { + "name": "object", + "required": false, + "value": {}, + }, + }, + "vbind": { + "control": { + "disabled": false, + }, + "defaultValue": { + "summary": undefined, + }, + "description": "", + "name": "vbind", + "table": { + "category": "props", + "defaultValue": { + "summary": undefined, + }, + "jsDocTags": [], + "type": { + "summary": "{ num: number; str: string; }", + }, + }, + "type": { + "name": "object", + "required": false, + "value": { + "num": { + "name": "number", + "required": true, + }, + "str": { + "name": "string", + "required": true, + }, + }, + }, + }, +} +`; diff --git a/code/renderers/vue3/src/docs/extractArgTypes.test.ts b/code/renderers/vue3/src/docs/extractArgTypes.test.ts new file mode 100644 index 000000000000..2c978af54dd0 --- /dev/null +++ b/code/renderers/vue3/src/docs/extractArgTypes.test.ts @@ -0,0 +1,540 @@ +import { extractComponentProps, hasDocgen } from '@storybook/docs-tools'; +import type { Mock } from 'vitest'; +import { beforeEach, describe, expect, it, vi, vitest } from 'vitest'; +import { extractArgTypes } from './extractArgTypes'; +import { + mockExtractComponentEventsReturn, + mockExtractComponentPropsReturn, + mockExtractComponentSlotsReturn, + referenceTypeEvents, + referenceTypeProps, + templateSlots, +} from './tests-meta-components/meta-components'; + +vitest.mock('@storybook/docs-tools'); + +describe('extractArgTypes', () => { + beforeEach(() => { + vi.resetAllMocks(); + }); + + it('should return null if component does not contain docs', () => { + (hasDocgen as Mock).mockReturnValueOnce(false); + (extractComponentProps as Mock).mockReturnValueOnce([] as any); + + expect(extractArgTypes({} as any)).toBeNull(); + }); + + it('should extract arg types for component', () => { + const component = referenceTypeProps; + (hasDocgen as Mock).mockReturnValueOnce(true); + (extractComponentProps as Mock).mockReturnValue(mockExtractComponentPropsReturn); + + const argTypes = extractArgTypes(component); + + expect(argTypes).toMatchInlineSnapshot(` + { + "array": { + "control": { + "disabled": false, + }, + "defaultValue": { + "summary": undefined, + }, + "description": "description required array object", + "name": "array", + "table": { + "category": "props", + "defaultValue": { + "summary": undefined, + }, + "jsDocTags": [], + "type": { + "summary": "MyNestedProps[]", + }, + }, + "type": { + "name": "array", + "required": true, + "value": { + "name": "object", + "required": false, + "value": { + "nestedProp": { + "name": "string", + "required": true, + }, + }, + }, + }, + }, + "arrayOptional": { + "control": { + "disabled": false, + }, + "defaultValue": { + "summary": undefined, + }, + "description": "description optional array object", + "name": "arrayOptional", + "table": { + "category": "props", + "defaultValue": { + "summary": undefined, + }, + "jsDocTags": [], + "type": { + "summary": "MyNestedProps[]", + }, + }, + "type": { + "name": "array", + "required": false, + "value": { + "name": "object", + "required": false, + "value": { + "nestedProp": { + "name": "string", + "required": true, + }, + }, + }, + }, + }, + "bar": { + "control": { + "disabled": false, + }, + "defaultValue": { + "summary": "1", + }, + "description": "description bar is optional number", + "name": "bar", + "table": { + "category": "props", + "defaultValue": { + "summary": "1", + }, + "jsDocTags": [], + "type": { + "summary": "number", + }, + }, + "type": { + "name": "number", + "required": false, + }, + }, + "baz": { + "control": { + "disabled": false, + }, + "defaultValue": { + "summary": undefined, + }, + "description": "description baz is required boolean", + "name": "baz", + "table": { + "category": "props", + "defaultValue": { + "summary": undefined, + }, + "jsDocTags": [], + "type": { + "summary": "boolean", + }, + }, + "type": { + "name": "boolean", + "required": true, + }, + }, + "enumValue": { + "control": { + "disabled": false, + }, + "defaultValue": { + "summary": undefined, + }, + "description": "description enum value", + "name": "enumValue", + "table": { + "category": "props", + "defaultValue": { + "summary": undefined, + }, + "jsDocTags": [], + "type": { + "summary": "MyEnum", + }, + }, + "type": { + "name": "enum", + "required": true, + "value": [ + "MyEnum.Small", + "MyEnum.Medium", + "MyEnum.Large", + ], + }, + }, + "foo": { + "control": { + "disabled": false, + }, + "defaultValue": { + "summary": undefined, + }, + "description": "@default: "rounded"
@since: v1.0.0
@see: https://vuejs.org/
@deprecated: v1.1.0

string foo", + "name": "foo", + "table": { + "category": "props", + "defaultValue": { + "summary": undefined, + }, + "jsDocTags": [ + { + "name": "default", + "text": ""rounded"", + }, + { + "name": "since", + "text": "v1.0.0", + }, + { + "name": "see", + "text": "https://vuejs.org/", + }, + { + "name": "deprecated", + "text": "v1.1.0", + }, + ], + "type": { + "summary": "string", + }, + }, + "type": { + "name": "string", + "required": true, + }, + }, + "inlined": { + "control": { + "disabled": false, + }, + "defaultValue": { + "summary": undefined, + }, + "description": "", + "name": "inlined", + "table": { + "category": "props", + "defaultValue": { + "summary": undefined, + }, + "jsDocTags": [], + "type": { + "summary": "{ foo: string; }", + }, + }, + "type": { + "name": "object", + "required": true, + "value": { + "foo": { + "name": "string", + "required": true, + }, + }, + }, + }, + "literalFromContext": { + "control": { + "disabled": false, + }, + "defaultValue": { + "summary": undefined, + }, + "description": "description literal type alias that require context", + "name": "literalFromContext", + "table": { + "category": "props", + "defaultValue": { + "summary": undefined, + }, + "jsDocTags": [], + "type": { + "summary": ""Uncategorized" | "Content" | "Interaction" | "Display" | "Forms" | "Addons"", + }, + }, + "type": { + "name": "enum", + "required": true, + "value": [ + "Uncategorized", + "Content", + "Interaction", + "Display", + "Forms", + "Addons", + ], + }, + }, + "nested": { + "control": { + "disabled": false, + }, + "defaultValue": { + "summary": undefined, + }, + "description": "description nested is required nested object", + "name": "nested", + "table": { + "category": "props", + "defaultValue": { + "summary": undefined, + }, + "jsDocTags": [], + "type": { + "summary": "MyNestedProps", + }, + }, + "type": { + "name": "object", + "required": true, + "value": { + "nestedProp": { + "name": "string", + "required": true, + }, + }, + }, + }, + "nestedIntersection": { + "control": { + "disabled": false, + }, + "defaultValue": { + "summary": undefined, + }, + "description": "description required nested object with intersection", + "name": "nestedIntersection", + "table": { + "category": "props", + "defaultValue": { + "summary": undefined, + }, + "jsDocTags": [], + "type": { + "summary": "MyNestedProps & { additionalProp: string; }", + }, + }, + "type": { + "name": "object", + "required": true, + "value": { + "additionalProp": { + "name": "string", + "required": true, + }, + "nestedProp": { + "name": "string", + "required": true, + }, + }, + }, + }, + "nestedOptional": { + "control": { + "disabled": false, + }, + "defaultValue": { + "summary": undefined, + }, + "description": "description optional nested object", + "name": "nestedOptional", + "table": { + "category": "props", + "defaultValue": { + "summary": undefined, + }, + "jsDocTags": [], + "type": { + "summary": "MyNestedProps | MyIgnoredNestedProps", + }, + }, + "type": { + "name": { + "kind": "enum", + "schema": [ + "undefined", + { + "kind": "object", + "schema": { + "nestedProp": { + "declarations": [], + "description": "nested prop documentation", + "global": false, + "name": "nestedProp", + "required": true, + "schema": "string", + "tags": [], + "type": "string", + }, + }, + "type": "MyNestedProps", + }, + { + "kind": "object", + "schema": { + "nestedProp": { + "declarations": [], + "description": "", + "global": false, + "name": "nestedProp", + "required": true, + "schema": "string", + "tags": [], + "type": "string", + }, + }, + "type": "MyIgnoredNestedProps", + }, + ], + "type": "MyNestedProps | MyIgnoredNestedProps | undefined", + }, + "required": false, + }, + }, + "recursive": { + "control": { + "disabled": false, + }, + "defaultValue": { + "summary": undefined, + }, + "description": "", + "name": "recursive", + "table": { + "category": "props", + "defaultValue": { + "summary": undefined, + }, + "jsDocTags": [], + "type": { + "summary": "MyNestedRecursiveProps", + }, + }, + "type": { + "name": "object", + "required": false, + "value": { + "recursive": { + "name": "MyNestedRecursiveProps", + "required": true, + }, + }, + }, + }, + "stringArray": { + "control": { + "disabled": false, + }, + "defaultValue": { + "summary": "["foo", "bar"]", + }, + "description": "description stringArray is string array", + "name": "stringArray", + "table": { + "category": "props", + "defaultValue": { + "summary": "["foo", "bar"]", + }, + "jsDocTags": [], + "type": { + "summary": "string[]", + }, + }, + "type": { + "name": "array", + "required": false, + "value": { + "name": "string", + "required": false, + }, + }, + }, + "union": { + "control": { + "disabled": false, + }, + "defaultValue": { + "summary": undefined, + }, + "description": "description union is required union type", + "name": "union", + "table": { + "category": "props", + "defaultValue": { + "summary": undefined, + }, + "jsDocTags": [], + "type": { + "summary": "string | number", + }, + }, + "type": { + "name": "string", + "required": true, + }, + }, + "unionOptional": { + "control": { + "disabled": false, + }, + "defaultValue": { + "summary": undefined, + }, + "description": "description unionOptional is optional union type", + "name": "unionOptional", + "table": { + "category": "props", + "defaultValue": { + "summary": undefined, + }, + "jsDocTags": [], + "type": { + "summary": "string | number | boolean", + }, + }, + "type": { + "name": "string", + "required": false, + }, + }, + } + `); + }); + + it('should extract events for Vue component', () => { + const component = referenceTypeEvents; + (hasDocgen as Mock).mockReturnValueOnce(true); + (extractComponentProps as Mock).mockReturnValue(mockExtractComponentEventsReturn); + + const argTypes = extractArgTypes(component); + + expect(argTypes).toMatchSnapshot(); + }); + + it('should extract slots type for Vue component', () => { + const component = templateSlots; + (hasDocgen as Mock).mockReturnValueOnce(true); + (extractComponentProps as Mock).mockReturnValue(mockExtractComponentSlotsReturn); + + const argTypes = extractArgTypes(component); + + expect(argTypes).toMatchSnapshot(); + }); +}); diff --git a/code/renderers/vue3/src/docs/extractArgTypes.ts b/code/renderers/vue3/src/docs/extractArgTypes.ts index 8c8b5f221638..5a535d40599c 100644 --- a/code/renderers/vue3/src/docs/extractArgTypes.ts +++ b/code/renderers/vue3/src/docs/extractArgTypes.ts @@ -1,32 +1,144 @@ -import type { StrictArgTypes } from '@storybook/types'; -import type { ArgTypesExtractor } from '@storybook/docs-tools'; -import { hasDocgen, extractComponentProps, convert } from '@storybook/docs-tools'; +import type { SBType, StrictArgTypes } from '@storybook/types'; -const SECTIONS = ['props', 'events', 'slots', 'methods']; +import { + extractComponentProps, + convert as genericConvert, + hasDocgen, + type ArgTypesExtractor, + type DocgenInfo, +} from '@storybook/docs-tools'; + +type Schema = { kind: string; schema: [] | object; type?: string } | string; +type MetaDocgenInfo = DocgenInfo & { + type: string | { name: string; value: string[] }; + default: string; + global: boolean; + name: string; + schema?: Schema; + tags?: { name: string; text: string }[]; +}; + +// "exposed" is used by the vue-component-meta plugin while "expose" is used by vue-docgen-api +const ARG_TYPE_SECTIONS = ['props', 'events', 'slots', 'exposed', 'expose'] as const; export const extractArgTypes: ArgTypesExtractor = (component) => { if (!hasDocgen(component)) { return null; } - const results: StrictArgTypes = {}; - SECTIONS.forEach((section) => { + + const argTypes: StrictArgTypes = {}; + + ARG_TYPE_SECTIONS.forEach((section) => { const props = extractComponentProps(component, section); - props.forEach(({ propDef, docgenInfo, jsDocTags }) => { - const { name, type, description, defaultValue: defaultSummary, required } = propDef; - const sbType = section === 'props' ? convert(docgenInfo) : { name: 'void' }; - - results[name] = { - name, - description, - type: { required, ...sbType }, + + props.forEach((extractedProp) => { + const docgenInfo = extractedProp.docgenInfo as MetaDocgenInfo; + + if (argTypes[docgenInfo.name] || docgenInfo.global) { + return; // skip duplicate and global props + } + + const type = + typeof docgenInfo.type === 'string' ? docgenInfo.type : docgenInfo.type?.name ?? ''; + const sbType = section === 'props' ? convertPropType(docgenInfo) : ({ name: type } as SBType); + + const defaultValue = { summary: docgenInfo.default }; + + argTypes[docgenInfo.name] = { + name: docgenInfo.name, + description: formatDescriptionWithTags(docgenInfo.description, docgenInfo.tags), + defaultValue, + type: sbType, table: { - type, - jsDocTags, - defaultValue: defaultSummary, + type: { summary: type.replace(' | undefined', '') }, + jsDocTags: docgenInfo.tags ?? [], + defaultValue, category: section, }, + control: { disabled: !['props', 'slots'].includes(section) }, }; }); }); - return results; + + return argTypes; +}; + +/** + * Converts the given prop type into a SBType so it can be correctly displayed in the UI (controls etc.). + */ +export const convertPropType = (propInfo: MetaDocgenInfo): SBType => { + const schema = propInfo.schema; + const required = propInfo.required ?? false; + const fallbackSbType = { name: schema, required } as SBType; + + if (!schema) return genericConvert(propInfo) ?? fallbackSbType; + if (typeof schema === 'string') return fallbackSbType; + + // convert enum schemas (e.g. union or enum type to corresponding SBType) + // so the enum values can be selected via radio/dropdown in the UI + if (schema.kind === 'enum' && Array.isArray(schema.schema)) { + // filter out empty or "undefined" for optional props + const definedValues = schema.schema.filter((item) => item != null && item !== 'undefined'); + + if (definedValues.length === 1 && typeof definedValues[0] === 'object') { + return convertPropType({ schema: definedValues[0] } as MetaDocgenInfo); + } + + const values = definedValues + .filter((item: Schema) => typeof item === 'string') + .map((item: Schema) => (typeof item !== 'string' ? item.schema.toString() : item)) + .map((item: string) => item.replace(/'/g, '"')); + + if (values.length === 0) return fallbackSbType; + + const isBoolean = values.length === 2 && values.includes('true') && values.includes('false'); + if (isBoolean) return { name: 'boolean', required }; + + const isLateralUnion = + values.length > 1 && values.every((item) => item.startsWith('"') && item.endsWith('"')); + const isEnum = + !isLateralUnion && + values.length > 1 && + values.every((item) => typeof item === 'string' && item.includes('.')); + + if (isLateralUnion || isEnum) { + const valuesWithoutQuotes = values.map((item: string) => item.replace(/"/g, '')); + return { name: 'enum', value: valuesWithoutQuotes, required }; + } + + return { name: values[0], required } as SBType; + } + + // recursively convert object properties to SBType + if (schema.kind === 'object' && typeof schema.schema === 'object') { + const schemaObject = schema.schema as Record; + + return { + name: 'object', + required, + value: Object.entries(schemaObject).reduce>((obj, [key, value]) => { + obj[key] = convertPropType(value); + return obj; + }, {}), + }; + } + + if (schema.kind === 'array' && Array.isArray(schema.schema)) { + return { + name: 'array', + value: convertPropType({ schema: schema.schema[0] } as MetaDocgenInfo), + required, + }; + } + + return fallbackSbType; +}; + +/** + * Adds the descriptions for the given tags if available. + */ +const formatDescriptionWithTags = (description: string, tags: MetaDocgenInfo['tags']): string => { + if (!tags?.length || !description) return description ?? ''; + const tagDescriptions = tags.map((tag) => `@${tag.name}: ${tag.text}`).join('
'); + return `${tagDescriptions}

${description}`; }; diff --git a/code/renderers/vue3/src/docs/sourceDecorator.ts b/code/renderers/vue3/src/docs/sourceDecorator.ts index 52303c553427..797e7a648d9a 100644 --- a/code/renderers/vue3/src/docs/sourceDecorator.ts +++ b/code/renderers/vue3/src/docs/sourceDecorator.ts @@ -166,7 +166,6 @@ function getTemplateComponents( if (!template) return [h(story, context?.args)]; return getComponents(template); } catch (e) { - console.log('error', e); return []; } } diff --git a/code/renderers/vue3/src/docs/tests-meta-components/meta-components.ts b/code/renderers/vue3/src/docs/tests-meta-components/meta-components.ts new file mode 100644 index 000000000000..085b59a1e9ae --- /dev/null +++ b/code/renderers/vue3/src/docs/tests-meta-components/meta-components.ts @@ -0,0 +1,2488 @@ +export const referenceTypeProps = { + __name: 'component', + __docgenInfo: { + exportName: 'default', + displayName: 'component', + type: 1, + props: [ + { + name: 'bar', + global: false, + description: 'description bar is optional number', + tags: [], + required: false, + type: 'number | undefined', + declarations: [], + schema: { + kind: 'enum', + type: 'number | undefined', + schema: ['undefined', 'number'], + }, + default: '1', + }, + { + name: 'stringArray', + global: false, + description: 'description stringArray is string array', + tags: [], + required: false, + type: 'string[] | undefined', + declarations: [], + schema: { + kind: 'enum', + type: 'string[] | undefined', + schema: [ + 'undefined', + { + kind: 'array', + type: 'string[]', + schema: ['string'], + }, + ], + }, + default: '["foo", "bar"]', + }, + { + name: 'key', + global: true, + description: '', + tags: [], + required: false, + type: 'string | number | symbol | undefined', + declarations: [], + schema: { + kind: 'enum', + type: 'string | number | symbol | undefined', + schema: ['undefined', 'string', 'number', 'symbol'], + }, + }, + { + name: 'ref', + global: true, + description: '', + tags: [], + required: false, + type: 'VNodeRef | undefined', + declarations: [], + schema: { + kind: 'enum', + type: 'VNodeRef | undefined', + schema: [ + 'undefined', + 'string', + 'Ref', + { + kind: 'event', + type: '(ref: Element | ComponentPublicInstance<{}, {}, {}, {}, {}, {}, {}, {}, false, ComponentOptionsBase, {}, {}> | null, refs: Record<...>): void', + schema: [], + }, + ], + }, + }, + { + name: 'ref_for', + global: true, + description: '', + tags: [], + required: false, + type: 'boolean | undefined', + declarations: [], + schema: { + kind: 'enum', + type: 'boolean | undefined', + schema: ['undefined', 'false', 'true'], + }, + }, + { + name: 'ref_key', + global: true, + description: '', + tags: [], + required: false, + type: 'string | undefined', + declarations: [], + schema: { + kind: 'enum', + type: 'string | undefined', + schema: ['undefined', 'string'], + }, + }, + { + name: 'class', + global: true, + description: '', + tags: [], + required: false, + type: 'unknown', + declarations: [], + schema: 'unknown', + }, + { + name: 'style', + global: true, + description: '', + tags: [], + required: false, + type: 'unknown', + declarations: [], + schema: 'unknown', + }, + { + name: 'foo', + global: false, + description: 'string foo', + tags: [ + { + name: 'default', + text: '"rounded"', + }, + { + name: 'since', + text: 'v1.0.0', + }, + { + name: 'see', + text: 'https://vuejs.org/', + }, + { + name: 'deprecated', + text: 'v1.1.0', + }, + ], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + { + name: 'baz', + global: false, + description: 'description baz is required boolean', + tags: [], + required: true, + type: 'boolean', + declarations: [], + schema: { + kind: 'enum', + type: 'boolean', + schema: ['false', 'true'], + }, + }, + { + name: 'union', + global: false, + description: 'description union is required union type', + tags: [], + required: true, + type: 'string | number', + declarations: [], + schema: { + kind: 'enum', + type: 'string | number', + schema: ['string', 'number'], + }, + }, + { + name: 'unionOptional', + global: false, + description: 'description unionOptional is optional union type', + tags: [], + required: false, + type: 'string | number | boolean | undefined', + declarations: [], + schema: { + kind: 'enum', + type: 'string | number | boolean | undefined', + schema: ['undefined', 'string', 'number', 'false', 'true'], + }, + }, + { + name: 'nested', + global: false, + description: 'description nested is required nested object', + tags: [], + required: true, + type: 'MyNestedProps', + declarations: [], + schema: { + kind: 'object', + type: 'MyNestedProps', + schema: { + nestedProp: { + name: 'nestedProp', + global: false, + description: 'nested prop documentation', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + }, + { + name: 'nestedIntersection', + global: false, + description: 'description required nested object with intersection', + tags: [], + required: true, + type: 'MyNestedProps & { additionalProp: string; }', + declarations: [], + schema: { + kind: 'object', + type: 'MyNestedProps & { additionalProp: string; }', + schema: { + nestedProp: { + name: 'nestedProp', + global: false, + description: 'nested prop documentation', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + additionalProp: { + name: 'additionalProp', + global: false, + description: 'description required additional property', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + }, + { + name: 'nestedOptional', + global: false, + description: 'description optional nested object', + tags: [], + required: false, + type: 'MyNestedProps | MyIgnoredNestedProps | undefined', + declarations: [], + schema: { + kind: 'enum', + type: 'MyNestedProps | MyIgnoredNestedProps | undefined', + schema: [ + 'undefined', + { + kind: 'object', + type: 'MyNestedProps', + schema: { + nestedProp: { + name: 'nestedProp', + global: false, + description: 'nested prop documentation', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + { + kind: 'object', + type: 'MyIgnoredNestedProps', + schema: { + nestedProp: { + name: 'nestedProp', + global: false, + description: '', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + ], + }, + }, + { + name: 'array', + global: false, + description: 'description required array object', + tags: [], + required: true, + type: 'MyNestedProps[]', + declarations: [], + schema: { + kind: 'array', + type: 'MyNestedProps[]', + schema: [ + { + kind: 'object', + type: 'MyNestedProps', + schema: { + nestedProp: { + name: 'nestedProp', + global: false, + description: 'nested prop documentation', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + ], + }, + }, + { + name: 'arrayOptional', + global: false, + description: 'description optional array object', + tags: [], + required: false, + type: 'MyNestedProps[] | undefined', + declarations: [], + schema: { + kind: 'enum', + type: 'MyNestedProps[] | undefined', + schema: [ + 'undefined', + { + kind: 'array', + type: 'MyNestedProps[]', + schema: [ + { + kind: 'object', + type: 'MyNestedProps', + schema: { + nestedProp: { + name: 'nestedProp', + global: false, + description: 'nested prop documentation', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + ], + }, + ], + }, + }, + { + name: 'enumValue', + global: false, + description: 'description enum value', + tags: [], + required: true, + type: 'MyEnum', + declarations: [], + schema: { + kind: 'enum', + type: 'MyEnum', + schema: ['MyEnum.Small', 'MyEnum.Medium', 'MyEnum.Large'], + }, + }, + { + name: 'literalFromContext', + global: false, + description: 'description literal type alias that require context', + tags: [], + required: true, + type: '"Uncategorized" | "Content" | "Interaction" | "Display" | "Forms" | "Addons"', + declarations: [], + schema: { + kind: 'enum', + type: '"Uncategorized" | "Content" | "Interaction" | "Display" | "Forms" | "Addons"', + schema: [ + '"Uncategorized"', + '"Content"', + '"Interaction"', + '"Display"', + '"Forms"', + '"Addons"', + ], + }, + }, + { + name: 'inlined', + global: false, + description: '', + tags: [], + required: true, + type: '{ foo: string; }', + declarations: [], + schema: { + kind: 'object', + type: '{ foo: string; }', + schema: { + foo: { + name: 'foo', + global: false, + description: '', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + }, + { + name: 'recursive', + global: false, + description: '', + tags: [], + required: false, + type: 'MyNestedRecursiveProps | undefined', + declarations: [], + schema: { + kind: 'enum', + type: 'MyNestedRecursiveProps | undefined', + schema: [ + 'undefined', + { + kind: 'object', + type: 'MyNestedRecursiveProps', + schema: { + recursive: { + name: 'recursive', + global: false, + description: '', + tags: [], + required: true, + type: 'MyNestedRecursiveProps', + declarations: [], + schema: 'MyNestedRecursiveProps', + }, + }, + }, + ], + }, + }, + ], + events: [], + slots: [], + exposed: [ + { + name: 'foo', + type: 'string', + description: 'string foo', + declarations: [], + schema: 'string', + }, + { + name: 'bar', + type: 'number', + description: 'description bar is optional number', + declarations: [], + schema: 'number', + }, + { + name: 'baz', + type: 'boolean', + description: 'description baz is required boolean', + declarations: [], + schema: { + kind: 'enum', + type: 'boolean', + schema: ['false', 'true'], + }, + }, + { + name: 'stringArray', + type: 'string[]', + description: 'description stringArray is string array', + declarations: [], + schema: { + kind: 'array', + type: 'string[]', + schema: ['string'], + }, + }, + { + name: 'union', + type: 'string | number', + description: 'description union is required union type', + declarations: [], + schema: { + kind: 'enum', + type: 'string | number', + schema: ['string', 'number'], + }, + }, + { + name: 'unionOptional', + type: 'string | number | boolean | undefined', + description: 'description unionOptional is optional union type', + declarations: [], + schema: { + kind: 'enum', + type: 'string | number | boolean | undefined', + schema: ['undefined', 'string', 'number', 'false', 'true'], + }, + }, + { + name: 'nested', + type: 'MyNestedProps', + description: 'description nested is required nested object', + declarations: [], + schema: { + kind: 'object', + type: 'MyNestedProps', + schema: { + nestedProp: { + name: 'nestedProp', + global: false, + description: 'nested prop documentation', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + }, + { + name: 'nestedIntersection', + type: 'MyNestedProps & { additionalProp: string; }', + description: 'description required nested object with intersection', + declarations: [], + schema: { + kind: 'object', + type: 'MyNestedProps & { additionalProp: string; }', + schema: { + nestedProp: { + name: 'nestedProp', + global: false, + description: 'nested prop documentation', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + additionalProp: { + name: 'additionalProp', + global: false, + description: 'description required additional property', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + }, + { + name: 'nestedOptional', + type: 'MyNestedProps | MyIgnoredNestedProps | undefined', + description: 'description optional nested object', + declarations: [], + schema: { + kind: 'enum', + type: 'MyNestedProps | MyIgnoredNestedProps | undefined', + schema: [ + 'undefined', + { + kind: 'object', + type: 'MyNestedProps', + schema: { + nestedProp: { + name: 'nestedProp', + global: false, + description: 'nested prop documentation', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + { + kind: 'object', + type: 'MyIgnoredNestedProps', + schema: { + nestedProp: { + name: 'nestedProp', + global: false, + description: '', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + ], + }, + }, + { + name: 'array', + type: 'MyNestedProps[]', + description: 'description required array object', + declarations: [], + schema: { + kind: 'array', + type: 'MyNestedProps[]', + schema: [ + { + kind: 'object', + type: 'MyNestedProps', + schema: { + nestedProp: { + name: 'nestedProp', + global: false, + description: 'nested prop documentation', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + ], + }, + }, + { + name: 'arrayOptional', + type: 'MyNestedProps[] | undefined', + description: 'description optional array object', + declarations: [], + schema: { + kind: 'enum', + type: 'MyNestedProps[] | undefined', + schema: [ + 'undefined', + { + kind: 'array', + type: 'MyNestedProps[]', + schema: [ + { + kind: 'object', + type: 'MyNestedProps', + schema: { + nestedProp: { + name: 'nestedProp', + global: false, + description: 'nested prop documentation', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + ], + }, + ], + }, + }, + { + name: 'enumValue', + type: 'MyEnum', + description: 'description enum value', + declarations: [], + schema: { + kind: 'enum', + type: 'MyEnum', + schema: ['MyEnum.Small', 'MyEnum.Medium', 'MyEnum.Large'], + }, + }, + { + name: 'literalFromContext', + type: '"Uncategorized" | "Content" | "Interaction" | "Display" | "Forms" | "Addons"', + description: 'description literal type alias that require context', + declarations: [], + schema: { + kind: 'enum', + type: '"Uncategorized" | "Content" | "Interaction" | "Display" | "Forms" | "Addons"', + schema: [ + '"Uncategorized"', + '"Content"', + '"Interaction"', + '"Display"', + '"Forms"', + '"Addons"', + ], + }, + }, + { + name: 'inlined', + type: '{ foo: string; }', + description: '', + declarations: [], + schema: { + kind: 'object', + type: '{ foo: string; }', + schema: { + foo: { + name: 'foo', + global: false, + description: '', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + }, + { + name: 'recursive', + type: 'MyNestedRecursiveProps | undefined', + description: '', + declarations: [], + schema: { + kind: 'enum', + type: 'MyNestedRecursiveProps | undefined', + schema: [ + 'undefined', + { + kind: 'object', + type: 'MyNestedRecursiveProps', + schema: { + recursive: { + name: 'recursive', + global: false, + description: '', + tags: [], + required: true, + type: 'MyNestedRecursiveProps', + declarations: [], + schema: 'MyNestedRecursiveProps', + }, + }, + }, + ], + }, + }, + ], + sourceFiles: + '/storybook/sandbox/vue3-vite-default-ts/src/stories/renderers/vue3_vue3-vite-default-ts/component-meta/reference-type-props/component.vue', + }, +}; + +export const mockExtractComponentPropsReturn = [ + { + propDef: { + name: 'bar', + type: {}, + required: false, + description: 'description bar is optional number', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'bar', + global: false, + description: 'description bar is optional number', + tags: [], + required: false, + type: 'number | undefined', + declarations: [], + schema: { + kind: 'enum', + type: 'number | undefined', + schema: ['undefined', 'number'], + }, + default: '1', + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'stringArray', + type: {}, + required: false, + description: 'description stringArray is string array', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'stringArray', + global: false, + description: 'description stringArray is string array', + tags: [], + required: false, + type: 'string[] | undefined', + declarations: [], + schema: { + kind: 'enum', + type: 'string[] | undefined', + schema: [ + 'undefined', + { + kind: 'array', + type: 'string[]', + schema: ['string'], + }, + ], + }, + default: '["foo", "bar"]', + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'key', + type: {}, + required: false, + description: '', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'key', + global: true, + description: '', + tags: [], + required: false, + type: 'string | number | symbol | undefined', + declarations: [], + schema: { + kind: 'enum', + type: 'string | number | symbol | undefined', + schema: ['undefined', 'string', 'number', 'symbol'], + }, + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'ref', + type: {}, + required: false, + description: '', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'ref', + global: true, + description: '', + tags: [], + required: false, + type: 'VNodeRef | undefined', + declarations: [], + schema: { + kind: 'enum', + type: 'VNodeRef | undefined', + schema: [ + 'undefined', + 'string', + 'Ref', + { + kind: 'event', + type: '(ref: Element | ComponentPublicInstance<{}, {}, {}, {}, {}, {}, {}, {}, false, ComponentOptionsBase, {}, {}> | null, refs: Record<...>): void', + schema: [], + }, + ], + }, + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'ref_for', + type: {}, + required: false, + description: '', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'ref_for', + global: true, + description: '', + tags: [], + required: false, + type: 'boolean | undefined', + declarations: [], + schema: { + kind: 'enum', + type: 'boolean | undefined', + schema: ['undefined', 'false', 'true'], + }, + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'ref_key', + type: {}, + required: false, + description: '', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'ref_key', + global: true, + description: '', + tags: [], + required: false, + type: 'string | undefined', + declarations: [], + schema: { + kind: 'enum', + type: 'string | undefined', + schema: ['undefined', 'string'], + }, + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'class', + type: {}, + required: false, + description: '', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'class', + global: true, + description: '', + tags: [], + required: false, + type: 'unknown', + declarations: [], + schema: 'unknown', + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'style', + type: {}, + required: false, + description: '', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'style', + global: true, + description: '', + tags: [], + required: false, + type: 'unknown', + declarations: [], + schema: 'unknown', + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'foo', + type: {}, + required: true, + description: 'string foo', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'foo', + global: false, + description: 'string foo', + tags: [ + { + name: 'default', + text: '"rounded"', + }, + { + name: 'since', + text: 'v1.0.0', + }, + { + name: 'see', + text: 'https://vuejs.org/', + }, + { + name: 'deprecated', + text: 'v1.1.0', + }, + ], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'baz', + type: {}, + required: true, + description: 'description baz is required boolean', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'baz', + global: false, + description: 'description baz is required boolean', + tags: [], + required: true, + type: 'boolean', + declarations: [], + schema: { + kind: 'enum', + type: 'boolean', + schema: ['false', 'true'], + }, + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'union', + type: {}, + required: true, + description: 'description union is required union type', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'union', + global: false, + description: 'description union is required union type', + tags: [], + required: true, + type: 'string | number', + declarations: [], + schema: { + kind: 'enum', + type: 'string | number', + schema: ['string', 'number'], + }, + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'unionOptional', + type: {}, + required: false, + description: 'description unionOptional is optional union type', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'unionOptional', + global: false, + description: 'description unionOptional is optional union type', + tags: [], + required: false, + type: 'string | number | boolean | undefined', + declarations: [], + schema: { + kind: 'enum', + type: 'string | number | boolean | undefined', + schema: ['undefined', 'string', 'number', 'false', 'true'], + }, + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'nested', + type: {}, + required: true, + description: 'description nested is required nested object', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'nested', + global: false, + description: 'description nested is required nested object', + tags: [], + required: true, + type: 'MyNestedProps', + declarations: [], + schema: { + kind: 'object', + type: 'MyNestedProps', + schema: { + nestedProp: { + name: 'nestedProp', + global: false, + description: 'nested prop documentation', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'nestedIntersection', + type: {}, + required: true, + description: 'description required nested object with intersection', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'nestedIntersection', + global: false, + description: 'description required nested object with intersection', + tags: [], + required: true, + type: 'MyNestedProps & { additionalProp: string; }', + declarations: [], + schema: { + kind: 'object', + type: 'MyNestedProps & { additionalProp: string; }', + schema: { + nestedProp: { + name: 'nestedProp', + global: false, + description: 'nested prop documentation', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + additionalProp: { + name: 'additionalProp', + global: false, + description: 'description required additional property', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'nestedOptional', + type: {}, + required: false, + description: 'description optional nested object', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'nestedOptional', + global: false, + description: 'description optional nested object', + tags: [], + required: false, + type: 'MyNestedProps | MyIgnoredNestedProps | undefined', + declarations: [], + schema: { + kind: 'enum', + type: 'MyNestedProps | MyIgnoredNestedProps | undefined', + schema: [ + 'undefined', + { + kind: 'object', + type: 'MyNestedProps', + schema: { + nestedProp: { + name: 'nestedProp', + global: false, + description: 'nested prop documentation', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + { + kind: 'object', + type: 'MyIgnoredNestedProps', + schema: { + nestedProp: { + name: 'nestedProp', + global: false, + description: '', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + ], + }, + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'array', + type: {}, + required: true, + description: 'description required array object', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'array', + global: false, + description: 'description required array object', + tags: [], + required: true, + type: 'MyNestedProps[]', + declarations: [], + schema: { + kind: 'array', + type: 'MyNestedProps[]', + schema: [ + { + kind: 'object', + type: 'MyNestedProps', + schema: { + nestedProp: { + name: 'nestedProp', + global: false, + description: 'nested prop documentation', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + ], + }, + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'arrayOptional', + type: {}, + required: false, + description: 'description optional array object', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'arrayOptional', + global: false, + description: 'description optional array object', + tags: [], + required: false, + type: 'MyNestedProps[] | undefined', + declarations: [], + schema: { + kind: 'enum', + type: 'MyNestedProps[] | undefined', + schema: [ + 'undefined', + { + kind: 'array', + type: 'MyNestedProps[]', + schema: [ + { + kind: 'object', + type: 'MyNestedProps', + schema: { + nestedProp: { + name: 'nestedProp', + global: false, + description: 'nested prop documentation', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + ], + }, + ], + }, + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'enumValue', + type: {}, + required: true, + description: 'description enum value', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'enumValue', + global: false, + description: 'description enum value', + tags: [], + required: true, + type: 'MyEnum', + declarations: [], + schema: { + kind: 'enum', + type: 'MyEnum', + schema: ['MyEnum.Small', 'MyEnum.Medium', 'MyEnum.Large'], + }, + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'literalFromContext', + type: {}, + required: true, + description: 'description literal type alias that require context', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'literalFromContext', + global: false, + description: 'description literal type alias that require context', + tags: [], + required: true, + type: '"Uncategorized" | "Content" | "Interaction" | "Display" | "Forms" | "Addons"', + declarations: [], + schema: { + kind: 'enum', + type: '"Uncategorized" | "Content" | "Interaction" | "Display" | "Forms" | "Addons"', + schema: [ + '"Uncategorized"', + '"Content"', + '"Interaction"', + '"Display"', + '"Forms"', + '"Addons"', + ], + }, + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'inlined', + type: {}, + required: true, + description: '', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'inlined', + global: false, + description: '', + tags: [], + required: true, + type: '{ foo: string; }', + declarations: [], + schema: { + kind: 'object', + type: '{ foo: string; }', + schema: { + foo: { + name: 'foo', + global: false, + description: '', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'recursive', + type: {}, + required: false, + description: '', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'recursive', + global: false, + description: '', + tags: [], + required: false, + type: 'MyNestedRecursiveProps | undefined', + declarations: [], + schema: { + kind: 'enum', + type: 'MyNestedRecursiveProps | undefined', + schema: [ + 'undefined', + { + kind: 'object', + type: 'MyNestedRecursiveProps', + schema: { + recursive: { + name: 'recursive', + global: false, + description: '', + tags: [], + required: true, + type: 'MyNestedRecursiveProps', + declarations: [], + schema: 'MyNestedRecursiveProps', + }, + }, + }, + ], + }, + }, + typeSystem: 'JavaScript', + }, +]; + +export const referenceTypeEvents = { + __name: 'component', + emits: ['foo', 'bar', 'baz'], + __hmrId: '3a8b03b5', + __file: + '/storybook/sandbox/vue3-vite-default-ts/src/stories/renderers/vue3/component-meta/reference-type-events/component.vue', + __docgenInfo: { + exportName: 'default', + displayName: 'component', + props: [ + { + name: 'key', + global: true, + description: '', + tags: [], + required: false, + type: 'string | number | symbol | undefined', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/node_modules/@vue/runtime-core/dist/runtime-core.d.ts', + range: [47082, 47113], + }, + ], + schema: { + kind: 'enum', + type: 'string | number | symbol | undefined', + schema: ['undefined', 'string', 'number', 'symbol'], + }, + }, + { + name: 'ref', + global: true, + description: '', + tags: [], + required: false, + type: 'VNodeRef | undefined', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/node_modules/@vue/runtime-core/dist/runtime-core.d.ts', + range: [47118, 47133], + }, + ], + schema: { + kind: 'enum', + type: 'VNodeRef | undefined', + schema: [ + 'undefined', + 'string', + 'Ref', + { + kind: 'event', + type: '(ref: Element | ComponentPublicInstance<{}, {}, {}, {}, {}, {}, {}, {}, false, ComponentOptionsBase, {}, {}> | null, refs: Record<...>): void', + schema: [], + }, + ], + }, + }, + { + name: 'ref_for', + global: true, + description: '', + tags: [], + required: false, + type: 'boolean | undefined', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/node_modules/@vue/runtime-core/dist/runtime-core.d.ts', + range: [47138, 47156], + }, + ], + schema: { + kind: 'enum', + type: 'boolean | undefined', + schema: ['undefined', 'false', 'true'], + }, + }, + { + name: 'ref_key', + global: true, + description: '', + tags: [], + required: false, + type: 'string | undefined', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/node_modules/@vue/runtime-core/dist/runtime-core.d.ts', + range: [47161, 47178], + }, + ], + schema: { + kind: 'enum', + type: 'string | undefined', + schema: ['undefined', 'string'], + }, + }, + { + name: 'class', + global: true, + description: '', + tags: [], + required: false, + type: 'unknown', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/node_modules/@vue/runtime-core/dist/runtime-core.d.ts', + range: [52888, 52904], + }, + ], + schema: 'unknown', + }, + { + name: 'style', + global: true, + description: '', + tags: [], + required: false, + type: 'unknown', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/node_modules/@vue/runtime-core/dist/runtime-core.d.ts', + range: [52909, 52925], + }, + ], + schema: 'unknown', + }, + ], + events: [ + { + name: 'foo', + type: '[data?: { foo: string; } | undefined]', + signature: '(event: "foo", data?: { foo: string; } | undefined): void', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/node_modules/@vue/runtime-core/dist/runtime-core.d.ts', + range: [4468, 4503], + }, + ], + schema: [ + { + kind: 'enum', + type: '{ foo: string; } | undefined', + schema: [ + 'undefined', + { + kind: 'object', + type: '{ foo: string; }', + schema: { + foo: { + name: 'foo', + global: false, + description: '', + tags: [], + required: true, + type: 'string', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/src/stories/renderers/vue3/component-meta/reference-type-events/component.vue', + range: [207, 218], + }, + ], + schema: 'string', + }, + }, + }, + ], + }, + ], + }, + { + name: 'bar', + type: '[value: { year: number; title?: any; }]', + signature: '(event: "bar", value: { year: number; title?: any; }): void', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/node_modules/@vue/runtime-core/dist/runtime-core.d.ts', + range: [4468, 4503], + }, + ], + schema: [ + { + kind: 'object', + type: '{ year: number; title?: any; }', + schema: { + year: { + name: 'year', + global: false, + description: '', + tags: [], + required: true, + type: 'number', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/src/stories/renderers/vue3/component-meta/reference-type-events/component.vue', + range: [255, 268], + }, + ], + schema: 'number', + }, + title: { + name: 'title', + global: false, + description: '', + tags: [], + required: false, + type: 'any', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/src/stories/renderers/vue3/component-meta/reference-type-events/component.vue', + range: [269, 280], + }, + ], + schema: 'any', + }, + }, + }, + ], + }, + { + name: 'baz', + type: '[]', + signature: '(event: "baz"): void', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/node_modules/@vue/runtime-core/dist/runtime-core.d.ts', + range: [4468, 4503], + }, + ], + schema: [], + }, + ], + slots: [], + exposed: [ + { + name: 'onFoo', + type: '((data?: { foo: string; } | undefined) => any) | undefined', + description: '', + declarations: [], + schema: { + kind: 'enum', + type: '((data?: { foo: string; } | undefined) => any) | undefined', + schema: [ + 'undefined', + { + kind: 'event', + type: '(data?: { foo: string; } | undefined): any', + schema: [ + { + kind: 'enum', + type: '{ foo: string; } | undefined', + schema: [ + 'undefined', + { + kind: 'object', + type: '{ foo: string; }', + schema: { + foo: { + name: 'foo', + global: false, + description: '', + tags: [], + required: true, + type: 'string', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/src/stories/renderers/vue3/component-meta/reference-type-events/component.vue', + range: [207, 218], + }, + ], + schema: 'string', + }, + }, + }, + ], + }, + ], + }, + ], + }, + }, + { + name: 'onBar', + type: '((value: { year: number; title?: any; }) => any) | undefined', + description: '', + declarations: [], + schema: { + kind: 'enum', + type: '((value: { year: number; title?: any; }) => any) | undefined', + schema: [ + 'undefined', + { + kind: 'event', + type: '(value: { year: number; title?: any; }): any', + schema: [ + { + kind: 'object', + type: '{ year: number; title?: any; }', + schema: { + year: { + name: 'year', + global: false, + description: '', + tags: [], + required: true, + type: 'number', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/src/stories/renderers/vue3/component-meta/reference-type-events/component.vue', + range: [255, 268], + }, + ], + schema: 'number', + }, + title: { + name: 'title', + global: false, + description: '', + tags: [], + required: false, + type: 'any', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/src/stories/renderers/vue3/component-meta/reference-type-events/component.vue', + range: [269, 280], + }, + ], + schema: 'any', + }, + }, + }, + ], + }, + ], + }, + }, + { + name: 'onBaz', + type: '(() => any) | undefined', + description: '', + declarations: [], + schema: { + kind: 'enum', + type: '(() => any) | undefined', + schema: [ + 'undefined', + { + kind: 'event', + type: '(): any', + schema: [], + }, + ], + }, + }, + ], + sourceFiles: + '/storybook/sandbox/vue3-vite-default-ts/src/stories/renderers/vue3/component-meta/reference-type-events/component.vue', + }, +}; + +export const mockExtractComponentEventsReturn = [ + { + propDef: { + name: 'foo', + type: {}, + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'foo', + type: '[data?: { foo: string; } | undefined]', + signature: '(event: "foo", data?: { foo: string; } | undefined): void', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/node_modules/@vue/runtime-core/dist/runtime-core.d.ts', + range: [4468, 4503], + }, + ], + schema: [ + { + kind: 'enum', + type: '{ foo: string; } | undefined', + schema: [ + 'undefined', + { + kind: 'object', + type: '{ foo: string; }', + schema: { + foo: { + name: 'foo', + global: false, + description: '', + tags: [], + required: true, + type: 'string', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/src/stories/renderers/vue3/component-meta/reference-type-events/component.vue', + range: [207, 218], + }, + ], + schema: 'string', + }, + }, + }, + ], + }, + ], + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'bar', + type: {}, + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'bar', + type: '[value: { year: number; title?: any; }]', + signature: '(event: "bar", value: { year: number; title?: any; }): void', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/node_modules/@vue/runtime-core/dist/runtime-core.d.ts', + range: [4468, 4503], + }, + ], + schema: [ + { + kind: 'object', + type: '{ year: number; title?: any; }', + schema: { + year: { + name: 'year', + global: false, + description: '', + tags: [], + required: true, + type: 'number', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/src/stories/renderers/vue3/component-meta/reference-type-events/component.vue', + range: [255, 268], + }, + ], + schema: 'number', + }, + title: { + name: 'title', + global: false, + description: '', + tags: [], + required: false, + type: 'any', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/src/stories/renderers/vue3/component-meta/reference-type-events/component.vue', + range: [269, 280], + }, + ], + schema: 'any', + }, + }, + }, + ], + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'baz', + type: {}, + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'baz', + type: '[]', + signature: '(event: "baz"): void', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/node_modules/@vue/runtime-core/dist/runtime-core.d.ts', + range: [4468, 4503], + }, + ], + schema: [], + }, + typeSystem: 'JavaScript', + }, +]; + +export const templateSlots = { + __hmrId: 'c8033161', + __file: + '/storybook/sandbox/vue3-vite-default-ts/src/stories/renderers/vue3/component-meta/template-slots/component.vue', + __docgenInfo: { + exportName: 'default', + displayName: 'component', + props: [ + { + name: 'key', + global: true, + description: '', + tags: [], + required: false, + type: 'string | number | symbol | undefined', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/node_modules/@vue/runtime-core/dist/runtime-core.d.ts', + range: [47082, 47113], + }, + ], + schema: { + kind: 'enum', + type: 'string | number | symbol | undefined', + schema: ['undefined', 'string', 'number', 'symbol'], + }, + }, + { + name: 'ref', + global: true, + description: '', + tags: [], + required: false, + type: 'VNodeRef | undefined', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/node_modules/@vue/runtime-core/dist/runtime-core.d.ts', + range: [47118, 47133], + }, + ], + schema: { + kind: 'enum', + type: 'VNodeRef | undefined', + schema: [ + 'undefined', + 'string', + 'Ref', + { + kind: 'event', + type: '(ref: Element | ComponentPublicInstance<{}, {}, {}, {}, {}, {}, {}, {}, false, ComponentOptionsBase, {}, {}> | null, refs: Record<...>): void', + schema: [], + }, + ], + }, + }, + { + name: 'ref_for', + global: true, + description: '', + tags: [], + required: false, + type: 'boolean | undefined', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/node_modules/@vue/runtime-core/dist/runtime-core.d.ts', + range: [47138, 47156], + }, + ], + schema: { + kind: 'enum', + type: 'boolean | undefined', + schema: ['undefined', 'false', 'true'], + }, + }, + { + name: 'ref_key', + global: true, + description: '', + tags: [], + required: false, + type: 'string | undefined', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/node_modules/@vue/runtime-core/dist/runtime-core.d.ts', + range: [47161, 47178], + }, + ], + schema: { + kind: 'enum', + type: 'string | undefined', + schema: ['undefined', 'string'], + }, + }, + { + name: 'class', + global: true, + description: '', + tags: [], + required: false, + type: 'unknown', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/node_modules/@vue/runtime-core/dist/runtime-core.d.ts', + range: [52888, 52904], + }, + ], + schema: 'unknown', + }, + { + name: 'style', + global: true, + description: '', + tags: [], + required: false, + type: 'unknown', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/node_modules/@vue/runtime-core/dist/runtime-core.d.ts', + range: [52909, 52925], + }, + ], + schema: 'unknown', + }, + ], + events: [], + slots: [ + { + name: 'no-bind', + type: '{}', + description: '', + declarations: [], + schema: { + kind: 'object', + type: '{}', + schema: {}, + }, + }, + { + name: 'default', + type: '{ num: number; }', + description: '', + declarations: [], + schema: { + kind: 'object', + type: '{ num: number; }', + schema: { + num: { + name: 'num', + global: false, + description: '', + tags: [], + required: true, + type: 'number', + declarations: [], + schema: 'number', + }, + }, + }, + }, + { + name: 'named', + type: '{ str: string; }', + description: '', + declarations: [], + schema: { + kind: 'object', + type: '{ str: string; }', + schema: { + str: { + name: 'str', + global: false, + description: '', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + }, + { + name: 'vbind', + type: '{ num: number; str: string; }', + description: '', + declarations: [], + schema: { + kind: 'object', + type: '{ num: number; str: string; }', + schema: { + num: { + name: 'num', + global: false, + description: '', + tags: [], + required: true, + type: 'number', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/src/stories/renderers/vue3/component-meta/template-slots/component.vue', + range: [153, 161], + }, + ], + schema: 'number', + }, + str: { + name: 'str', + global: false, + description: '', + tags: [], + required: true, + type: 'string', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/src/stories/renderers/vue3/component-meta/template-slots/component.vue', + range: [163, 173], + }, + ], + schema: 'string', + }, + }, + }, + }, + ], + exposed: [ + { + name: '$slots', + type: 'Readonly & { "no-bind"?(_: {}): any; default?(_: { num: number; }): any; named?(_: { str: string; }): any; vbind?(_: { num: number; str: string; }): any; }', + description: '', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/node_modules/@vue/runtime-core/dist/runtime-core.d.ts', + range: [8406, 8433], + }, + ], + schema: { + kind: 'object', + type: 'Readonly & { "no-bind"?(_: {}): any; default?(_: { num: number; }): any; named?(_: { str: string; }): any; vbind?(_: { num: number; str: string; }): any; }', + schema: { + 'no-bind': { + name: 'no-bind', + global: false, + description: '', + tags: [], + required: false, + type: '((_: {}) => any) | undefined', + declarations: [], + schema: { + kind: 'enum', + type: '((_: {}) => any) | undefined', + schema: [ + 'undefined', + { + kind: 'event', + type: '(_: {}): any', + schema: [], + }, + ], + }, + }, + default: { + name: 'default', + global: false, + description: '', + tags: [], + required: false, + type: '((_: { num: number; }) => any) | undefined', + declarations: [], + schema: { + kind: 'enum', + type: '((_: { num: number; }) => any) | undefined', + schema: [ + 'undefined', + { + kind: 'event', + type: '(_: { num: number; }): any', + schema: [], + }, + ], + }, + }, + named: { + name: 'named', + global: false, + description: '', + tags: [], + required: false, + type: '((_: { str: string; }) => any) | undefined', + declarations: [], + schema: { + kind: 'enum', + type: '((_: { str: string; }) => any) | undefined', + schema: [ + 'undefined', + { + kind: 'event', + type: '(_: { str: string; }): any', + schema: [], + }, + ], + }, + }, + vbind: { + name: 'vbind', + global: false, + description: '', + tags: [], + required: false, + type: '((_: { num: number; str: string; }) => any) | undefined', + declarations: [], + schema: { + kind: 'enum', + type: '((_: { num: number; str: string; }) => any) | undefined', + schema: [ + 'undefined', + { + kind: 'event', + type: '(_: { num: number; str: string; }): any', + schema: [], + }, + ], + }, + }, + }, + }, + }, + ], + sourceFiles: + '/storybook/sandbox/vue3-vite-default-ts/src/stories/renderers/vue3/component-meta/template-slots/component.vue', + }, +}; + +export const mockExtractComponentSlotsReturn = [ + { + propDef: { + name: 'no-bind', + type: {}, + description: '', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'no-bind', + type: '{}', + description: '', + declarations: [], + schema: { + kind: 'object', + type: '{}', + schema: {}, + }, + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'default', + type: {}, + description: '', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'default', + type: '{ num: number; }', + description: '', + declarations: [], + schema: { + kind: 'object', + type: '{ num: number; }', + schema: { + num: { + name: 'num', + global: false, + description: '', + tags: [], + required: true, + type: 'number', + declarations: [], + schema: 'number', + }, + }, + }, + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'named', + type: {}, + description: '', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'named', + type: '{ str: string; }', + description: '', + declarations: [], + schema: { + kind: 'object', + type: '{ str: string; }', + schema: { + str: { + name: 'str', + global: false, + description: '', + tags: [], + required: true, + type: 'string', + declarations: [], + schema: 'string', + }, + }, + }, + }, + typeSystem: 'JavaScript', + }, + { + propDef: { + name: 'vbind', + type: {}, + description: '', + defaultValue: null, + sbType: { + name: 'other', + }, + }, + docgenInfo: { + name: 'vbind', + type: '{ num: number; str: string; }', + description: '', + declarations: [], + schema: { + kind: 'object', + type: '{ num: number; str: string; }', + schema: { + num: { + name: 'num', + global: false, + description: '', + tags: [], + required: true, + type: 'number', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/src/stories/renderers/vue3/component-meta/template-slots/component.vue', + range: [153, 161], + }, + ], + schema: 'number', + }, + str: { + name: 'str', + global: false, + description: '', + tags: [], + required: true, + type: 'string', + declarations: [ + { + file: '/storybook/sandbox/vue3-vite-default-ts/src/stories/renderers/vue3/component-meta/template-slots/component.vue', + range: [163, 173], + }, + ], + schema: 'string', + }, + }, + }, + }, + typeSystem: 'JavaScript', + }, +]; diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/OptionApi.stories.ts b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/OptionApi.stories.ts new file mode 100644 index 000000000000..f37f0147b37a --- /dev/null +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/OptionApi.stories.ts @@ -0,0 +1,19 @@ +import type { Meta, StoryObj } from '@storybook/vue3'; +import Component from './options-api/component'; + +const meta = { + component: Component, + tags: ['autodocs'], +} satisfies Meta; + +type Story = StoryObj; +export default meta; + +export const Default: Story = { + args: { + numberDefault: 12, + objectDefault: { bar: 'foo' }, + arrayDefault: [1, 2, 3], + complexDefault: [1, 2, 3, 4, 5], + }, +}; diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/ReferenceTypeEvents.stories.ts b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/ReferenceTypeEvents.stories.ts new file mode 100644 index 000000000000..6421e50b4b13 --- /dev/null +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/ReferenceTypeEvents.stories.ts @@ -0,0 +1,12 @@ +import type { Meta, StoryObj } from '@storybook/vue3'; +import Component from './reference-type-events/component.vue'; + +const meta = { + component: Component, + tags: ['autodocs'], +} satisfies Meta; + +type Story = StoryObj; +export default meta; + +export const ReferenceTypeEvents: Story = {}; diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/ReferenceTypeExposed.stories.ts b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/ReferenceTypeExposed.stories.ts new file mode 100644 index 000000000000..5f4d8049caae --- /dev/null +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/ReferenceTypeExposed.stories.ts @@ -0,0 +1,12 @@ +import type { Meta, StoryObj } from '@storybook/vue3'; +import Component from './reference-type-exposed/component.vue'; + +const meta = { + component: Component, + tags: ['autodocs'], +} satisfies Meta; + +type Story = StoryObj; +export default meta; + +export const ReferenceTypeExposed: Story = {}; diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/ReferenceTypeProps.stories.ts b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/ReferenceTypeProps.stories.ts new file mode 100644 index 000000000000..d213003bc00f --- /dev/null +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/ReferenceTypeProps.stories.ts @@ -0,0 +1,33 @@ +import type { Meta, StoryObj } from '@storybook/vue3'; +import Component from './reference-type-props/component.vue'; + +const meta = { + component: Component, + tags: ['autodocs'], +} satisfies Meta; + +type Story = StoryObj; +export default meta; + +enum MyEnum { + Small, + Medium, + Large, +} + +export const ReferenceTypeProps: Story = { + args: { + foo: 'Foo', + baz: true, + stringArray: ['Foo', 'Bar', 'Baz'], + bar: 1, + unionOptional: 'Foo', + union: 'Foo', + inlined: { foo: 'Foo' }, + nested: { nestedProp: 'Nested Prop' }, + nestedIntersection: { nestedProp: 'Nested Prop', additionalProp: 'Additional Prop' }, + array: [{ nestedProp: 'Nested Prop' }], + literalFromContext: 'Uncategorized', + enumValue: MyEnum.Small, + }, +}; diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/TemplateSlots.stories.ts b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/TemplateSlots.stories.ts new file mode 100644 index 000000000000..817bdcba42df --- /dev/null +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/TemplateSlots.stories.ts @@ -0,0 +1,18 @@ +import type { Meta, StoryObj } from '@storybook/vue3'; +import Component from './template-slots/component.vue'; + +const meta = { + component: Component, + tags: ['autodocs'], +} satisfies Meta; + +type Story = StoryObj; +export default meta; + +export const Default: Story = { + args: { + default: ({ num }) => `Default slot { num=${num} }`, + named: ({ str }) => `Named slot { str=${str} }`, + vbind: ({ num, str }) => `Named v-bind slot { num=${num}, str=${str} }`, + }, +}; diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/TsComponent.stories.ts b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/TsComponent.stories.ts new file mode 100644 index 000000000000..a6c53ef319f4 --- /dev/null +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/TsComponent.stories.ts @@ -0,0 +1,17 @@ +import type { Meta, StoryObj } from '@storybook/vue3'; +import Component from './ts-component/component'; + +const meta = { + component: Component, + tags: ['autodocs'], +} satisfies Meta; + +type Story = StoryObj; +export default meta; + +export const Default: Story = { + args: { + foo: 'bar', + bar: 20, + }, +}; diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/TsNameExport.stories.ts b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/TsNameExport.stories.ts new file mode 100644 index 000000000000..1d8d73780075 --- /dev/null +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/TsNameExport.stories.ts @@ -0,0 +1,17 @@ +import type { Meta, StoryObj } from '@storybook/vue3'; +import { ComponentA } from './ts-named-export/component'; + +const meta = { + component: ComponentA, + tags: ['autodocs'], +} satisfies Meta; + +type Story = StoryObj; +export default meta; + +export const Default: Story = { + args: { + size: 'large', + backgroundColor: 'blue', + }, +}; diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/class-slots/component.vue b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/class-slots/component.vue new file mode 100644 index 000000000000..a3491292f5d4 --- /dev/null +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/class-slots/component.vue @@ -0,0 +1,10 @@ + diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/options-api/component.ts b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/options-api/component.ts new file mode 100644 index 000000000000..53e3f9732026 --- /dev/null +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/options-api/component.ts @@ -0,0 +1,65 @@ +import { defineComponent, h } from 'vue'; + +interface SubmitPayload { + /** + * email of user + */ + email: string; + /** + * password of same user + */ + password: string; +} + +export default defineComponent({ + emits: { + // Validate submit event + submit: ({ email, password }: SubmitPayload) => { + if (email && password) { + return true; + } + + return false; + }, + }, + props: { + /** + * Number prop with default + */ + numberDefault: { + type: Number, + default: 42, + }, + /** + * Object prop with default + */ + objectDefault: { + type: Object, + default: () => ({ + foo: 'bar', + }), + }, + /** + * Array prop with default + */ + arrayDefault: { + type: Array, + default: () => [1, 2, 3], + }, + /** + * Default function more complex + */ + complexDefault: { + type: Array, + default: (props: any) => { + if (props.arrayDefault.length > props.numberDefault) { + return []; + } + return undefined; + }, + }, + }, + render() { + return h('pre', JSON.stringify(this.$props, null, 2)); + }, +}); diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/reference-type-events/component.vue b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/reference-type-events/component.vue new file mode 100644 index 000000000000..e670706aff05 --- /dev/null +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/reference-type-events/component.vue @@ -0,0 +1,31 @@ + + + diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/reference-type-exposed/component.vue b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/reference-type-exposed/component.vue new file mode 100644 index 000000000000..9ceeaeb84f6e --- /dev/null +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/reference-type-exposed/component.vue @@ -0,0 +1,21 @@ + + + diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/reference-type-props/component-js-setup.vue b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/reference-type-props/component-js-setup.vue new file mode 100644 index 000000000000..2b75e9a36c83 --- /dev/null +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/reference-type-props/component-js-setup.vue @@ -0,0 +1,58 @@ + diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/reference-type-props/component-js.vue b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/reference-type-props/component-js.vue new file mode 100644 index 000000000000..78dc088acbc6 --- /dev/null +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/reference-type-props/component-js.vue @@ -0,0 +1,43 @@ + + + diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/reference-type-props/component.vue b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/reference-type-props/component.vue new file mode 100644 index 000000000000..49c83a600140 --- /dev/null +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/reference-type-props/component.vue @@ -0,0 +1,109 @@ + + + diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/reference-type-props/my-props.ts b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/reference-type-props/my-props.ts new file mode 100644 index 000000000000..b198bac5b72e --- /dev/null +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/reference-type-props/my-props.ts @@ -0,0 +1,113 @@ +export interface MyNestedProps { + /** + * nested prop documentation + */ + nestedProp: string; +} + +export interface MyIgnoredNestedProps { + nestedProp: string; +} + +export interface MyNestedRecursiveProps { + recursive: MyNestedRecursiveProps; +} + +enum MyEnum { + Small, + Medium, + Large, +} + +const categories = [ + 'Uncategorized', + 'Content', + 'Interaction', + 'Display', + 'Forms', + 'Addons', +] as const; + +type MyCategories = (typeof categories)[number]; + +export interface MyProps { + /** + * string foo + * + * @default "rounded" + * @since v1.0.0 + * @see https://vuejs.org/ + * @example + * ```vue + * + * ``` + */ + foo: string; + /** + * optional number bar + */ + bar?: number; + /** + * string array baz + */ + baz?: string[]; + /** + * required union type + */ + union: string | number; + /** + * optional union type + */ + unionOptional?: string | number; + /** + * required nested object + */ + nested: MyNestedProps; + /** + * required nested object with intersection + */ + nestedIntersection: MyNestedProps & { + /** + * required additional property + */ + additionalProp: string; + }; + /** + * optional nested object + */ + nestedOptional?: MyNestedProps | MyIgnoredNestedProps; + /** + * required array object + */ + array: MyNestedProps[]; + /** + * optional array object + */ + arrayOptional?: MyNestedProps[]; + /** + * enum value + */ + enumValue: MyEnum; + /** + * literal type alias that require context + */ + literalFromContext: MyCategories; + inlined: { foo: string }; + recursive: MyNestedRecursiveProps; +} + +export const StringRequired = { + type: String, + required: true, +} as const; + +export const StringEmpty = { + type: String, + value: '', +} as const; + +export const StringUndefined = { + type: String, +} as const; diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/template-slots/component-no-script.vue b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/template-slots/component-no-script.vue new file mode 100644 index 000000000000..6c6432e31a07 --- /dev/null +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/template-slots/component-no-script.vue @@ -0,0 +1,6 @@ + diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/template-slots/component.vue b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/template-slots/component.vue new file mode 100644 index 000000000000..b71a49de53d8 --- /dev/null +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/template-slots/component.vue @@ -0,0 +1,11 @@ + + + diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/ts-component/component.ts b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/ts-component/component.ts new file mode 100644 index 000000000000..4b9c790b9911 --- /dev/null +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/ts-component/component.ts @@ -0,0 +1,22 @@ +import { defineComponent, h } from 'vue'; + +export default defineComponent({ + props: { + /** + * string foo + */ + foo: { + type: String, + required: true, + }, + /** + * optional number bar + */ + bar: { + type: Number, + }, + }, + setup(props) { + return () => h('pre', JSON.stringify(props, null, 2)); + }, +}); diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/ts-named-export/component.ts b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/ts-named-export/component.ts new file mode 100644 index 000000000000..2976e45e175e --- /dev/null +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/ts-named-export/component.ts @@ -0,0 +1,52 @@ +import type { PropType } from 'vue'; +import { defineComponent, h } from 'vue'; + +export const ComponentA = defineComponent({ + name: 'MyCompo1', + props: { + /** + * This is a description of the prop + * @values 'small', 'medium', 'large' + * @defaultValue 'medium' + * @control select + * @group Size + * */ + size: { + type: String as PropType<'small' | 'medium' | 'large'>, + default: 'medium', + }, + /** + * This is a description of the prop + * @defaultValue false + * @control color + * @group Style + * */ + backgroundColor: { + type: String, + default: 'red', + }, + }, + setup(props: any) { + return () => h('pre', JSON.stringify(props, null, 2)); + }, +}); + +export const ComponentB = defineComponent({ + name: 'MyCompo2', + props: { + /** + * This is a description of the prop + * @values true, false + * @defaultValue false + * @control boolean + * @group Size + * */ + primary: { + type: Boolean, + default: false, + }, + }, + setup(props: any) { + return () => h('pre', JSON.stringify(props, null, 2)); + }, +}); diff --git a/code/yarn.lock b/code/yarn.lock index 07c7d2bd6b0e..9a8fb5f0771b 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -6807,11 +6807,14 @@ __metadata: "@storybook/builder-vite": "workspace:*" "@storybook/core-server": "workspace:*" "@storybook/vue3": "workspace:*" + "@types/find-package-json": "npm:^1.2.6" "@types/node": "npm:^18.0.0" + find-package-json: "npm:^1.2.0" magic-string: "npm:^0.30.0" typescript: "npm:^5.3.2" vite: "npm:^4.0.0" - vue-docgen-api: "npm:^4.40.0" + vue-component-meta: "npm:^1.8.27" + vue-docgen-api: "npm:^4.75.1" peerDependencies: vite: ^4.0.0 || ^5.0.0 languageName: unknown @@ -7463,6 +7466,15 @@ __metadata: languageName: node linkType: hard +"@types/find-package-json@npm:^1.2.6": + version: 1.2.6 + resolution: "@types/find-package-json@npm:1.2.6" + dependencies: + "@types/node": "npm:*" + checksum: e9ec7d10f9c919b14cf391e710f41ff6684a6e6d87afc6322e7f7e3afe30b5f046b806767cb1509af6265e3f4ceb11fac9da279757839269a4c849359d7f5f18 + languageName: node + linkType: hard + "@types/fs-extra@npm:^11.0.1": version: 11.0.4 resolution: "@types/fs-extra@npm:11.0.4" @@ -8645,6 +8657,15 @@ __metadata: languageName: node linkType: hard +"@volar/language-core@npm:1.11.1, @volar/language-core@npm:~1.11.1": + version: 1.11.1 + resolution: "@volar/language-core@npm:1.11.1" + dependencies: + "@volar/source-map": "npm:1.11.1" + checksum: 92c4439e3a9ccc534c970031388c318740f6fa032283d03e136c6c8c0228f549c68a7c363af1a28252617a0dca6069e14028329ac906d5acf1912931d0cdcb69 + languageName: node + linkType: hard + "@volar/source-map@npm:1.10.1, @volar/source-map@npm:~1.10.0": version: 1.10.1 resolution: "@volar/source-map@npm:1.10.1" @@ -8654,6 +8675,15 @@ __metadata: languageName: node linkType: hard +"@volar/source-map@npm:1.11.1, @volar/source-map@npm:~1.11.1": + version: 1.11.1 + resolution: "@volar/source-map@npm:1.11.1" + dependencies: + muggle-string: "npm:^0.3.1" + checksum: 0bfc639889802705f8036ea8b2052a95a4d691a68bc2b6744ba8b9d312d887393dd3278101180a5ee5304972899d493972a483afafd41e097968746c77d724cb + languageName: node + linkType: hard + "@volar/typescript@npm:~1.10.0": version: 1.10.1 resolution: "@volar/typescript@npm:1.10.1" @@ -8663,6 +8693,16 @@ __metadata: languageName: node linkType: hard +"@volar/typescript@npm:~1.11.1": + version: 1.11.1 + resolution: "@volar/typescript@npm:1.11.1" + dependencies: + "@volar/language-core": "npm:1.11.1" + path-browserify: "npm:^1.0.1" + checksum: 86fe153db3a14d8eb3632784a1d7fcbfbfb51fa5517c3878bfdd49ee8d15a83b1a09f9c589454b7396454c104d3a8e2db3a987dc99b37c33816772fc3e292bf2 + languageName: node + linkType: hard + "@vue/compiler-core@npm:3.0.0": version: 3.0.0 resolution: "@vue/compiler-core@npm:3.0.0" @@ -8843,6 +8883,28 @@ __metadata: languageName: node linkType: hard +"@vue/language-core@npm:1.8.27": + version: 1.8.27 + resolution: "@vue/language-core@npm:1.8.27" + dependencies: + "@volar/language-core": "npm:~1.11.1" + "@volar/source-map": "npm:~1.11.1" + "@vue/compiler-dom": "npm:^3.3.0" + "@vue/shared": "npm:^3.3.0" + computeds: "npm:^0.0.1" + minimatch: "npm:^9.0.3" + muggle-string: "npm:^0.3.1" + path-browserify: "npm:^1.0.1" + vue-template-compiler: "npm:^2.7.14" + peerDependencies: + typescript: "*" + peerDependenciesMeta: + typescript: + optional: true + checksum: 2018214d8ce2643d19e8e84eddaeacddca28b2980984d7916d97f97556c3716be184cf9f8c4f506d072a11f265401e3bc0391117cf7cfcc1e4a25048f4432dc7 + languageName: node + linkType: hard + "@vue/reactivity-transform@npm:3.3.11": version: 3.3.11 resolution: "@vue/reactivity-transform@npm:3.3.11" @@ -11904,6 +11966,13 @@ __metadata: languageName: node linkType: hard +"computeds@npm:^0.0.1": + version: 0.0.1 + resolution: "computeds@npm:0.0.1" + checksum: 8a8736f1f43e4a99286519785d71a10ece8f444a2fa1fc2fe1f03dedf63f3477b45094002c85a2826f7631759c9f5a00b4ace47456997f253073fc525e8983de + languageName: node + linkType: hard + "concat-map@npm:0.0.1": version: 0.0.1 resolution: "concat-map@npm:0.0.1" @@ -15248,6 +15317,13 @@ __metadata: languageName: node linkType: hard +"find-package-json@npm:^1.2.0": + version: 1.2.0 + resolution: "find-package-json@npm:1.2.0" + checksum: 85d6c97afb9f8f0deb0d344a1c4eb8027347cf4d61666c28d3ac3f913e916684441218682b3dd6f8ad570e5d43c96a7db521f70183d70df559d07e1f99cdc635 + languageName: node + linkType: hard + "find-root@npm:^1.1.0": version: 1.1.0 resolution: "find-root@npm:1.1.0" @@ -29193,6 +29269,30 @@ __metadata: languageName: node linkType: hard +"vue-component-meta@npm:^1.8.27": + version: 1.8.27 + resolution: "vue-component-meta@npm:1.8.27" + dependencies: + "@volar/typescript": "npm:~1.11.1" + "@vue/language-core": "npm:1.8.27" + path-browserify: "npm:^1.0.1" + vue-component-type-helpers: "npm:1.8.27" + peerDependencies: + typescript: "*" + peerDependenciesMeta: + typescript: + optional: true + checksum: 40884b316940e6995a6e7f9e5cbe5536b5c6e380acfd5b1d24914511972a241550c04474f4fffdf6305b1c9962b1137b5fd6183dc309127d3a268fe7d8d85df9 + languageName: node + linkType: hard + +"vue-component-type-helpers@npm:1.8.27": + version: 1.8.27 + resolution: "vue-component-type-helpers@npm:1.8.27" + checksum: 3403d70951e422162321e810f54f23f11ee5d2642631d2ca2cb1de18e5d35a0b7b05dd1f9bd02a0ae77dfa0b80751d826865d98f928ae6d6fbce9303406c9820 + languageName: node + linkType: hard + "vue-component-type-helpers@npm:1.8.4": version: 1.8.4 resolution: "vue-component-type-helpers@npm:1.8.4" @@ -29207,7 +29307,7 @@ __metadata: languageName: node linkType: hard -"vue-docgen-api@npm:^4.40.0, vue-docgen-api@npm:^4.46.0": +"vue-docgen-api@npm:^4.46.0, vue-docgen-api@npm:^4.75.1": version: 4.75.1 resolution: "vue-docgen-api@npm:4.75.1" dependencies: