@oaysus/cli 0.1.4 → 0.1.6

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.
Files changed (80) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +16 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/switch.d.ts +6 -0
  5. package/dist/commands/switch.d.ts.map +1 -0
  6. package/dist/commands/switch.js +120 -0
  7. package/dist/commands/switch.js.map +1 -0
  8. package/dist/components/App.d.ts +2 -0
  9. package/dist/components/App.d.ts.map +1 -1
  10. package/dist/components/App.js +3 -0
  11. package/dist/components/App.js.map +1 -1
  12. package/dist/lib/shared/auth-middleware.js +1 -1
  13. package/dist/lib/shared/auth-middleware.js.map +1 -1
  14. package/dist/lib/shared/auth.d.ts +8 -0
  15. package/dist/lib/shared/auth.d.ts.map +1 -1
  16. package/dist/lib/shared/auth.js +44 -0
  17. package/dist/lib/shared/auth.js.map +1 -1
  18. package/dist/lib/shared/commands.d.ts.map +1 -1
  19. package/dist/lib/shared/commands.js +4 -0
  20. package/dist/lib/shared/commands.js.map +1 -1
  21. package/dist/screens/SwitchScreen.d.ts +14 -0
  22. package/dist/screens/SwitchScreen.d.ts.map +1 -0
  23. package/dist/screens/SwitchScreen.js +196 -0
  24. package/dist/screens/SwitchScreen.js.map +1 -0
  25. package/dist/screens/WelcomeScreen.d.ts +2 -0
  26. package/dist/screens/WelcomeScreen.d.ts.map +1 -1
  27. package/dist/screens/WelcomeScreen.js +4 -1
  28. package/dist/screens/WelcomeScreen.js.map +1 -1
  29. package/dist/types/index.d.ts +1 -0
  30. package/dist/types/index.d.ts.map +1 -1
  31. package/package.json +3 -2
  32. package/src/templates/react-theme-pack/.storybook/main.ts.template +16 -0
  33. package/src/templates/react-theme-pack/.storybook/preview.ts.template +43 -0
  34. package/src/templates/react-theme-pack/.storybook/utils/schemaToArgTypes.ts.template +92 -0
  35. package/src/templates/react-theme-pack/README.md.template +71 -0
  36. package/src/templates/react-theme-pack/components/example-schema.json.template +24 -0
  37. package/src/templates/react-theme-pack/components/example.stories.tsx.template +29 -0
  38. package/src/templates/react-theme-pack/components/example.tsx.template +28 -0
  39. package/src/templates/react-theme-pack/package.json.template +51 -0
  40. package/src/templates/react-theme-pack/preview/generate.js.template +218 -0
  41. package/src/templates/react-theme-pack/preview/server.js.template +40 -0
  42. package/src/templates/react-theme-pack/shared/types.ts.template +19 -0
  43. package/src/templates/react-theme-pack/shared/utils.ts.template +30 -0
  44. package/src/templates/react-theme-pack/styles/tailwind.css.template +1 -0
  45. package/src/templates/react-theme-pack/tsconfig.json.template +24 -0
  46. package/src/templates/react-theme-pack/vite.config.ts.template +12 -0
  47. package/src/templates/shared/.gitignore.template +46 -0
  48. package/src/templates/shared/postcss.config.js.template +6 -0
  49. package/src/templates/shared/tailwind.config.js.template +11 -0
  50. package/src/templates/svelte-theme-pack/.storybook/main.ts.template +13 -0
  51. package/src/templates/svelte-theme-pack/.storybook/preview.ts.template +40 -0
  52. package/src/templates/svelte-theme-pack/.storybook/utils/schemaToArgTypes.ts.template +107 -0
  53. package/src/templates/svelte-theme-pack/README.md.template +67 -0
  54. package/src/templates/svelte-theme-pack/components/example-schema.json.template +24 -0
  55. package/src/templates/svelte-theme-pack/components/example.stories.ts.template +34 -0
  56. package/src/templates/svelte-theme-pack/components/example.svelte.template +29 -0
  57. package/src/templates/svelte-theme-pack/package.json.template +45 -0
  58. package/src/templates/svelte-theme-pack/preview/generate.js.template +221 -0
  59. package/src/templates/svelte-theme-pack/preview/server.js.template +40 -0
  60. package/src/templates/svelte-theme-pack/shared/types.ts.template +31 -0
  61. package/src/templates/svelte-theme-pack/shared/utils.ts.template +37 -0
  62. package/src/templates/svelte-theme-pack/styles/tailwind.css.template +1 -0
  63. package/src/templates/svelte-theme-pack/svelte.config.js.template +5 -0
  64. package/src/templates/svelte-theme-pack/tsconfig.json.template +27 -0
  65. package/src/templates/svelte-theme-pack/vite.config.ts.template +12 -0
  66. package/src/templates/vue-theme-pack/.storybook/main.ts.template +13 -0
  67. package/src/templates/vue-theme-pack/.storybook/preview.ts.template +40 -0
  68. package/src/templates/vue-theme-pack/.storybook/utils/schemaToArgTypes.ts.template +107 -0
  69. package/src/templates/vue-theme-pack/README.md.template +69 -0
  70. package/src/templates/vue-theme-pack/components/example-schema.json.template +24 -0
  71. package/src/templates/vue-theme-pack/components/example.stories.ts.template +34 -0
  72. package/src/templates/vue-theme-pack/components/example.vue.template +32 -0
  73. package/src/templates/vue-theme-pack/package.json.template +44 -0
  74. package/src/templates/vue-theme-pack/preview/generate.js.template +218 -0
  75. package/src/templates/vue-theme-pack/preview/server.js.template +40 -0
  76. package/src/templates/vue-theme-pack/shared/types.ts.template +31 -0
  77. package/src/templates/vue-theme-pack/shared/utils.ts.template +37 -0
  78. package/src/templates/vue-theme-pack/styles/tailwind.css.template +1 -0
  79. package/src/templates/vue-theme-pack/tsconfig.json.template +27 -0
  80. package/src/templates/vue-theme-pack/vite.config.ts.template +12 -0
@@ -0,0 +1,24 @@
1
+ {
2
+ "type": "{{COMPONENT_TYPE}}",
3
+ "displayName": "{{COMPONENT_NAME}}",
4
+ "description": "{{DESCRIPTION}}",
5
+ "category": "{{CATEGORY}}",
6
+ "props": {
7
+ "heading": {
8
+ "type": "string",
9
+ "default": "Welcome"
10
+ },
11
+ "subheading": {
12
+ "type": "string",
13
+ "default": "Your amazing tagline"
14
+ },
15
+ "buttonText": {
16
+ "type": "string",
17
+ "default": "Get Started"
18
+ },
19
+ "buttonLink": {
20
+ "type": "string",
21
+ "default": "#"
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,34 @@
1
+ import type { Meta, StoryObj } from '@storybook/svelte';
2
+ import {{COMPONENT_NAME}} from './{{COMPONENT_NAME}}.svelte';
3
+ import { schemaToArgTypes, schemaToDefaultArgs } from '../.storybook/utils/schemaToArgTypes';
4
+ import schema from './schema.json';
5
+
6
+ const meta: Meta<typeof {{COMPONENT_NAME}}> = {
7
+ title: 'Components/{{COMPONENT_NAME}}',
8
+ component: {{COMPONENT_NAME}},
9
+ argTypes: schemaToArgTypes(schema),
10
+ args: schemaToDefaultArgs(schema),
11
+ parameters: {
12
+ layout: 'fullscreen'
13
+ }
14
+ };
15
+
16
+ export default meta;
17
+ type Story = StoryObj<typeof {{COMPONENT_NAME}}>;
18
+
19
+ /**
20
+ * Default story using schema defaults
21
+ */
22
+ export const Default: Story = {};
23
+
24
+ /**
25
+ * Custom example with modified props
26
+ */
27
+ export const CustomExample: Story = {
28
+ args: {
29
+ heading: 'Custom Heading',
30
+ subheading: 'This is a custom subheading',
31
+ buttonText: 'Click Me',
32
+ buttonLink: '/custom-link'
33
+ }
34
+ };
@@ -0,0 +1,29 @@
1
+ <script lang="ts">
2
+ // Svelte 5 runes mode - use $props() instead of export let
3
+ interface Props {
4
+ heading?: string;
5
+ subheading?: string;
6
+ buttonText?: string;
7
+ buttonLink?: string;
8
+ }
9
+
10
+ let {
11
+ heading = 'Welcome',
12
+ subheading = 'Your amazing tagline',
13
+ buttonText = 'Get Started',
14
+ buttonLink = '#'
15
+ }: Props = $props();
16
+ </script>
17
+
18
+ <div class="bg-linear-to-r from-orange-500 via-pink-500 to-purple-600 text-white py-24 px-4 min-h-[500px] flex items-center justify-center border-8 border-yellow-400 shadow-2xl">
19
+ <div class="max-w-4xl mx-auto text-center">
20
+ <h1 class="text-6xl font-black mb-6 text-white drop-shadow-lg">{heading}</h1>
21
+ <p class="text-2xl mb-10 text-yellow-200 font-semibold">{subheading}</p>
22
+ <a
23
+ href={buttonLink}
24
+ class="inline-block bg-linear-to-r from-green-400 to-cyan-500 text-white px-8 py-4 rounded-full text-xl font-bold shadow-xl hover:scale-110 hover:rotate-2 transition-all duration-300 cursor-pointer no-underline"
25
+ >
26
+ {buttonText}
27
+ </a>
28
+ </div>
29
+ </div>
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "{{PROJECT_NAME}}",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "{{DESCRIPTION}}",
6
+ "author": "{{AUTHOR}}",
7
+ "license": "MIT",
8
+ "scripts": {
9
+ "preview": "node preview/generate.js && node preview/server.js",
10
+ "preview:build": "node preview/generate.js",
11
+ "preview:start": "node preview/server.js",
12
+ "storybook": "storybook dev -p 6006",
13
+ "build-storybook": "storybook build -o storybook-static"
14
+ },
15
+ "peerDependencies": {
16
+ "svelte": "^5.43.14"
17
+ },
18
+ "devDependencies": {
19
+ "@storybook/addon-a11y": "^10.1.2",
20
+ "@storybook/svelte": "^10.1.2",
21
+ "@storybook/svelte-vite": "^10.1.2",
22
+ "@sveltejs/vite-plugin-svelte": "^5.0.0",
23
+ "@tailwindcss/cli": "^4.1.17",
24
+ "@tailwindcss/postcss": "^4.1.17",
25
+ "autoprefixer": "^10.4.22",
26
+ "express": "^5.1.0",
27
+ "postcss": "^8.5.6",
28
+ "storybook": "^10.1.2",
29
+ "svelte": "^5.43.14",
30
+ "svelte-check": "^3.6.0",
31
+ "tailwindcss": "^4.1.17",
32
+ "typescript": "^5.9.3",
33
+ "vite": "^6.0.0"
34
+ },
35
+ "oaysus": {
36
+ "theme": {
37
+ "name": "{{PROJECT_NAME}}-pack",
38
+ "displayName": "{{DISPLAY_NAME}}",
39
+ "description": "{{DESCRIPTION}}",
40
+ "category": "marketing",
41
+ "isPremium": false,
42
+ "tags": ["marketing", "components", "theme", "svelte", "performance"]
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Preview HTML Generator - Svelte
3
+ * Generates a local preview page that mimics the dashboard's preview-shell.html
4
+ */
5
+
6
+ import fs from 'fs';
7
+ import path from 'path';
8
+ import { fileURLToPath } from 'url';
9
+
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = path.dirname(__filename);
12
+
13
+ const BUILD_DIR = path.join(__dirname, '../.oaysus-build');
14
+ const PREVIEW_DIST = path.join(__dirname, 'dist');
15
+ const OUTPUT_HTML = path.join(PREVIEW_DIST, 'index.html');
16
+
17
+ // Ensure preview/dist directory exists
18
+ if (!fs.existsSync(PREVIEW_DIST)) {
19
+ fs.mkdirSync(PREVIEW_DIST, { recursive: true });
20
+ }
21
+
22
+ // Check if build exists
23
+ if (!fs.existsSync(BUILD_DIR)) {
24
+ console.error('❌ Error: .oaysus-build directory not found!');
25
+ console.error(' Run "oaysus build" first to build your components.');
26
+ process.exit(1);
27
+ }
28
+
29
+ // Read all components
30
+ const components = [];
31
+ const componentDirs = fs.readdirSync(BUILD_DIR).filter(dir => {
32
+ const fullPath = path.join(BUILD_DIR, dir);
33
+ return fs.statSync(fullPath).isDirectory() && dir !== 'deps';
34
+ });
35
+
36
+ for (const dir of componentDirs) {
37
+ const schemaPath = path.join(BUILD_DIR, dir, 'schema.json');
38
+ const jsPath = path.join(BUILD_DIR, dir, 'index.js');
39
+
40
+ if (fs.existsSync(schemaPath) && fs.existsSync(jsPath)) {
41
+ const schema = JSON.parse(fs.readFileSync(schemaPath, 'utf-8'));
42
+ components.push({
43
+ name: dir,
44
+ displayName: schema.displayName || dir,
45
+ schema,
46
+ jsPath: `/build/${dir}/index.js`
47
+ });
48
+ }
49
+ }
50
+
51
+ // Read import map
52
+ let importMap = { imports: {} };
53
+ const importMapPath = path.join(BUILD_DIR, 'import-map.json');
54
+ if (fs.existsSync(importMapPath)) {
55
+ importMap = JSON.parse(fs.readFileSync(importMapPath, 'utf-8'));
56
+ }
57
+
58
+ // Convert R2 URLs to local URLs
59
+ const localImportMap = { imports: {} };
60
+ for (const [key, value] of Object.entries(importMap.imports)) {
61
+ // Convert R2 URL to local path
62
+ // Example: https://r2.dev/.../deps/svelte@4.2.0/index.js → /build/deps/svelte@4.2.0/index.js
63
+ const match = value.match(/deps\/(.*)/);
64
+ if (match) {
65
+ localImportMap.imports[key] = `/build/deps/${match[1]}`;
66
+ } else {
67
+ localImportMap.imports[key] = value;
68
+ }
69
+ }
70
+
71
+ // Generate HTML
72
+ const html = `<!DOCTYPE html>
73
+ <html lang="en">
74
+ <head>
75
+ <meta charset="UTF-8">
76
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
77
+ <title>Component Preview - {{PROJECT_NAME}}</title>
78
+ <link rel="stylesheet" href="/build/theme.css">
79
+ <style>
80
+ body {
81
+ margin: 0;
82
+ padding: 0;
83
+ }
84
+ </style>
85
+ </head>
86
+ <body>
87
+ ${components.map(comp => `<div id="preview-${comp.name}"></div>`).join('\n ')}
88
+
89
+ <!-- Import Map -->
90
+ <script type="importmap">
91
+ ${JSON.stringify(localImportMap, null, 2)}
92
+ </script>
93
+
94
+ <!-- Component Loading Script -->
95
+ <script type="module">
96
+ // Component configurations
97
+ const components = ${JSON.stringify(components, null, 2)};
98
+
99
+ // Load Svelte mount function
100
+ let mount;
101
+
102
+ async function loadSvelte() {
103
+ try {
104
+ const svelteModule = await import('svelte');
105
+ mount = svelteModule.mount;
106
+
107
+ if (!mount) {
108
+ throw new Error('mount not found in svelte module');
109
+ }
110
+
111
+ console.log('✅ Svelte mount function loaded');
112
+ } catch (error) {
113
+ console.error('❌ Failed to load Svelte:', error);
114
+ throw error;
115
+ }
116
+ }
117
+
118
+ // Load and render a Svelte component
119
+ async function loadComponent(comp) {
120
+ const container = document.getElementById(\`preview-\${comp.name}\`);
121
+
122
+ try {
123
+ console.log(\`Loading component: \${comp.displayName}\`);
124
+
125
+ // Import the component module
126
+ const module = await import(comp.jsPath);
127
+ console.log(\`✅ Loaded module for \${comp.displayName}:\`, module);
128
+
129
+ // Get the component - Svelte 5 uses default export
130
+ const Component = module.default;
131
+
132
+ if (!Component || typeof Component !== 'function') {
133
+ throw new Error('Component must be exported as default and must be a function');
134
+ }
135
+
136
+ console.log(\`✅ Component function for \${comp.displayName}:\`, Component);
137
+
138
+ // Get default props from schema
139
+ const defaultProps = {};
140
+ if (comp.schema.props) {
141
+ for (const [key, prop] of Object.entries(comp.schema.props)) {
142
+ if (prop.default !== undefined) {
143
+ defaultProps[key] = prop.default;
144
+ } else if (prop.type === 'object' && prop.properties) {
145
+ // Build nested object from properties
146
+ const nestedObj = {};
147
+ for (const [nestedKey, nestedProp] of Object.entries(prop.properties)) {
148
+ if (nestedProp.default !== undefined) {
149
+ nestedObj[nestedKey] = nestedProp.default;
150
+ }
151
+ }
152
+ if (Object.keys(nestedObj).length > 0) {
153
+ defaultProps[key] = nestedObj;
154
+ }
155
+ }
156
+ }
157
+ }
158
+
159
+ console.log(\`📝 Rendering \${comp.displayName} with props:\`, defaultProps);
160
+
161
+ // Mount Svelte 5 component using mount() function
162
+ const app = mount(Component, {
163
+ target: container,
164
+ props: defaultProps
165
+ });
166
+
167
+ console.log(\`✅ Successfully mounted \${comp.displayName}\`, app);
168
+ return app;
169
+ } catch (error) {
170
+ console.error(\`❌ Failed to load \${comp.displayName}:\`, error);
171
+ container.innerHTML = \`
172
+ <div class="error">
173
+ <strong>Error loading \${comp.displayName}:</strong><br>
174
+ \${error.message}
175
+ </div>
176
+ \`;
177
+ }
178
+ }
179
+
180
+ // Main execution
181
+ async function main() {
182
+ try {
183
+ console.log('🚀 Starting component preview...');
184
+
185
+ // Load Svelte legacy adapter first
186
+ await loadSvelte();
187
+
188
+ // Load all components
189
+ for (const comp of components) {
190
+ await loadComponent(comp);
191
+ }
192
+
193
+ console.log('✅ All components loaded successfully!');
194
+ } catch (error) {
195
+ console.error('❌ Preview failed:', error);
196
+ }
197
+ }
198
+
199
+ main();
200
+ </script>
201
+ </body>
202
+ </html>
203
+ `;
204
+
205
+ // Write HTML file
206
+ fs.writeFileSync(OUTPUT_HTML, html);
207
+
208
+ console.log(`
209
+ ✅ Preview HTML generated successfully!
210
+
211
+ 📁 Location: ${OUTPUT_HTML}
212
+
213
+ 🎯 Components found: ${components.length}
214
+ ${components.map(c => ` • ${c.displayName} (${c.name})`).join('\n')}
215
+
216
+ 🚀 Start the preview server with:
217
+ pnpm run preview:start
218
+
219
+ Or run the full preview (generate + serve):
220
+ pnpm run preview
221
+ `);
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Local Preview Server
3
+ * Serves the built components for local testing without uploading to R2
4
+ */
5
+
6
+ import express from 'express';
7
+ import path from 'path';
8
+ import { fileURLToPath } from 'url';
9
+
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = path.dirname(__filename);
12
+
13
+ const app = express();
14
+ const PORT = 4000;
15
+
16
+ // Serve .oaysus-build directory (component bundles and dependencies)
17
+ app.use('/build', express.static(path.join(__dirname, '../.oaysus-build')));
18
+
19
+ // Serve preview directory (HTML and assets)
20
+ app.use(express.static(path.join(__dirname, 'dist')));
21
+
22
+ // Handle 404s
23
+ app.use((req, res) => {
24
+ res.status(404).send('File not found');
25
+ });
26
+
27
+ // Start server
28
+ app.listen(PORT, () => {
29
+ console.log(`
30
+ ╔════════════════════════════════════════════════════════════╗
31
+ ║ ║
32
+ ║ 🎨 Component Preview Server ║
33
+ ║ ║
34
+ ║ Running at: http://localhost:${PORT} ║
35
+ ║ ║
36
+ ║ Press Ctrl+C to stop the server ║
37
+ ║ ║
38
+ ╚════════════════════════════════════════════════════════════╝
39
+ `);
40
+ });
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Shared TypeScript types for Svelte components
3
+ */
4
+
5
+ export interface BaseComponentProps {
6
+ class?: string;
7
+ }
8
+
9
+ export interface ButtonProps extends BaseComponentProps {
10
+ text: string;
11
+ link: string;
12
+ variant?: 'primary' | 'secondary';
13
+ }
14
+
15
+ export interface HeadingProps extends BaseComponentProps {
16
+ heading: string;
17
+ subheading?: string;
18
+ }
19
+
20
+ export interface ImageProps {
21
+ src: string;
22
+ alt: string;
23
+ width?: number;
24
+ height?: number;
25
+ }
26
+
27
+ export interface LinkProps {
28
+ text: string;
29
+ href: string;
30
+ target?: '_blank' | '_self';
31
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Shared utility functions for Svelte components
3
+ */
4
+
5
+ /**
6
+ * Combine class names, filtering out falsy values
7
+ */
8
+ export function cn(...classes: (string | undefined | null | false)[]): string {
9
+ return classes.filter(Boolean).join(' ');
10
+ }
11
+
12
+ /**
13
+ * Format a date to a readable string
14
+ */
15
+ export function formatDate(date: Date | string): string {
16
+ const d = typeof date === 'string' ? new Date(date) : date;
17
+ return d.toLocaleDateString('en-US', {
18
+ year: 'numeric',
19
+ month: 'long',
20
+ day: 'numeric'
21
+ });
22
+ }
23
+
24
+ /**
25
+ * Truncate text to a maximum length
26
+ */
27
+ export function truncate(text: string, maxLength: number): string {
28
+ if (text.length <= maxLength) return text;
29
+ return text.slice(0, maxLength).trim() + '...';
30
+ }
31
+
32
+ /**
33
+ * Generate a unique ID
34
+ */
35
+ export function generateId(prefix: string = 'id'): string {
36
+ return `${prefix}-${Math.random().toString(36).substr(2, 9)}`;
37
+ }
@@ -0,0 +1 @@
1
+ @import "tailwindcss";
@@ -0,0 +1,5 @@
1
+ import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
2
+
3
+ export default {
4
+ preprocess: vitePreprocess()
5
+ };
@@ -0,0 +1,27 @@
1
+ {
2
+ "extends": "./.svelte-kit/tsconfig.json",
3
+ "compilerOptions": {
4
+ "target": "ES2020",
5
+ "useDefineForClassFields": true,
6
+ "module": "ESNext",
7
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
8
+ "skipLibCheck": true,
9
+ "moduleResolution": "bundler",
10
+ "allowImportingTsExtensions": true,
11
+ "resolveJsonModule": true,
12
+ "isolatedModules": true,
13
+ "noEmit": true,
14
+ "strict": true,
15
+ "noUnusedLocals": true,
16
+ "noUnusedParameters": true,
17
+ "noFallthroughCasesInSwitch": true,
18
+ "esModuleInterop": true,
19
+ "forceConsistentCasingInFileNames": true,
20
+ "baseUrl": ".",
21
+ "paths": {
22
+ "@/*": ["./*"]
23
+ }
24
+ },
25
+ "include": ["**/*.ts", "**/*.svelte"],
26
+ "exclude": ["node_modules", "dist", ".oaysus-build"]
27
+ }
@@ -0,0 +1,12 @@
1
+ import { defineConfig } from 'vite';
2
+ import { svelte } from '@sveltejs/vite-plugin-svelte';
3
+ import { resolve } from 'path';
4
+
5
+ export default defineConfig({
6
+ plugins: [svelte()],
7
+ resolve: {
8
+ alias: {
9
+ '@': resolve(__dirname, './')
10
+ }
11
+ }
12
+ });
@@ -0,0 +1,13 @@
1
+ import type { StorybookConfig } from '@storybook/vue3-vite';
2
+
3
+ const config: StorybookConfig = {
4
+ stories: ['../components/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
5
+ addons: ['@storybook/addon-a11y'],
6
+ framework: {
7
+ name: '@storybook/vue3-vite',
8
+ options: {}
9
+ },
10
+ docs: {}
11
+ };
12
+
13
+ export default config;
@@ -0,0 +1,40 @@
1
+ import type { Preview } from '@storybook/vue3';
2
+ import '../styles/tailwind.css';
3
+
4
+ const preview: Preview = {
5
+ parameters: {
6
+ controls: {
7
+ matchers: {
8
+ color: /(background|color)$/i,
9
+ date: /Date$/i
10
+ }
11
+ },
12
+ viewport: {
13
+ viewports: {
14
+ mobile: {
15
+ name: 'Mobile',
16
+ styles: { width: '375px', height: '667px' }
17
+ },
18
+ tablet: {
19
+ name: 'Tablet',
20
+ styles: { width: '768px', height: '1024px' }
21
+ },
22
+ desktop: {
23
+ name: 'Desktop',
24
+ styles: { width: '1280px', height: '800px' }
25
+ }
26
+ }
27
+ },
28
+ backgrounds: {
29
+ default: 'light',
30
+ values: [
31
+ { name: 'light', value: '#ffffff' },
32
+ { name: 'dark', value: '#1f2937' },
33
+ { name: 'gray', value: '#f3f4f6' }
34
+ ]
35
+ },
36
+ layout: 'fullscreen'
37
+ }
38
+ };
39
+
40
+ export default preview;
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Converts a component schema.json to Storybook ArgTypes
3
+ * This enables automatic control generation from Oaysus component schemas
4
+ */
5
+
6
+ interface SchemaProp {
7
+ type: string;
8
+ displayName?: string;
9
+ description?: string;
10
+ default?: unknown;
11
+ min?: number;
12
+ max?: number;
13
+ step?: number;
14
+ properties?: Record<string, SchemaProp>;
15
+ fields?: Array<{ name: string; type: string; default?: unknown }>;
16
+ }
17
+
18
+ interface ComponentSchema {
19
+ type: string;
20
+ displayName: string;
21
+ description?: string;
22
+ category?: string;
23
+ props: Record<string, SchemaProp>;
24
+ }
25
+
26
+ interface ArgType {
27
+ name?: string;
28
+ description?: string;
29
+ control: { type: string; [key: string]: unknown };
30
+ table?: {
31
+ category?: string;
32
+ defaultValue?: { summary: string };
33
+ };
34
+ }
35
+
36
+ /**
37
+ * Map schema prop type to Storybook control type
38
+ */
39
+ function propTypeToControl(prop: SchemaProp): ArgType['control'] {
40
+ switch (prop.type) {
41
+ case 'color':
42
+ return {
43
+ type: 'color',
44
+ presetColors: ['#3b82f6', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', '#ec4899']
45
+ };
46
+ case 'range':
47
+ return {
48
+ type: 'range',
49
+ min: prop.min ?? 0,
50
+ max: prop.max ?? 100,
51
+ step: prop.step ?? 1
52
+ };
53
+ case 'number':
54
+ return { type: 'number' };
55
+ case 'boolean':
56
+ return { type: 'boolean' };
57
+ case 'textarea':
58
+ case 'string':
59
+ case 'text':
60
+ case 'link':
61
+ return { type: 'text' };
62
+ case 'image':
63
+ case 'array':
64
+ case 'object':
65
+ return { type: 'object' };
66
+ default:
67
+ return { type: 'text' };
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Convert full schema to Storybook ArgTypes object
73
+ */
74
+ export function schemaToArgTypes(schema: ComponentSchema): Record<string, ArgType> {
75
+ const argTypes: Record<string, ArgType> = {};
76
+
77
+ for (const [propName, propDef] of Object.entries(schema.props)) {
78
+ argTypes[propName] = {
79
+ name: propDef.displayName || propName,
80
+ description: propDef.description || '',
81
+ control: propTypeToControl(propDef),
82
+ table: {
83
+ category: 'Props',
84
+ defaultValue: propDef.default !== undefined
85
+ ? { summary: JSON.stringify(propDef.default) }
86
+ : undefined
87
+ }
88
+ };
89
+ }
90
+
91
+ return argTypes;
92
+ }
93
+
94
+ /**
95
+ * Extract default args from schema for story initialization
96
+ */
97
+ export function schemaToDefaultArgs(schema: ComponentSchema): Record<string, unknown> {
98
+ const args: Record<string, unknown> = {};
99
+
100
+ for (const [propName, propDef] of Object.entries(schema.props)) {
101
+ if (propDef.default !== undefined) {
102
+ args[propName] = propDef.default;
103
+ }
104
+ }
105
+
106
+ return args;
107
+ }