@tpitre/story-ui 3.10.2 → 3.10.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -132,8 +132,11 @@ export function extractImportsFromCode(code, importPath) {
132
132
  }
133
133
  /**
134
134
  * Generate a filename from a story title and hash.
135
+ * @param title - The story title
136
+ * @param hash - The unique hash for the story
137
+ * @param extension - The file extension (e.g., '.stories.tsx' or '.stories.ts')
135
138
  */
136
- export function fileNameFromTitle(title, hash) {
139
+ export function fileNameFromTitle(title, hash, extension = '.stories.tsx') {
137
140
  if (!title || typeof title !== 'string') {
138
141
  title = 'untitled';
139
142
  }
@@ -146,7 +149,7 @@ export function fileNameFromTitle(title, hash) {
146
149
  .replace(/^-+|-+$/g, '')
147
150
  .replace(/"|'/g, '')
148
151
  .slice(0, 60);
149
- return `${base}-${hash}.stories.tsx`;
152
+ return `${base}-${hash}${extension}`;
150
153
  }
151
154
  /**
152
155
  * Find a similar icon name from the allowed icons set.
@@ -183,3 +186,157 @@ export function findSimilarIcon(iconName, allowedIcons) {
183
186
  }
184
187
  return null;
185
188
  }
189
+ /**
190
+ * Creates a framework-aware fallback story when generation fails.
191
+ * Uses the adapter to generate framework-appropriate code.
192
+ */
193
+ export function createFrameworkAwareFallbackStory(prompt, config, framework) {
194
+ const title = prompt.length > 50 ? prompt.substring(0, 50) + '...' : prompt;
195
+ const escapedTitle = title.replace(/"/g, '\\"').replace(/'/g, "\\'");
196
+ const storyPrefix = config.storyPrefix || 'Generated/';
197
+ // Framework-specific fallback templates
198
+ switch (framework) {
199
+ case 'vue':
200
+ return `import type { Meta, StoryObj } from '@storybook/vue3';
201
+
202
+ // Fallback story generated due to AI generation error
203
+ const meta: Meta = {
204
+ title: '${storyPrefix}${escapedTitle}',
205
+ parameters: {
206
+ docs: {
207
+ description: {
208
+ story: 'This is a fallback story created when the AI generation failed due to syntax errors.'
209
+ }
210
+ }
211
+ }
212
+ };
213
+
214
+ export default meta;
215
+ type Story = StoryObj;
216
+
217
+ export const Default: Story = {
218
+ render: () => ({
219
+ template: \`
220
+ <div style="padding: 2rem; text-align: center; border: 2px dashed #ccc; border-radius: 8px;">
221
+ <h2>Story Generation Error</h2>
222
+ <p>The AI-generated story contained syntax errors and could not be created.</p>
223
+ <p><strong>Original prompt:</strong> ${escapedTitle}</p>
224
+ <p>Please try rephrasing your request.</p>
225
+ </div>
226
+ \`
227
+ })
228
+ };`;
229
+ case 'angular':
230
+ return `import type { Meta, StoryObj } from '@storybook/angular';
231
+
232
+ // Fallback story generated due to AI generation error
233
+ const meta: Meta = {
234
+ title: '${storyPrefix}${escapedTitle}',
235
+ parameters: {
236
+ docs: {
237
+ description: {
238
+ story: 'This is a fallback story created when the AI generation failed due to syntax errors.'
239
+ }
240
+ }
241
+ }
242
+ };
243
+
244
+ export default meta;
245
+ type Story = StoryObj;
246
+
247
+ export const Default: Story = {
248
+ render: () => ({
249
+ template: \`
250
+ <div style="padding: 2rem; text-align: center; border: 2px dashed #ccc; border-radius: 8px;">
251
+ <h2>Story Generation Error</h2>
252
+ <p>The AI-generated story contained syntax errors and could not be created.</p>
253
+ <p><strong>Original prompt:</strong> ${escapedTitle}</p>
254
+ <p>Please try rephrasing your request.</p>
255
+ </div>
256
+ \`
257
+ })
258
+ };`;
259
+ case 'svelte':
260
+ return `import type { Meta, StoryObj } from '@storybook/svelte';
261
+
262
+ // Fallback story generated due to AI generation error
263
+ const meta: Meta = {
264
+ title: '${storyPrefix}${escapedTitle}',
265
+ parameters: {
266
+ docs: {
267
+ description: {
268
+ story: 'This is a fallback story created when the AI generation failed due to syntax errors.'
269
+ }
270
+ }
271
+ }
272
+ };
273
+
274
+ export default meta;
275
+ type Story = StoryObj;
276
+
277
+ export const Default: Story = {
278
+ render: () => ({
279
+ Component: null,
280
+ props: {}
281
+ })
282
+ };`;
283
+ case 'web-components':
284
+ return `import { html } from 'lit';
285
+ import type { Meta, StoryObj } from '@storybook/web-components';
286
+
287
+ // Fallback story generated due to AI generation error
288
+ const meta: Meta = {
289
+ title: '${storyPrefix}${escapedTitle}',
290
+ parameters: {
291
+ docs: {
292
+ description: {
293
+ story: 'This is a fallback story created when the AI generation failed due to syntax errors.'
294
+ }
295
+ }
296
+ }
297
+ };
298
+
299
+ export default meta;
300
+ type Story = StoryObj;
301
+
302
+ export const Default: Story = {
303
+ render: () => html\`
304
+ <div style="padding: 2rem; text-align: center; border: 2px dashed #ccc; border-radius: 8px;">
305
+ <h2>Story Generation Error</h2>
306
+ <p>The AI-generated story contained syntax errors and could not be created.</p>
307
+ <p><strong>Original prompt:</strong> ${escapedTitle}</p>
308
+ <p>Please try rephrasing your request.</p>
309
+ </div>
310
+ \`
311
+ };`;
312
+ case 'react':
313
+ default:
314
+ const storybookFramework = config.storybookFramework || '@storybook/react';
315
+ return `import React from 'react';
316
+ import type { StoryObj } from '${storybookFramework}';
317
+
318
+ // Fallback story generated due to AI generation error
319
+ export default {
320
+ title: '${storyPrefix}${escapedTitle}',
321
+ component: () => (
322
+ <div style={{ padding: '2rem', textAlign: 'center', border: '2px dashed #ccc', borderRadius: '8px' }}>
323
+ <h2>Story Generation Error</h2>
324
+ <p>The AI-generated story contained syntax errors and could not be created.</p>
325
+ <p><strong>Original prompt:</strong> ${escapedTitle}</p>
326
+ <p>Please try rephrasing your request or contact support.</p>
327
+ </div>
328
+ ),
329
+ parameters: {
330
+ docs: {
331
+ description: {
332
+ story: 'This is a fallback story created when the AI generation failed due to syntax errors.'
333
+ }
334
+ }
335
+ }
336
+ };
337
+
338
+ export const Default: StoryObj = {
339
+ args: {}
340
+ };`;
341
+ }
342
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"angular-adapter.d.ts","sourceRoot":"","sources":["../../../story-generator/framework-adapters/angular-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,aAAa,EACb,cAAc,EACd,sBAAsB,EACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,qBAAa,cAAe,SAAQ,oBAAoB;IACtD,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAa;IACzC,QAAQ,CAAC,IAAI,aAAa;IAC1B,QAAQ,CAAC,wBAAwB,EAAE,cAAc,EAAE,CAGjD;IACF,QAAQ,CAAC,gBAAgB,iBAAiB;IAE1C,oBAAoB,CAClB,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM;IA0HT,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM;IA+J/C,mBAAmB,CACjB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,GAChC,MAAM;IAqDT,gBAAgB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM;IA4B1D;;OAEG;IACH,OAAO,CAAC,WAAW;IAOnB;;OAEG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAkBzC;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;CA2BrE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,cAAc,CAErD"}
1
+ {"version":3,"file":"angular-adapter.d.ts","sourceRoot":"","sources":["../../../story-generator/framework-adapters/angular-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,aAAa,EACb,cAAc,EACd,sBAAsB,EACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,qBAAa,cAAe,SAAQ,oBAAoB;IACtD,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAa;IACzC,QAAQ,CAAC,IAAI,aAAa;IAC1B,QAAQ,CAAC,wBAAwB,EAAE,cAAc,EAAE,CAGjD;IACF,QAAQ,CAAC,gBAAgB,iBAAiB;IAE1C,oBAAoB,CAClB,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM;IAkIT,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM;IAgK/C,mBAAmB,CACjB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,GAChC,MAAM;IAqDT,gBAAgB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM;IA4B1D;;OAEG;IACH,OAAO,CAAC,WAAW;IAOnB;;OAEG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAkBzC;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;CA2BrE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,cAAc,CAErD"}
@@ -133,6 +133,14 @@ CONTENT PROJECTION (ng-content):
133
133
  - Default slot: Content between tags
134
134
  - Named slots: Use ngProjectAs or select attribute
135
135
 
136
+ MATERIAL ICONS (CRITICAL - If using @angular/material):
137
+ - ALWAYS use full icon names, NEVER abbreviate: "favorite" (not "fav"), "home" (not "ho"), "delete" (not "de"), "settings" (not "se")
138
+ - Always import MatIconModule in moduleMetadata when using <mat-icon>
139
+ - Correct syntax: <mat-icon>favorite</mat-icon>, <mat-icon>home</mat-icon>
140
+ - Common icons: home, favorite, delete, settings, search, menu, close, add, remove, edit, save, cancel, check, arrow_back, arrow_forward
141
+ - For filled variants: favorite, star, check_circle
142
+ - For outlined variants: favorite_border, star_border, check_circle_outline
143
+
136
144
  ${this.getCommonRules()}`;
137
145
  }
138
146
  generateExamples(config) {
@@ -227,7 +235,6 @@ export const ProductCard: Story = {
227
235
  \`\`\`typescript
228
236
  import type { Meta, StoryObj } from '@storybook/angular';
229
237
  import { applicationConfig } from '@storybook/angular';
230
- import { action } from '@storybook/addon-actions';
231
238
  import { ButtonComponent } from 'your-library';
232
239
 
233
240
  const meta: Meta<ButtonComponent> = {
@@ -238,16 +245,18 @@ const meta: Meta<ButtonComponent> = {
238
245
  providers: [],
239
246
  }),
240
247
  ],
248
+ argTypes: {
249
+ // Use argTypes with action for event logging instead of addon-actions
250
+ onClick: { action: 'clicked' },
251
+ },
241
252
  };
242
253
 
243
254
  export default meta;
244
255
  type Story = StoryObj<ButtonComponent>;
245
256
 
246
257
  export const WithClick: Story = {
247
- render: () => ({
248
- props: {
249
- onClick: action('button-click'),
250
- },
258
+ render: (args) => ({
259
+ props: args,
251
260
  template: \`
252
261
  <app-button (click)="onClick($event)" variant="primary">
253
262
  Click me
@@ -1 +1 @@
1
- {"version":3,"file":"svelte-adapter.d.ts","sourceRoot":"","sources":["../../../story-generator/framework-adapters/svelte-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,aAAa,EACb,cAAc,EACd,sBAAsB,EACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,qBAAa,aAAc,SAAQ,oBAAoB;IACrD,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAY;IACxC,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,wBAAwB,EAAE,cAAc,EAAE,CAGjD;IACF,QAAQ,CAAC,gBAAgB,iBAAiB;IAE1C,oBAAoB,CAClB,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM;IA8GT,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM;IAuJ/C,mBAAmB,CACjB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,GAChC,MAAM;IA4CT,gBAAgB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM;IAsB1D;;OAEG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAiDzC;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;IAwBpE;;OAEG;IACH,eAAe,CACb,UAAU,EAAE,mBAAmB,EAAE,EACjC,MAAM,EAAE,aAAa,GACpB,MAAM;CAWV;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,aAAa,CAEnD"}
1
+ {"version":3,"file":"svelte-adapter.d.ts","sourceRoot":"","sources":["../../../story-generator/framework-adapters/svelte-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,aAAa,EACb,cAAc,EACd,sBAAsB,EACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,qBAAa,aAAc,SAAQ,oBAAoB;IACrD,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAY;IACxC,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,wBAAwB,EAAE,cAAc,EAAE,CAGjD;IACF,QAAQ,CAAC,gBAAgB,iBAAiB;IAE1C,oBAAoB,CAClB,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM;IAmGT,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM;IAyI/C,mBAAmB,CACjB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,GAChC,MAAM;IA4CT,gBAAgB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM;IAsB1D;;OAEG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAiDzC;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;IAwBpE;;OAEG;IACH,eAAe,CACb,UAAU,EAAE,mBAAmB,EAAE,EACjC,MAAM,EAAE,aAAa,GACpB,MAAM;CAWV;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,aAAa,CAEnD"}
@@ -28,43 +28,40 @@ Use ONLY the Svelte components from the ${componentSystemName} listed below.
28
28
 
29
29
  MANDATORY IMPORTS - First lines of every story file:
30
30
  1. import type { Meta, StoryObj } from '@storybook/svelte';
31
- 2. import ComponentName from '${config.importPath || 'your-library'}/ComponentName.svelte';
31
+ 2. import { ComponentName } from '${config.importPath || 'flowbite-svelte'}';
32
32
 
33
- SVELTE STORY FORMAT:
34
- - Import .svelte files directly
33
+ SVELTE STORY FORMAT (CSF 3.0):
34
+ - Use named imports from flowbite-svelte (NOT default imports from .svelte files)
35
35
  - Props are passed via args object
36
- - Use render function for complex templates
36
+ - Use render function ONLY for multiple components or complex layouts
37
37
 
38
- STORY STRUCTURE (CSF 3.0):
38
+ STORY STRUCTURE:
39
39
  - Meta object with component, title, and parameters
40
- - Stories use args for simple prop passing
41
- - Use render for component composition
40
+ - Stories use args for prop passing
41
+ - Keep stories simple - avoid complex render functions when possible
42
42
 
43
43
  CRITICAL RULES:
44
- - Import Svelte components (default export from .svelte files)
45
- - For slots, use render with a wrapper component
46
- - Events use on: directive in Svelte templates
44
+ - Import using named exports: import { Button, Card } from 'flowbite-svelte';
45
+ - DO NOT use 'slot' property in render functions - it does NOT work
46
+ - DO NOT use 'children' in args
47
+ - For components that need text content, use the component's text/label prop if available
48
+ - For button text, most Flowbite components accept text as a prop or the component handles it
47
49
 
48
- CRITICAL - SVELTE SLOT CONTENT:
49
- - Svelte components use SLOTS for content, NOT children props
50
- - Always use render function with 'slot' property for text/content
51
- - Never use 'children' in args - it will cause runtime errors
52
-
53
- Example structure:
50
+ SIMPLE EXAMPLE (PREFERRED):
54
51
  \`\`\`typescript
55
52
  import type { Meta, StoryObj } from '@storybook/svelte';
56
- import { Button } from 'your-library';
53
+ import { Button } from 'flowbite-svelte';
57
54
 
58
55
  const meta: Meta<Button> = {
59
56
  title: 'Components/Button',
60
57
  component: Button,
61
58
  tags: ['autodocs'],
59
+ parameters: { layout: 'centered' },
62
60
  argTypes: {
63
- variant: {
61
+ color: {
64
62
  control: 'select',
65
- options: ['primary', 'secondary', 'ghost'],
63
+ options: ['primary', 'blue', 'alternative', 'dark', 'light', 'green', 'red'],
66
64
  },
67
- onclick: { action: 'clicked' },
68
65
  },
69
66
  };
70
67
 
@@ -73,201 +70,179 @@ type Story = StoryObj<typeof meta>;
73
70
 
74
71
  export const Primary: Story = {
75
72
  args: {
76
- variant: 'primary',
73
+ color: 'primary',
77
74
  },
78
- render: (args) => ({
75
+ };
76
+
77
+ export const AllColors: Story = {
78
+ render: () => ({
79
79
  Component: Button,
80
- props: args,
81
- slot: 'Click me',
80
+ props: { color: 'blue' },
82
81
  }),
83
82
  };
84
83
  \`\`\`
85
84
 
86
- For stories with slots (using wrapper component):
87
- \`\`\`svelte
88
- <!-- ButtonWithIcon.stories.svelte -->
89
- <script context="module" lang="ts">
90
- import type { Meta } from '@storybook/svelte';
91
- import Button from 'your-library/Button.svelte';
92
- import Icon from 'your-library/Icon.svelte';
93
-
94
- export const meta: Meta<Button> = {
95
- title: 'Components/Button/WithIcon',
96
- component: Button,
97
- };
98
- </script>
99
-
100
- <script lang="ts">
101
- import { Story } from '@storybook/svelte';
102
- </script>
103
-
104
- <Story name="With Icon">
105
- <Button variant="primary">
106
- <Icon slot="icon" name="star" />
107
- Starred
108
- </Button>
109
- </Story>
85
+ FOR MULTIPLE COMPONENTS (use render with template):
86
+ \`\`\`typescript
87
+ import type { Meta, StoryObj } from '@storybook/svelte';
88
+ import { ButtonGroup, Button } from 'flowbite-svelte';
89
+
90
+ const meta: Meta<ButtonGroup> = {
91
+ title: 'Components/ButtonGroup',
92
+ component: ButtonGroup,
93
+ tags: ['autodocs'],
94
+ parameters: { layout: 'centered' },
95
+ };
96
+
97
+ export default meta;
98
+ type Story = StoryObj<typeof meta>;
99
+
100
+ // For simple button groups, just show the component
101
+ export const Default: Story = {
102
+ args: {},
103
+ };
110
104
  \`\`\`
111
105
 
112
106
  SVELTE TEMPLATE SYNTAX:
113
107
  - Props: property={value}
114
- - Events: on:event={handler}
108
+ - Events: onclick={handler} (Svelte 5 syntax, NOT on:click)
115
109
  - Two-way binding: bind:value
116
110
  - Conditionals: {#if condition}...{/if}
117
111
  - Loops: {#each items as item}...{/each}
118
112
 
119
- SLOTS:
120
- - Default slot: Content between tags
121
- - Named slots: <span slot="name">content</span>
122
- - Slot props: let:prop
123
-
124
113
  ${this.getCommonRules()}`;
125
114
  }
126
115
  generateExamples(config) {
127
- const lib = config.importPath || 'your-library';
116
+ const lib = config.importPath || 'flowbite-svelte';
128
117
  return `
129
- ## Example Stories for Svelte
118
+ ## Example Stories for Svelte (CSF 3.0 Format)
130
119
 
131
- ### TypeScript Stories File
120
+ ### Simple Component Story (PREFERRED)
132
121
  \`\`\`typescript
133
122
  import type { Meta, StoryObj } from '@storybook/svelte';
134
- import { Button } from 'your-library';
123
+ import { Button } from '${lib}';
135
124
 
136
125
  const meta: Meta<Button> = {
137
126
  title: 'Components/Button',
138
127
  component: Button,
139
128
  tags: ['autodocs'],
129
+ parameters: { layout: 'centered' },
140
130
  argTypes: {
141
- variant: {
131
+ color: {
142
132
  control: 'select',
143
- options: ['primary', 'secondary', 'ghost'],
133
+ options: ['primary', 'blue', 'alternative', 'dark', 'light', 'green', 'red'],
144
134
  },
145
135
  size: {
146
136
  control: 'select',
147
- options: ['small', 'medium', 'large'],
137
+ options: ['xs', 'sm', 'md', 'lg', 'xl'],
148
138
  },
149
- onclick: { action: 'clicked' },
150
139
  },
151
140
  };
152
141
 
153
142
  export default meta;
154
143
  type Story = StoryObj<typeof meta>;
155
144
 
156
- // IMPORTANT: Use render with slot property for content
157
- export const Default: Story = {
145
+ export const Primary: Story = {
158
146
  args: {
159
- variant: 'primary',
160
- size: 'medium',
147
+ color: 'primary',
148
+ size: 'md',
161
149
  },
162
- render: (args) => ({
163
- Component: Button,
164
- props: args,
165
- slot: 'Button',
166
- }),
167
150
  };
168
151
 
169
152
  export const Disabled: Story = {
170
153
  args: {
171
- variant: 'primary',
154
+ color: 'primary',
172
155
  disabled: true,
173
156
  },
174
- render: (args) => ({
157
+ };
158
+
159
+ export const AllSizes: Story = {
160
+ render: () => ({
175
161
  Component: Button,
176
- props: args,
177
- slot: 'Disabled',
162
+ props: { color: 'blue', size: 'lg' },
178
163
  }),
179
164
  };
180
165
  \`\`\`
181
166
 
182
- ### Svelte Stories File (for complex templates)
183
- \`\`\`svelte
184
- <!-- Card.stories.svelte -->
185
- <script context="module" lang="ts">
186
- import type { Meta } from '@storybook/svelte';
187
- import Card from '${lib}/Card.svelte';
188
- import Button from 'your-library/Button.svelte';
189
- import Text from '${lib}/Text.svelte';
190
-
191
- export const meta: Meta<Card> = {
192
- title: 'Components/Card',
193
- component: Card,
194
- };
195
- </script>
196
-
197
- <script lang="ts">
198
- import { Story, Template } from '@storybook/svelte';
199
- </script>
200
-
201
- <Story name="Product Card">
202
- <Card style="width: 300px">
203
- <img
204
- slot="media"
205
- src="https://picsum.photos/300/200"
206
- alt="Product"
207
- />
208
- <Text slot="title" variant="heading">Product Name</Text>
209
- <Text>$99.00</Text>
210
- <Button slot="actions" variant="primary">Add to Cart</Button>
211
- </Card>
212
- </Story>
213
-
214
- <Story name="Simple Card">
215
- <Card>
216
- <Text>Simple card content</Text>
217
- </Card>
218
- </Story>
219
- \`\`\`
167
+ ### Card Component Story
168
+ \`\`\`typescript
169
+ import type { Meta, StoryObj } from '@storybook/svelte';
170
+ import { Card } from '${lib}';
220
171
 
221
- ### With Reactive State
222
- \`\`\`svelte
223
- <!-- Input.stories.svelte -->
224
- <script context="module" lang="ts">
225
- import type { Meta } from '@storybook/svelte';
226
- import Input from '${lib}/Input.svelte';
227
-
228
- export const meta: Meta<Input> = {
229
- title: 'Components/Input',
230
- component: Input,
231
- };
232
- </script>
233
-
234
- <script lang="ts">
235
- import { Story } from '@storybook/svelte';
236
- let value = '';
237
- </script>
238
-
239
- <Story name="Controlled">
240
- <div>
241
- <Input bind:value placeholder="Type here..." />
242
- <p>Value: {value}</p>
243
- </div>
244
- </Story>
172
+ const meta: Meta<Card> = {
173
+ title: 'Components/Card',
174
+ component: Card,
175
+ tags: ['autodocs'],
176
+ parameters: { layout: 'centered' },
177
+ };
178
+
179
+ export default meta;
180
+ type Story = StoryObj<typeof meta>;
181
+
182
+ export const Default: Story = {
183
+ args: {
184
+ class: 'max-w-sm',
185
+ },
186
+ };
187
+
188
+ export const WithImage: Story = {
189
+ args: {
190
+ img: 'https://picsum.photos/300/200',
191
+ class: 'max-w-sm',
192
+ },
193
+ };
194
+
195
+ export const Horizontal: Story = {
196
+ args: {
197
+ horizontal: true,
198
+ class: 'max-w-xl',
199
+ },
200
+ };
245
201
  \`\`\`
246
202
 
247
- ### With Event Handling
203
+ ### Alert Component Story
248
204
  \`\`\`typescript
249
205
  import type { Meta, StoryObj } from '@storybook/svelte';
250
- import { action } from '@storybook/addon-actions';
251
- import { Button } from 'your-library';
206
+ import { Alert } from '${lib}';
252
207
 
253
- const meta: Meta<Button> = {
254
- title: 'Components/Button',
255
- component: Button,
208
+ const meta: Meta<Alert> = {
209
+ title: 'Components/Alert',
210
+ component: Alert,
211
+ tags: ['autodocs'],
212
+ parameters: { layout: 'centered' },
213
+ argTypes: {
214
+ color: {
215
+ control: 'select',
216
+ options: ['primary', 'blue', 'red', 'green', 'yellow', 'dark'],
217
+ },
218
+ },
256
219
  };
257
220
 
258
221
  export default meta;
259
222
  type Story = StoryObj<typeof meta>;
260
223
 
261
- export const WithClickHandler: Story = {
224
+ export const Info: Story = {
262
225
  args: {
263
- variant: 'primary',
264
- onclick: action('button-clicked'),
226
+ color: 'blue',
227
+ },
228
+ };
229
+
230
+ export const Success: Story = {
231
+ args: {
232
+ color: 'green',
233
+ },
234
+ };
235
+
236
+ export const Warning: Story = {
237
+ args: {
238
+ color: 'yellow',
239
+ },
240
+ };
241
+
242
+ export const Error: Story = {
243
+ args: {
244
+ color: 'red',
265
245
  },
266
- render: (args) => ({
267
- Component: Button,
268
- props: args,
269
- slot: 'Click me',
270
- }),
271
246
  };
272
247
  \`\`\`
273
248
  `;
@@ -1 +1 @@
1
- {"version":3,"file":"storyValidator.d.ts","sourceRoot":"","sources":["../../story-generator/storyValidator.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,eAAe,EAAE,CA2CrE"}
1
+ {"version":3,"file":"storyValidator.d.ts","sourceRoot":"","sources":["../../story-generator/storyValidator.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,eAAe,EAAE,CA+CrE"}
@@ -7,8 +7,12 @@ export function validateStory(storyContent) {
7
7
  { pattern: /UNSAFE_style\s*=\s*\{/i, message: 'The `UNSAFE_style` prop is strictly forbidden. Do not use it for any reason.' },
8
8
  { pattern: /UNSAFE_className\s*=\s*['"]/i, message: 'The `UNSAFE_className` prop is forbidden.' },
9
9
  { pattern: /<Text\s+as\s*=\s*["']h[1-6]["']/i, message: 'Text component does not support heading elements (h1-h6) in the "as" prop. Use Heading component instead.' },
10
- // Remove overly strict rules - divs, imgs, and inline styles are fine in moderation
11
- // Only check for actual syntax errors or patterns that would break Storybook
10
+ // Catch imports that don't exist in production environments
11
+ { pattern: /from\s+['"]@storybook\/addon-actions['"]/i, message: 'Do not import from @storybook/addon-actions. Use argTypes with action property instead: argTypes: { onClick: { action: "clicked" } }' },
12
+ // Catch Svelte slot property which doesn't work in modern Storybook
13
+ { pattern: /slot:\s*['"][^'"]+['"]/i, message: 'The slot property in render functions does not work in Svelte Storybook. Use simple args-based stories instead.' },
14
+ // Catch abbreviated Material icon names that will render as text instead of icons
15
+ { pattern: /<mat-icon>\s*(fav|ho|de|se|sta|che|add|rem|edi|sav|can|men|clo|sea)\s*<\/mat-icon>/i, message: 'Material icon name appears to be abbreviated. Use full icon names: "favorite" (not "fav"), "home" (not "ho"), "delete" (not "de"), "settings" (not "se"), etc.' },
12
16
  ];
13
17
  lines.forEach((line, index) => {
14
18
  for (const { pattern, message } of forbiddenPatterns) {