@mozaic-ds/vue
Version:
Mozaic-Vue is the Vue.js implementation of ADEO Design system
147 lines (135 loc) • 3.67 kB
text/typescript
import type { Meta, StoryObj } from '@storybook/vue3-vite';
import { defineComponent } from 'vue';
import './Catalog.scss';
type StoryModule = {
default?: {
title?: string;
args?: Record<string, unknown>;
parameters?: {
docs?: {
description?: {
component?: string;
story?: string;
};
};
};
render?: (...args: unknown[]) => unknown;
};
[key: string]: unknown;
};
const storyModules = import.meta.glob('../components/*/*.stories.ts', {
eager: true,
}) as Record<string, StoryModule>;
const humanizeComponentName = (value: string) =>
value
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
.replace(/[-_]+/g, ' ')
.replace(/\b\w/g, (char) => char.toUpperCase())
.trim();
const slugify = (value: string) =>
value
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-+|-+$/g, '');
const getStoryHref = (title: string) => `/?path=/docs/${slugify(title)}--docs`;
const catalogStories = Object.entries(storyModules)
.filter(([, module]) => Boolean(module.default?.title))
.map(([filePath, module]) => {
const meta = module.default ?? {};
const storyName = Object.keys(module).find(
(name) => name !== 'default' && name !== '__esModule',
);
const story = storyName ? (module[storyName] as StoryModule) : undefined;
const render =
typeof story?.render === 'function'
? story.render
: typeof meta.render === 'function'
? meta.render
: undefined;
const args = {
...(meta.args ?? {}),
...(story?.args ?? {}),
};
const componentName =
filePath.split('/components/')[1]?.split('/')[0] ??
meta.title ??
'Component';
const rawTitle =
(meta.title ?? componentName).split('/').pop() ?? componentName;
return {
filePath,
title: humanizeComponentName(rawTitle),
description:
meta.parameters?.docs?.description?.component ??
meta.parameters?.docs?.description?.story ??
'Component documentation and examples.',
storyHref: getStoryHref(meta.title ?? componentName),
previewComponent:
render && typeof render === 'function'
? defineComponent(render(args as never))
: undefined,
};
})
.sort((left, right) => left.title.localeCompare(right.title));
const meta: Meta = {
title: 'Catalog',
parameters: {
controls: {
disable: true,
},
docs: {
controls: {
disable: true,
},
description: {
component: 'A live catalog of the library components.',
},
toc: false,
canvas: { sourceState: 'none' },
},
},
};
export default meta;
type Story = StoryObj;
export const Default: Story = {
render: () => ({
setup() {
return { catalogStories };
},
template: `
<section
class="catalog-grid"
>
<article
v-for="entry in catalogStories"
:key="entry.filePath"
class="catalog-card"
>
<div
class="catalog-preview"
>
<component :is="entry.previewComponent" v-if="entry.previewComponent" />
<span v-else>{{ entry.title }}</span>
</div>
<h3
class="catalog-title"
>
<a class="catalog-link" :href="entry.storyHref">{{ entry.title }}</a>
</h3>
<p
class="catalog-description"
>
{{ entry.description }}
</p>
</article>
</section>
`,
}),
parameters: {
docs: {
canvas: {
withToolbar: false,
},
},
},
};