@idealyst/mcp-server 1.2.7 → 1.2.8
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.
- package/dist/data/components/Button.d.ts.map +1 -1
- package/dist/data/components/Button.js +5 -6
- package/dist/data/components/Button.js.map +1 -1
- package/dist/data/components/Input.d.ts.map +1 -1
- package/dist/data/components/Input.js +4 -3
- package/dist/data/components/Input.js.map +1 -1
- package/dist/data/components/Text.d.ts.map +1 -1
- package/dist/data/components/Text.js +26 -19
- package/dist/data/components/Text.js.map +1 -1
- package/dist/data/framework-guides.d.ts.map +1 -1
- package/dist/data/framework-guides.js +842 -174
- package/dist/data/framework-guides.js.map +1 -1
- package/dist/data/translate-guides.d.ts +2 -0
- package/dist/data/translate-guides.d.ts.map +1 -0
- package/dist/data/translate-guides.js +1030 -0
- package/dist/data/translate-guides.js.map +1 -0
- package/dist/generated/types.json +247 -243
- package/dist/index.js +71 -2
- package/dist/index.js.map +1 -1
- package/dist/tools/get-types.d.ts +11 -0
- package/dist/tools/get-types.d.ts.map +1 -1
- package/dist/tools/get-types.js +25 -0
- package/dist/tools/get-types.js.map +1 -1
- package/package.json +4 -4
|
@@ -12,45 +12,49 @@ npx @idealyst/cli init my-app
|
|
|
12
12
|
cd my-app
|
|
13
13
|
\`\`\`
|
|
14
14
|
|
|
15
|
-
This creates a monorepo workspace with:
|
|
15
|
+
This single command creates a **complete monorepo workspace** with all 5 packages:
|
|
16
|
+
- \`packages/web/\` - React web app (Vite)
|
|
17
|
+
- \`packages/native/\` - React Native mobile app
|
|
18
|
+
- \`packages/api/\` - tRPC API server with GraphQL
|
|
19
|
+
- \`packages/database/\` - Prisma database layer
|
|
20
|
+
- \`packages/shared/\` - Shared utilities and tRPC client
|
|
21
|
+
|
|
22
|
+
Plus:
|
|
16
23
|
- Yarn 3 workspace setup
|
|
17
24
|
- TypeScript configuration
|
|
18
25
|
- Jest testing setup
|
|
19
26
|
- Git repository
|
|
20
27
|
- Dev container configuration
|
|
21
28
|
|
|
22
|
-
### 2.
|
|
29
|
+
### 2. Start Development
|
|
23
30
|
|
|
24
|
-
Create a web app:
|
|
25
31
|
\`\`\`bash
|
|
26
|
-
|
|
27
|
-
|
|
32
|
+
# Start web dev server
|
|
33
|
+
cd packages/web
|
|
34
|
+
yarn dev
|
|
28
35
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
\`\`\`
|
|
36
|
+
# Start native dev (in another terminal)
|
|
37
|
+
cd packages/native
|
|
38
|
+
yarn start
|
|
33
39
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
# Start API server (in another terminal)
|
|
41
|
+
cd packages/api
|
|
42
|
+
yarn dev
|
|
37
43
|
\`\`\`
|
|
38
44
|
|
|
39
|
-
|
|
40
|
-
\`\`\`bash
|
|
41
|
-
npx @idealyst/cli create database --type database
|
|
42
|
-
\`\`\`
|
|
45
|
+
### 3. Configure Babel (Required for Styling)
|
|
43
46
|
|
|
44
|
-
|
|
47
|
+
Add the Idealyst plugin to your babel.config.js:
|
|
45
48
|
|
|
46
|
-
\`\`\`
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
\`\`\`javascript
|
|
50
|
+
module.exports = {
|
|
51
|
+
presets: ['module:@react-native/babel-preset'],
|
|
52
|
+
plugins: [
|
|
53
|
+
['@idealyst/theme/plugin', {
|
|
54
|
+
themePath: './src/theme/styles.ts', // Path to your theme file
|
|
55
|
+
}],
|
|
56
|
+
],
|
|
57
|
+
};
|
|
54
58
|
\`\`\`
|
|
55
59
|
|
|
56
60
|
## Project Structure
|
|
@@ -59,11 +63,12 @@ yarn dev
|
|
|
59
63
|
my-app/
|
|
60
64
|
├── packages/
|
|
61
65
|
│ ├── web/ # React web app (Vite)
|
|
62
|
-
│ ├──
|
|
63
|
-
│ ├── api/ # tRPC API server
|
|
66
|
+
│ ├── native/ # React Native app
|
|
67
|
+
│ ├── api/ # tRPC + GraphQL API server
|
|
64
68
|
│ ├── database/ # Prisma database layer
|
|
65
|
-
│ └── shared/ # Shared utilities
|
|
69
|
+
│ └── shared/ # Shared utilities & tRPC client
|
|
66
70
|
├── package.json
|
|
71
|
+
├── tsconfig.json
|
|
67
72
|
└── yarn.lock
|
|
68
73
|
\`\`\`
|
|
69
74
|
|
|
@@ -74,14 +79,16 @@ my-app/
|
|
|
74
79
|
- **Modern Tooling**: Vite, TypeScript, Jest, Prisma
|
|
75
80
|
- **Monorepo Structure**: Share code across packages
|
|
76
81
|
- **Theme System**: Consistent styling with react-native-unistyles
|
|
82
|
+
- **Style Extensions**: Customize component styles at build time
|
|
77
83
|
- **Navigation**: Unified navigation for web and native
|
|
78
84
|
|
|
79
85
|
## Next Steps
|
|
80
86
|
|
|
81
87
|
1. Explore the component library: \`@idealyst/components\`
|
|
82
|
-
2.
|
|
83
|
-
3.
|
|
84
|
-
4.
|
|
88
|
+
2. Learn the style system: \`idealyst://framework/style-system\`
|
|
89
|
+
3. Set up your database schema in \`packages/database\`
|
|
90
|
+
4. Define your API routes in \`packages/api\`
|
|
91
|
+
5. Build your UI using Idealyst components
|
|
85
92
|
`,
|
|
86
93
|
"idealyst://framework/components-overview": `# Idealyst Components Overview
|
|
87
94
|
|
|
@@ -186,188 +193,177 @@ import { Button, Card, Text, View } from '@idealyst/components';
|
|
|
186
193
|
`,
|
|
187
194
|
"idealyst://framework/theming": `# Theming Guide
|
|
188
195
|
|
|
189
|
-
Idealyst uses react-native-unistyles for cross-platform theming with full TypeScript support.
|
|
190
|
-
|
|
191
|
-
## Theme Structure
|
|
196
|
+
Idealyst uses react-native-unistyles for cross-platform theming with full TypeScript support. Themes are created using a fluent builder pattern.
|
|
192
197
|
|
|
193
|
-
|
|
194
|
-
- **Colors**: Text, surface, border, intent colors
|
|
195
|
-
- **Typography**: Font families, sizes, weights
|
|
196
|
-
- **Spacing**: Consistent spacing scale
|
|
197
|
-
- **Border Radius**: Rounded corner sizes
|
|
198
|
-
- **Breakpoints**: Responsive design breakpoints
|
|
198
|
+
## Theme Builder API
|
|
199
199
|
|
|
200
|
-
|
|
200
|
+
Create themes using the builder pattern:
|
|
201
201
|
|
|
202
202
|
\`\`\`typescript
|
|
203
|
-
{
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
203
|
+
import { createTheme } from '@idealyst/theme';
|
|
204
|
+
|
|
205
|
+
export const myTheme = createTheme()
|
|
206
|
+
// Add semantic intents
|
|
207
|
+
.addIntent('primary', {
|
|
208
|
+
primary: '#3b82f6', // Main color
|
|
209
|
+
contrast: '#ffffff', // Text on primary background
|
|
210
|
+
light: '#bfdbfe', // Lighter variant
|
|
211
|
+
dark: '#1e40af', // Darker variant
|
|
212
|
+
})
|
|
213
|
+
.addIntent('success', {
|
|
214
|
+
primary: '#22c55e',
|
|
215
|
+
contrast: '#ffffff',
|
|
216
|
+
light: '#a7f3d0',
|
|
217
|
+
dark: '#165e29',
|
|
218
|
+
})
|
|
219
|
+
.addIntent('error', {
|
|
220
|
+
primary: '#ef4444',
|
|
221
|
+
contrast: '#ffffff',
|
|
222
|
+
light: '#fca5a1',
|
|
223
|
+
dark: '#9b2222',
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
// Add border radii
|
|
227
|
+
.addRadius('none', 0)
|
|
228
|
+
.addRadius('sm', 4)
|
|
229
|
+
.addRadius('md', 8)
|
|
230
|
+
.addRadius('lg', 12)
|
|
231
|
+
|
|
232
|
+
// Add shadows (cross-platform)
|
|
233
|
+
.addShadow('sm', {
|
|
234
|
+
elevation: 1,
|
|
235
|
+
shadowColor: '#000000',
|
|
236
|
+
shadowOffset: { width: 0, height: 1 },
|
|
237
|
+
shadowOpacity: 0.08,
|
|
238
|
+
shadowRadius: 1,
|
|
239
|
+
boxShadow: '0px 1px 2px rgba(0, 0, 0, 0.1)', // web-only
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
// Set colors
|
|
243
|
+
.setColors({
|
|
244
|
+
pallet: { /* color palette */ },
|
|
211
245
|
surface: {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
246
|
+
screen: '#ffffff',
|
|
247
|
+
primary: '#ffffff',
|
|
248
|
+
secondary: '#f5f5f5',
|
|
215
249
|
inverse: '#000000',
|
|
216
250
|
},
|
|
217
|
-
|
|
218
|
-
primary: '#
|
|
219
|
-
secondary: '#
|
|
220
|
-
|
|
221
|
-
},
|
|
222
|
-
intents: {
|
|
223
|
-
primary: {
|
|
224
|
-
main: '#3B82F6',
|
|
225
|
-
container: '#DBEAFE',
|
|
226
|
-
onContainer: '#1E40AF',
|
|
227
|
-
},
|
|
228
|
-
success: {
|
|
229
|
-
main: '#10B981',
|
|
230
|
-
container: '#D1FAE5',
|
|
231
|
-
onContainer: '#065F46',
|
|
232
|
-
},
|
|
233
|
-
error: {
|
|
234
|
-
main: '#EF4444',
|
|
235
|
-
container: '#FEE2E2',
|
|
236
|
-
onContainer: '#991B1B',
|
|
237
|
-
},
|
|
238
|
-
warning: {
|
|
239
|
-
main: '#F59E0B',
|
|
240
|
-
container: '#FEF3C7',
|
|
241
|
-
onContainer: '#92400E',
|
|
242
|
-
},
|
|
243
|
-
},
|
|
244
|
-
spacing: {
|
|
245
|
-
xs: 4,
|
|
246
|
-
sm: 8,
|
|
247
|
-
md: 16,
|
|
248
|
-
lg: 24,
|
|
249
|
-
xl: 32,
|
|
250
|
-
xxl: 48,
|
|
251
|
-
},
|
|
252
|
-
borderRadius: {
|
|
253
|
-
sm: 4,
|
|
254
|
-
md: 8,
|
|
255
|
-
lg: 12,
|
|
256
|
-
xl: 16,
|
|
257
|
-
},
|
|
258
|
-
typography: {
|
|
259
|
-
fontFamily: {
|
|
260
|
-
sans: 'System',
|
|
261
|
-
mono: 'Monospace',
|
|
251
|
+
text: {
|
|
252
|
+
primary: '#000000',
|
|
253
|
+
secondary: '#333333',
|
|
254
|
+
inverse: '#ffffff',
|
|
262
255
|
},
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
md: 16,
|
|
267
|
-
lg: 18,
|
|
268
|
-
xl: 20,
|
|
256
|
+
border: {
|
|
257
|
+
primary: '#e0e0e0',
|
|
258
|
+
disabled: '#f0f0f0',
|
|
269
259
|
},
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
// Set component sizes (xs, sm, md, lg, xl)
|
|
263
|
+
.setSizes({
|
|
264
|
+
button: {
|
|
265
|
+
xs: { paddingVertical: 4, paddingHorizontal: 8, minHeight: 24, fontSize: 12 },
|
|
266
|
+
sm: { paddingVertical: 6, paddingHorizontal: 12, minHeight: 32, fontSize: 14 },
|
|
267
|
+
md: { paddingVertical: 8, paddingHorizontal: 16, minHeight: 40, fontSize: 16 },
|
|
268
|
+
lg: { paddingVertical: 10, paddingHorizontal: 20, minHeight: 48, fontSize: 18 },
|
|
269
|
+
xl: { paddingVertical: 12, paddingHorizontal: 24, minHeight: 56, fontSize: 20 },
|
|
276
270
|
},
|
|
277
|
-
|
|
278
|
-
}
|
|
279
|
-
\`\`\`
|
|
271
|
+
// ... other components (chip, badge, icon, input, etc.)
|
|
272
|
+
})
|
|
280
273
|
|
|
281
|
-
|
|
274
|
+
// Set interaction styles
|
|
275
|
+
.setInteraction({
|
|
276
|
+
focusedBackground: 'rgba(59, 130, 246, 0.08)',
|
|
277
|
+
focusBorder: 'rgba(59, 130, 246, 0.3)',
|
|
278
|
+
opacity: { hover: 0.9, active: 0.75, disabled: 0.5 },
|
|
279
|
+
})
|
|
282
280
|
|
|
283
|
-
|
|
281
|
+
// Set responsive breakpoints
|
|
282
|
+
.setBreakpoints({
|
|
283
|
+
xs: 0, // Portrait phones
|
|
284
|
+
sm: 576, // Landscape phones
|
|
285
|
+
md: 768, // Tablets
|
|
286
|
+
lg: 992, // Desktops
|
|
287
|
+
xl: 1200, // Large desktops
|
|
288
|
+
})
|
|
284
289
|
|
|
285
|
-
|
|
286
|
-
// theme.ts
|
|
287
|
-
export const customTheme = {
|
|
288
|
-
colors: {
|
|
289
|
-
// Override colors
|
|
290
|
-
text: {
|
|
291
|
-
primary: '#1A1A1A',
|
|
292
|
-
// ...
|
|
293
|
-
},
|
|
294
|
-
},
|
|
295
|
-
intents: {
|
|
296
|
-
primary: {
|
|
297
|
-
main: '#6366F1', // Custom brand color
|
|
298
|
-
// ...
|
|
299
|
-
},
|
|
300
|
-
},
|
|
301
|
-
// ... rest of theme
|
|
302
|
-
};
|
|
290
|
+
.build();
|
|
303
291
|
\`\`\`
|
|
304
292
|
|
|
305
|
-
##
|
|
293
|
+
## Intent Structure
|
|
306
294
|
|
|
307
|
-
|
|
308
|
-
import { UnistylesRegistry } from 'react-native-unistyles';
|
|
309
|
-
import { lightTheme, darkTheme } from './themes';
|
|
295
|
+
Each intent defines four color values:
|
|
310
296
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
initialTheme: 'light',
|
|
318
|
-
});
|
|
319
|
-
\`\`\`
|
|
297
|
+
| Property | Purpose |
|
|
298
|
+
|------------|-----------------------------------|
|
|
299
|
+
| \`primary\` | Main color used for backgrounds |
|
|
300
|
+
| \`contrast\` | Text color on primary background |
|
|
301
|
+
| \`light\` | Lighter tint for subtle states |
|
|
302
|
+
| \`dark\` | Darker shade for pressed states |
|
|
320
303
|
|
|
321
|
-
##
|
|
304
|
+
## Extending an Existing Theme
|
|
322
305
|
|
|
323
|
-
|
|
306
|
+
Use \`fromTheme()\` to extend a base theme:
|
|
324
307
|
|
|
325
308
|
\`\`\`typescript
|
|
326
|
-
import {
|
|
309
|
+
import { fromTheme, lightTheme } from '@idealyst/theme';
|
|
310
|
+
|
|
311
|
+
export const brandTheme = fromTheme(lightTheme)
|
|
312
|
+
.addIntent('brand', {
|
|
313
|
+
primary: '#6366f1',
|
|
314
|
+
contrast: '#ffffff',
|
|
315
|
+
light: '#818cf8',
|
|
316
|
+
dark: '#4f46e5',
|
|
317
|
+
})
|
|
318
|
+
.build();
|
|
319
|
+
\`\`\`
|
|
327
320
|
|
|
328
|
-
|
|
329
|
-
const { theme } = useStyles();
|
|
321
|
+
## Registering Your Theme
|
|
330
322
|
|
|
331
|
-
|
|
332
|
-
theme.setTheme(theme.name === 'light' ? 'dark' : 'light');
|
|
333
|
-
};
|
|
323
|
+
For full TypeScript inference:
|
|
334
324
|
|
|
335
|
-
|
|
325
|
+
\`\`\`typescript
|
|
326
|
+
// src/theme/styles.ts
|
|
327
|
+
export const myTheme = createTheme()
|
|
328
|
+
// ... builder chain
|
|
329
|
+
.build();
|
|
330
|
+
|
|
331
|
+
// Register the theme type
|
|
332
|
+
declare module '@idealyst/theme' {
|
|
333
|
+
interface RegisteredTheme {
|
|
334
|
+
theme: typeof myTheme;
|
|
335
|
+
}
|
|
336
336
|
}
|
|
337
337
|
\`\`\`
|
|
338
338
|
|
|
339
|
-
##
|
|
340
|
-
|
|
341
|
-
Use breakpoints for responsive layouts:
|
|
339
|
+
## Using Themes with Unistyles
|
|
342
340
|
|
|
343
341
|
\`\`\`typescript
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
padding: theme.spacing.md,
|
|
342
|
+
import { UnistylesRegistry } from 'react-native-unistyles';
|
|
343
|
+
import { lightTheme, darkTheme } from '@idealyst/theme';
|
|
347
344
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
}
|
|
356
|
-
}));
|
|
345
|
+
UnistylesRegistry
|
|
346
|
+
.addThemes({
|
|
347
|
+
light: lightTheme,
|
|
348
|
+
dark: darkTheme,
|
|
349
|
+
})
|
|
350
|
+
.addConfig({
|
|
351
|
+
initialTheme: 'light',
|
|
352
|
+
});
|
|
357
353
|
\`\`\`
|
|
358
354
|
|
|
359
355
|
## Platform-Specific Styles
|
|
360
356
|
|
|
361
357
|
\`\`\`typescript
|
|
362
|
-
const styles = StyleSheet.create(theme => ({
|
|
358
|
+
const styles = StyleSheet.create((theme) => ({
|
|
363
359
|
button: {
|
|
364
|
-
padding:
|
|
360
|
+
padding: 16,
|
|
365
361
|
|
|
366
362
|
_web: {
|
|
367
363
|
cursor: 'pointer',
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
},
|
|
364
|
+
transition: 'all 0.1s ease',
|
|
365
|
+
_hover: { opacity: 0.9 },
|
|
366
|
+
_active: { opacity: 0.75 },
|
|
371
367
|
},
|
|
372
368
|
|
|
373
369
|
_native: {
|
|
@@ -376,6 +372,12 @@ const styles = StyleSheet.create(theme => ({
|
|
|
376
372
|
},
|
|
377
373
|
}));
|
|
378
374
|
\`\`\`
|
|
375
|
+
|
|
376
|
+
## See Also
|
|
377
|
+
|
|
378
|
+
- \`idealyst://framework/style-system\` - Style definition APIs (defineStyle, extendStyle)
|
|
379
|
+
- \`idealyst://framework/babel-plugin\` - Babel plugin configuration
|
|
380
|
+
- \`idealyst://framework/breakpoints\` - Responsive breakpoint system
|
|
379
381
|
`,
|
|
380
382
|
"idealyst://framework/cli": `# Idealyst CLI Reference
|
|
381
383
|
|
|
@@ -1045,6 +1047,672 @@ Features:
|
|
|
1045
1047
|
3. **Error Handling**: Use Pothos error types
|
|
1046
1048
|
4. **Authorization**: Add auth checks in resolvers
|
|
1047
1049
|
5. **N+1 Prevention**: Use Prisma's query optimization
|
|
1050
|
+
`,
|
|
1051
|
+
"idealyst://framework/style-system": `# Style Definition System
|
|
1052
|
+
|
|
1053
|
+
Idealyst provides a powerful style definition system with build-time transformations via Babel plugin.
|
|
1054
|
+
|
|
1055
|
+
## Overview
|
|
1056
|
+
|
|
1057
|
+
The style system provides:
|
|
1058
|
+
- **defineStyle()**: Define base styles for components
|
|
1059
|
+
- **extendStyle()**: Merge additional styles with base styles
|
|
1060
|
+
- **overrideStyle()**: Completely replace component styles
|
|
1061
|
+
- **$iterator pattern**: Expand styles for all theme keys
|
|
1062
|
+
|
|
1063
|
+
## defineStyle()
|
|
1064
|
+
|
|
1065
|
+
Define base styles for a component:
|
|
1066
|
+
|
|
1067
|
+
\`\`\`typescript
|
|
1068
|
+
import { defineStyle, ThemeStyleWrapper } from '@idealyst/theme';
|
|
1069
|
+
import type { Theme as BaseTheme } from '@idealyst/theme';
|
|
1070
|
+
|
|
1071
|
+
// Wrap theme for $iterator support
|
|
1072
|
+
type Theme = ThemeStyleWrapper<BaseTheme>;
|
|
1073
|
+
|
|
1074
|
+
export const buttonStyles = defineStyle('Button', (theme: Theme) => ({
|
|
1075
|
+
button: {
|
|
1076
|
+
borderRadius: theme.radii.md,
|
|
1077
|
+
backgroundColor: theme.intents.primary.primary,
|
|
1078
|
+
|
|
1079
|
+
variants: {
|
|
1080
|
+
size: {
|
|
1081
|
+
// $iterator expands to all size keys (xs, sm, md, lg, xl)
|
|
1082
|
+
paddingVertical: theme.sizes.$button.paddingVertical,
|
|
1083
|
+
paddingHorizontal: theme.sizes.$button.paddingHorizontal,
|
|
1084
|
+
},
|
|
1085
|
+
disabled: {
|
|
1086
|
+
true: { opacity: 0.5 },
|
|
1087
|
+
false: { opacity: 1 },
|
|
1088
|
+
},
|
|
1089
|
+
},
|
|
1090
|
+
},
|
|
1091
|
+
text: {
|
|
1092
|
+
color: theme.intents.primary.contrast,
|
|
1093
|
+
variants: {
|
|
1094
|
+
size: {
|
|
1095
|
+
fontSize: theme.sizes.$button.fontSize,
|
|
1096
|
+
},
|
|
1097
|
+
},
|
|
1098
|
+
},
|
|
1099
|
+
}));
|
|
1100
|
+
\`\`\`
|
|
1101
|
+
|
|
1102
|
+
## Dynamic Style Functions
|
|
1103
|
+
|
|
1104
|
+
For styles depending on runtime props:
|
|
1105
|
+
|
|
1106
|
+
\`\`\`typescript
|
|
1107
|
+
export const buttonStyles = defineStyle('Button', (theme: Theme) => ({
|
|
1108
|
+
button: ({ intent = 'primary', type = 'contained' }: ButtonDynamicProps) => ({
|
|
1109
|
+
backgroundColor: type === 'contained'
|
|
1110
|
+
? theme.intents[intent].primary
|
|
1111
|
+
: 'transparent',
|
|
1112
|
+
borderColor: type === 'outlined'
|
|
1113
|
+
? theme.intents[intent].primary
|
|
1114
|
+
: 'transparent',
|
|
1115
|
+
}),
|
|
1116
|
+
}));
|
|
1117
|
+
\`\`\`
|
|
1118
|
+
|
|
1119
|
+
## Using Styles in Components
|
|
1120
|
+
|
|
1121
|
+
\`\`\`typescript
|
|
1122
|
+
import { buttonStyles } from './Button.styles';
|
|
1123
|
+
|
|
1124
|
+
const Button = ({ size = 'md', disabled = false, intent, type }) => {
|
|
1125
|
+
// Apply variants
|
|
1126
|
+
buttonStyles.useVariants({ size, disabled });
|
|
1127
|
+
|
|
1128
|
+
// Static styles - no function call
|
|
1129
|
+
const staticStyle = buttonStyles.button;
|
|
1130
|
+
|
|
1131
|
+
// Dynamic styles - function call with props
|
|
1132
|
+
const dynamicStyle = (buttonStyles.button as any)({ intent, type });
|
|
1133
|
+
|
|
1134
|
+
return (
|
|
1135
|
+
<TouchableOpacity style={dynamicStyle}>
|
|
1136
|
+
<Text style={buttonStyles.text}>Click me</Text>
|
|
1137
|
+
</TouchableOpacity>
|
|
1138
|
+
);
|
|
1139
|
+
};
|
|
1140
|
+
\`\`\`
|
|
1141
|
+
|
|
1142
|
+
## extendStyle()
|
|
1143
|
+
|
|
1144
|
+
Merge additional styles with base component styles:
|
|
1145
|
+
|
|
1146
|
+
\`\`\`typescript
|
|
1147
|
+
// style-extensions.ts
|
|
1148
|
+
import { extendStyle } from '@idealyst/theme';
|
|
1149
|
+
|
|
1150
|
+
extendStyle('Button', (theme) => ({
|
|
1151
|
+
button: {
|
|
1152
|
+
borderRadius: 9999, // Make all buttons pill-shaped
|
|
1153
|
+
},
|
|
1154
|
+
text: {
|
|
1155
|
+
fontFamily: 'CustomFont',
|
|
1156
|
+
},
|
|
1157
|
+
}));
|
|
1158
|
+
\`\`\`
|
|
1159
|
+
|
|
1160
|
+
## overrideStyle()
|
|
1161
|
+
|
|
1162
|
+
Completely replace component styles:
|
|
1163
|
+
|
|
1164
|
+
\`\`\`typescript
|
|
1165
|
+
import { overrideStyle } from '@idealyst/theme';
|
|
1166
|
+
|
|
1167
|
+
overrideStyle('Button', (theme) => ({
|
|
1168
|
+
button: {
|
|
1169
|
+
backgroundColor: theme.colors.surface.primary,
|
|
1170
|
+
borderWidth: 2,
|
|
1171
|
+
borderColor: theme.intents.primary.primary,
|
|
1172
|
+
},
|
|
1173
|
+
text: {
|
|
1174
|
+
color: theme.intents.primary.primary,
|
|
1175
|
+
},
|
|
1176
|
+
}));
|
|
1177
|
+
\`\`\`
|
|
1178
|
+
|
|
1179
|
+
## Import Order Matters
|
|
1180
|
+
|
|
1181
|
+
Extensions must be imported **before** components:
|
|
1182
|
+
|
|
1183
|
+
\`\`\`typescript
|
|
1184
|
+
// App.tsx
|
|
1185
|
+
import './style-extensions'; // FIRST - registers extensions
|
|
1186
|
+
import { Button } from '@idealyst/components'; // SECOND - uses extensions
|
|
1187
|
+
\`\`\`
|
|
1188
|
+
|
|
1189
|
+
## When to Use Each
|
|
1190
|
+
|
|
1191
|
+
| API | Use When |
|
|
1192
|
+
|-----|----------|
|
|
1193
|
+
| \`defineStyle()\` | Creating component library styles |
|
|
1194
|
+
| \`extendStyle()\` | Adding/modifying specific properties |
|
|
1195
|
+
| \`overrideStyle()\` | Completely custom styling |
|
|
1196
|
+
|
|
1197
|
+
## See Also
|
|
1198
|
+
|
|
1199
|
+
- \`idealyst://framework/theming\` - Theme builder API
|
|
1200
|
+
- \`idealyst://framework/babel-plugin\` - Plugin configuration
|
|
1201
|
+
- \`idealyst://framework/iterator-pattern\` - $iterator expansion
|
|
1202
|
+
`,
|
|
1203
|
+
"idealyst://framework/babel-plugin": `# Idealyst Babel Plugin
|
|
1204
|
+
|
|
1205
|
+
The Idealyst Babel plugin transforms style definitions at build time.
|
|
1206
|
+
|
|
1207
|
+
## Installation
|
|
1208
|
+
|
|
1209
|
+
The plugin is included with \`@idealyst/theme\`.
|
|
1210
|
+
|
|
1211
|
+
## Configuration
|
|
1212
|
+
|
|
1213
|
+
\`\`\`javascript
|
|
1214
|
+
// babel.config.js
|
|
1215
|
+
module.exports = {
|
|
1216
|
+
presets: ['module:@react-native/babel-preset'],
|
|
1217
|
+
plugins: [
|
|
1218
|
+
['@idealyst/theme/plugin', {
|
|
1219
|
+
// REQUIRED: Path to your theme file
|
|
1220
|
+
themePath: './src/theme/styles.ts',
|
|
1221
|
+
|
|
1222
|
+
// Optional: Enable debug logging
|
|
1223
|
+
debug: false,
|
|
1224
|
+
verbose: false,
|
|
1225
|
+
|
|
1226
|
+
// Optional: Paths to auto-process
|
|
1227
|
+
autoProcessPaths: [
|
|
1228
|
+
'@idealyst/components',
|
|
1229
|
+
'@idealyst/datepicker',
|
|
1230
|
+
'src/',
|
|
1231
|
+
],
|
|
1232
|
+
}],
|
|
1233
|
+
],
|
|
1234
|
+
};
|
|
1235
|
+
\`\`\`
|
|
1236
|
+
|
|
1237
|
+
## What the Plugin Does
|
|
1238
|
+
|
|
1239
|
+
### 1. Transforms defineStyle() to StyleSheet.create()
|
|
1240
|
+
|
|
1241
|
+
**Input:**
|
|
1242
|
+
\`\`\`typescript
|
|
1243
|
+
defineStyle('Button', (theme) => ({
|
|
1244
|
+
button: { backgroundColor: theme.intents.primary.primary }
|
|
1245
|
+
}));
|
|
1246
|
+
\`\`\`
|
|
1247
|
+
|
|
1248
|
+
**Output:**
|
|
1249
|
+
\`\`\`typescript
|
|
1250
|
+
StyleSheet.create((theme) => ({
|
|
1251
|
+
button: { backgroundColor: theme.intents.primary.primary }
|
|
1252
|
+
}));
|
|
1253
|
+
\`\`\`
|
|
1254
|
+
|
|
1255
|
+
### 2. Expands $iterator Patterns
|
|
1256
|
+
|
|
1257
|
+
**Input:**
|
|
1258
|
+
\`\`\`typescript
|
|
1259
|
+
defineStyle('Button', (theme) => ({
|
|
1260
|
+
button: {
|
|
1261
|
+
variants: {
|
|
1262
|
+
size: {
|
|
1263
|
+
paddingVertical: theme.sizes.$button.paddingVertical,
|
|
1264
|
+
},
|
|
1265
|
+
},
|
|
1266
|
+
},
|
|
1267
|
+
}));
|
|
1268
|
+
\`\`\`
|
|
1269
|
+
|
|
1270
|
+
**Output:**
|
|
1271
|
+
\`\`\`typescript
|
|
1272
|
+
StyleSheet.create((theme) => ({
|
|
1273
|
+
button: {
|
|
1274
|
+
variants: {
|
|
1275
|
+
size: {
|
|
1276
|
+
xs: { paddingVertical: theme.sizes.button.xs.paddingVertical },
|
|
1277
|
+
sm: { paddingVertical: theme.sizes.button.sm.paddingVertical },
|
|
1278
|
+
md: { paddingVertical: theme.sizes.button.md.paddingVertical },
|
|
1279
|
+
lg: { paddingVertical: theme.sizes.button.lg.paddingVertical },
|
|
1280
|
+
xl: { paddingVertical: theme.sizes.button.xl.paddingVertical },
|
|
1281
|
+
},
|
|
1282
|
+
},
|
|
1283
|
+
},
|
|
1284
|
+
}));
|
|
1285
|
+
\`\`\`
|
|
1286
|
+
|
|
1287
|
+
### 3. Merges Extensions at Build Time
|
|
1288
|
+
|
|
1289
|
+
\`\`\`typescript
|
|
1290
|
+
// Extension (processed first)
|
|
1291
|
+
extendStyle('Button', (theme) => ({
|
|
1292
|
+
button: { borderRadius: 9999 },
|
|
1293
|
+
}));
|
|
1294
|
+
|
|
1295
|
+
// Base (merges with extension)
|
|
1296
|
+
defineStyle('Button', (theme) => ({
|
|
1297
|
+
button: { padding: 16 },
|
|
1298
|
+
}));
|
|
1299
|
+
|
|
1300
|
+
// Result: { padding: 16, borderRadius: 9999 }
|
|
1301
|
+
\`\`\`
|
|
1302
|
+
|
|
1303
|
+
### 4. Removes extendStyle/overrideStyle Calls
|
|
1304
|
+
|
|
1305
|
+
After capturing extension definitions, the plugin removes the calls from the output since all merging happens at build time.
|
|
1306
|
+
|
|
1307
|
+
## Theme Analysis
|
|
1308
|
+
|
|
1309
|
+
The plugin statically analyzes your theme file to extract:
|
|
1310
|
+
- Intent names (primary, success, error, etc.)
|
|
1311
|
+
- Size keys (xs, sm, md, lg, xl)
|
|
1312
|
+
- Radius names (none, sm, md, lg)
|
|
1313
|
+
- Shadow names (none, sm, md, lg, xl)
|
|
1314
|
+
|
|
1315
|
+
This enables $iterator expansion without runtime overhead.
|
|
1316
|
+
|
|
1317
|
+
## Troubleshooting
|
|
1318
|
+
|
|
1319
|
+
### Styles Not Applying
|
|
1320
|
+
|
|
1321
|
+
1. Verify \`themePath\` points to your theme file
|
|
1322
|
+
2. Clear bundler cache: \`yarn start --reset-cache\`
|
|
1323
|
+
3. Check \`void StyleSheet;\` marker exists in style files
|
|
1324
|
+
|
|
1325
|
+
### Theme Changes Not Detected
|
|
1326
|
+
|
|
1327
|
+
1. Restart Metro bundler (theme is analyzed once)
|
|
1328
|
+
2. Verify theme exports correctly
|
|
1329
|
+
|
|
1330
|
+
### Debug Mode
|
|
1331
|
+
|
|
1332
|
+
Enable verbose logging:
|
|
1333
|
+
|
|
1334
|
+
\`\`\`javascript
|
|
1335
|
+
['@idealyst/theme/plugin', {
|
|
1336
|
+
themePath: './src/theme/styles.ts',
|
|
1337
|
+
verbose: true,
|
|
1338
|
+
}],
|
|
1339
|
+
\`\`\`
|
|
1340
|
+
`,
|
|
1341
|
+
"idealyst://framework/breakpoints": `# Responsive Breakpoints
|
|
1342
|
+
|
|
1343
|
+
Idealyst provides a responsive breakpoint system built on Unistyles v3, enabling width-based responsive styling across web and native platforms.
|
|
1344
|
+
|
|
1345
|
+
## Default Breakpoints
|
|
1346
|
+
|
|
1347
|
+
The default themes include 5 breakpoints:
|
|
1348
|
+
|
|
1349
|
+
| Breakpoint | Min Width | Target Devices |
|
|
1350
|
+
|------------|-----------|----------------|
|
|
1351
|
+
| \`xs\` | 0px | Portrait phones |
|
|
1352
|
+
| \`sm\` | 576px | Landscape phones |
|
|
1353
|
+
| \`md\` | 768px | Tablets |
|
|
1354
|
+
| \`lg\` | 992px | Desktops |
|
|
1355
|
+
| \`xl\` | 1200px | Large desktops |
|
|
1356
|
+
|
|
1357
|
+
## Defining Breakpoints
|
|
1358
|
+
|
|
1359
|
+
### Using setBreakpoints()
|
|
1360
|
+
|
|
1361
|
+
Set all breakpoints at once:
|
|
1362
|
+
|
|
1363
|
+
\`\`\`typescript
|
|
1364
|
+
import { createTheme } from '@idealyst/theme';
|
|
1365
|
+
|
|
1366
|
+
const theme = createTheme()
|
|
1367
|
+
// ... other theme config
|
|
1368
|
+
.setBreakpoints({
|
|
1369
|
+
xs: 0, // Must have one breakpoint at 0
|
|
1370
|
+
sm: 576,
|
|
1371
|
+
md: 768,
|
|
1372
|
+
lg: 992,
|
|
1373
|
+
xl: 1200,
|
|
1374
|
+
})
|
|
1375
|
+
.build();
|
|
1376
|
+
\`\`\`
|
|
1377
|
+
|
|
1378
|
+
### Using addBreakpoint()
|
|
1379
|
+
|
|
1380
|
+
Add breakpoints individually:
|
|
1381
|
+
|
|
1382
|
+
\`\`\`typescript
|
|
1383
|
+
import { fromTheme, lightTheme } from '@idealyst/theme';
|
|
1384
|
+
|
|
1385
|
+
const theme = fromTheme(lightTheme)
|
|
1386
|
+
.addBreakpoint('xxl', 1400) // Add extra large breakpoint
|
|
1387
|
+
.addBreakpoint('xxxl', 1800) // Add even larger
|
|
1388
|
+
.build();
|
|
1389
|
+
\`\`\`
|
|
1390
|
+
|
|
1391
|
+
## Using Breakpoints in Styles
|
|
1392
|
+
|
|
1393
|
+
### In StyleSheet.create()
|
|
1394
|
+
|
|
1395
|
+
Use object notation for responsive values:
|
|
1396
|
+
|
|
1397
|
+
\`\`\`typescript
|
|
1398
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
1399
|
+
|
|
1400
|
+
const styles = StyleSheet.create((theme) => ({
|
|
1401
|
+
container: {
|
|
1402
|
+
// Responsive padding
|
|
1403
|
+
padding: {
|
|
1404
|
+
xs: 8,
|
|
1405
|
+
md: 16,
|
|
1406
|
+
xl: 24,
|
|
1407
|
+
},
|
|
1408
|
+
|
|
1409
|
+
// Responsive flex direction
|
|
1410
|
+
flexDirection: {
|
|
1411
|
+
xs: 'column',
|
|
1412
|
+
md: 'row',
|
|
1413
|
+
},
|
|
1414
|
+
|
|
1415
|
+
// Responsive gap
|
|
1416
|
+
gap: {
|
|
1417
|
+
xs: 8,
|
|
1418
|
+
sm: 12,
|
|
1419
|
+
lg: 16,
|
|
1420
|
+
},
|
|
1421
|
+
},
|
|
1422
|
+
|
|
1423
|
+
text: {
|
|
1424
|
+
fontSize: {
|
|
1425
|
+
xs: 14,
|
|
1426
|
+
md: 16,
|
|
1427
|
+
lg: 18,
|
|
1428
|
+
},
|
|
1429
|
+
},
|
|
1430
|
+
}));
|
|
1431
|
+
\`\`\`
|
|
1432
|
+
|
|
1433
|
+
### Cascading Behavior
|
|
1434
|
+
|
|
1435
|
+
Values cascade up - if a breakpoint isn't defined, it uses the nearest smaller one:
|
|
1436
|
+
|
|
1437
|
+
\`\`\`typescript
|
|
1438
|
+
padding: {
|
|
1439
|
+
xs: 8, // Used for xs, sm (no sm defined)
|
|
1440
|
+
md: 16, // Used for md, lg (no lg defined)
|
|
1441
|
+
xl: 24, // Used for xl
|
|
1442
|
+
}
|
|
1443
|
+
\`\`\`
|
|
1444
|
+
|
|
1445
|
+
## Runtime Utilities
|
|
1446
|
+
|
|
1447
|
+
### getCurrentBreakpoint()
|
|
1448
|
+
|
|
1449
|
+
Get the current active breakpoint:
|
|
1450
|
+
|
|
1451
|
+
\`\`\`typescript
|
|
1452
|
+
import { getCurrentBreakpoint } from '@idealyst/theme';
|
|
1453
|
+
|
|
1454
|
+
const current = getCurrentBreakpoint();
|
|
1455
|
+
console.log(current); // 'md'
|
|
1456
|
+
\`\`\`
|
|
1457
|
+
|
|
1458
|
+
### getBreakpoints()
|
|
1459
|
+
|
|
1460
|
+
Get all registered breakpoints:
|
|
1461
|
+
|
|
1462
|
+
\`\`\`typescript
|
|
1463
|
+
import { getBreakpoints } from '@idealyst/theme';
|
|
1464
|
+
|
|
1465
|
+
const breakpoints = getBreakpoints();
|
|
1466
|
+
// { xs: 0, sm: 576, md: 768, lg: 992, xl: 1200 }
|
|
1467
|
+
\`\`\`
|
|
1468
|
+
|
|
1469
|
+
### isBreakpointUp() / isBreakpointDown()
|
|
1470
|
+
|
|
1471
|
+
Check viewport against breakpoints:
|
|
1472
|
+
|
|
1473
|
+
\`\`\`typescript
|
|
1474
|
+
import { isBreakpointUp, isBreakpointDown } from '@idealyst/theme';
|
|
1475
|
+
|
|
1476
|
+
if (isBreakpointUp('md')) {
|
|
1477
|
+
// Tablet or larger
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
if (isBreakpointDown('md')) {
|
|
1481
|
+
// Mobile only (below tablet)
|
|
1482
|
+
}
|
|
1483
|
+
\`\`\`
|
|
1484
|
+
|
|
1485
|
+
### resolveResponsive()
|
|
1486
|
+
|
|
1487
|
+
Resolve a responsive value for the current breakpoint:
|
|
1488
|
+
|
|
1489
|
+
\`\`\`typescript
|
|
1490
|
+
import { resolveResponsive } from '@idealyst/theme';
|
|
1491
|
+
|
|
1492
|
+
const padding = resolveResponsive({ xs: 8, md: 16, xl: 24 });
|
|
1493
|
+
// Returns 8 on mobile, 16 on tablet, 24 on desktop
|
|
1494
|
+
\`\`\`
|
|
1495
|
+
|
|
1496
|
+
## Responsive Type
|
|
1497
|
+
|
|
1498
|
+
The \`Responsive<T>\` type makes any value responsive:
|
|
1499
|
+
|
|
1500
|
+
\`\`\`typescript
|
|
1501
|
+
import { Responsive, Size } from '@idealyst/theme';
|
|
1502
|
+
|
|
1503
|
+
// Can be either a direct value or breakpoint map
|
|
1504
|
+
type Props = {
|
|
1505
|
+
size: Responsive<Size>;
|
|
1506
|
+
};
|
|
1507
|
+
|
|
1508
|
+
// Both are valid:
|
|
1509
|
+
<Component size="md" />
|
|
1510
|
+
<Component size={{ xs: 'sm', md: 'lg' }} />
|
|
1511
|
+
\`\`\`
|
|
1512
|
+
|
|
1513
|
+
### Type Guard
|
|
1514
|
+
|
|
1515
|
+
Check if a value is responsive:
|
|
1516
|
+
|
|
1517
|
+
\`\`\`typescript
|
|
1518
|
+
import { isResponsiveValue, Responsive, Size } from '@idealyst/theme';
|
|
1519
|
+
|
|
1520
|
+
function handleSize(size: Responsive<Size>) {
|
|
1521
|
+
if (isResponsiveValue(size)) {
|
|
1522
|
+
// size is Partial<Record<Breakpoint, Size>>
|
|
1523
|
+
console.log(size.xs, size.md);
|
|
1524
|
+
} else {
|
|
1525
|
+
// size is Size
|
|
1526
|
+
console.log(size);
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
\`\`\`
|
|
1530
|
+
|
|
1531
|
+
## TypeScript Support
|
|
1532
|
+
|
|
1533
|
+
Custom breakpoints are fully typed:
|
|
1534
|
+
|
|
1535
|
+
\`\`\`typescript
|
|
1536
|
+
const theme = createTheme()
|
|
1537
|
+
.setBreakpoints({
|
|
1538
|
+
mobile: 0,
|
|
1539
|
+
tablet: 768,
|
|
1540
|
+
desktop: 1024,
|
|
1541
|
+
})
|
|
1542
|
+
.build();
|
|
1543
|
+
|
|
1544
|
+
// Register for type inference
|
|
1545
|
+
declare module '@idealyst/theme' {
|
|
1546
|
+
interface CustomThemeRegistry {
|
|
1547
|
+
theme: typeof theme;
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
// Now Breakpoint = 'mobile' | 'tablet' | 'desktop'
|
|
1552
|
+
import { Breakpoint } from '@idealyst/theme';
|
|
1553
|
+
\`\`\`
|
|
1554
|
+
|
|
1555
|
+
## Unistyles Integration
|
|
1556
|
+
|
|
1557
|
+
Breakpoints are automatically registered with Unistyles:
|
|
1558
|
+
|
|
1559
|
+
\`\`\`typescript
|
|
1560
|
+
import { UnistylesRegistry } from 'react-native-unistyles';
|
|
1561
|
+
import { lightTheme, darkTheme } from '@idealyst/theme';
|
|
1562
|
+
|
|
1563
|
+
UnistylesRegistry
|
|
1564
|
+
.addThemes({ light: lightTheme, dark: darkTheme })
|
|
1565
|
+
.addBreakpoints(lightTheme.breakpoints) // Register breakpoints
|
|
1566
|
+
.addConfig({ initialTheme: 'light' });
|
|
1567
|
+
\`\`\`
|
|
1568
|
+
|
|
1569
|
+
## Cross-Platform Behavior
|
|
1570
|
+
|
|
1571
|
+
- **Web**: Breakpoints convert to CSS media queries automatically
|
|
1572
|
+
- **Native**: Uses device screen width (works with tablets, phones, etc.)
|
|
1573
|
+
- **Same API**: Write once, works everywhere
|
|
1574
|
+
|
|
1575
|
+
## Best Practices
|
|
1576
|
+
|
|
1577
|
+
1. **Mobile-first**: Start with \`xs\` and add larger breakpoints as needed
|
|
1578
|
+
2. **Use cascading**: Don't define every breakpoint - let values cascade
|
|
1579
|
+
3. **Consistent breakpoints**: Use the same breakpoints across themes
|
|
1580
|
+
4. **Test on devices**: Verify layouts on actual device widths
|
|
1581
|
+
5. **Avoid over-responsiveness**: Not everything needs to change per breakpoint
|
|
1582
|
+
`,
|
|
1583
|
+
"idealyst://framework/iterator-pattern": `# The $iterator Pattern
|
|
1584
|
+
|
|
1585
|
+
The \`$iterator\` pattern allows defining styles once that expand to all keys of a theme object.
|
|
1586
|
+
|
|
1587
|
+
## ThemeStyleWrapper
|
|
1588
|
+
|
|
1589
|
+
Wrap your theme type to enable $iterator properties:
|
|
1590
|
+
|
|
1591
|
+
\`\`\`typescript
|
|
1592
|
+
import { ThemeStyleWrapper } from '@idealyst/theme';
|
|
1593
|
+
import type { Theme as BaseTheme } from '@idealyst/theme';
|
|
1594
|
+
|
|
1595
|
+
type Theme = ThemeStyleWrapper<BaseTheme>;
|
|
1596
|
+
\`\`\`
|
|
1597
|
+
|
|
1598
|
+
This adds \`$property\` versions of iterable theme properties:
|
|
1599
|
+
|
|
1600
|
+
| Original Path | $iterator Path |
|
|
1601
|
+
|--------------------------|---------------------------|
|
|
1602
|
+
| \`theme.intents.primary\` | \`theme.$intents.primary\` |
|
|
1603
|
+
| \`theme.sizes.button.md\` | \`theme.sizes.$button.md\` |
|
|
1604
|
+
|
|
1605
|
+
## Usage Examples
|
|
1606
|
+
|
|
1607
|
+
### Expand Intents
|
|
1608
|
+
|
|
1609
|
+
\`\`\`typescript
|
|
1610
|
+
// Single definition
|
|
1611
|
+
variants: {
|
|
1612
|
+
intent: {
|
|
1613
|
+
backgroundColor: theme.$intents.light,
|
|
1614
|
+
borderColor: theme.$intents.primary,
|
|
1615
|
+
},
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
// Expands to all intent keys (primary, success, error, warning, etc.)
|
|
1619
|
+
// Result:
|
|
1620
|
+
// intent: {
|
|
1621
|
+
// primary: { backgroundColor: theme.intents.primary.light, borderColor: theme.intents.primary.primary },
|
|
1622
|
+
// success: { backgroundColor: theme.intents.success.light, borderColor: theme.intents.success.primary },
|
|
1623
|
+
// error: { ... },
|
|
1624
|
+
// ...
|
|
1625
|
+
// }
|
|
1626
|
+
\`\`\`
|
|
1627
|
+
|
|
1628
|
+
### Expand Sizes
|
|
1629
|
+
|
|
1630
|
+
\`\`\`typescript
|
|
1631
|
+
// Single definition
|
|
1632
|
+
variants: {
|
|
1633
|
+
size: {
|
|
1634
|
+
paddingVertical: theme.sizes.$button.paddingVertical,
|
|
1635
|
+
fontSize: theme.sizes.$button.fontSize,
|
|
1636
|
+
},
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
// Expands to all size keys (xs, sm, md, lg, xl)
|
|
1640
|
+
// Result:
|
|
1641
|
+
// size: {
|
|
1642
|
+
// xs: { paddingVertical: theme.sizes.button.xs.paddingVertical, fontSize: theme.sizes.button.xs.fontSize },
|
|
1643
|
+
// sm: { paddingVertical: theme.sizes.button.sm.paddingVertical, fontSize: theme.sizes.button.sm.fontSize },
|
|
1644
|
+
// md: { ... },
|
|
1645
|
+
// ...
|
|
1646
|
+
// }
|
|
1647
|
+
\`\`\`
|
|
1648
|
+
|
|
1649
|
+
## Complete Example
|
|
1650
|
+
|
|
1651
|
+
\`\`\`typescript
|
|
1652
|
+
import { defineStyle, ThemeStyleWrapper } from '@idealyst/theme';
|
|
1653
|
+
import type { Theme as BaseTheme } from '@idealyst/theme';
|
|
1654
|
+
|
|
1655
|
+
type Theme = ThemeStyleWrapper<BaseTheme>;
|
|
1656
|
+
|
|
1657
|
+
export const chipStyles = defineStyle('Chip', (theme: Theme) => ({
|
|
1658
|
+
chip: {
|
|
1659
|
+
borderRadius: 999,
|
|
1660
|
+
|
|
1661
|
+
variants: {
|
|
1662
|
+
// Expand for all sizes
|
|
1663
|
+
size: {
|
|
1664
|
+
paddingVertical: theme.sizes.$chip.paddingVertical,
|
|
1665
|
+
paddingHorizontal: theme.sizes.$chip.paddingHorizontal,
|
|
1666
|
+
minHeight: theme.sizes.$chip.minHeight,
|
|
1667
|
+
},
|
|
1668
|
+
|
|
1669
|
+
// Expand for all intents
|
|
1670
|
+
intent: {
|
|
1671
|
+
backgroundColor: theme.$intents.light,
|
|
1672
|
+
borderColor: theme.$intents.primary,
|
|
1673
|
+
},
|
|
1674
|
+
},
|
|
1675
|
+
},
|
|
1676
|
+
|
|
1677
|
+
text: {
|
|
1678
|
+
variants: {
|
|
1679
|
+
size: {
|
|
1680
|
+
fontSize: theme.sizes.$chip.fontSize,
|
|
1681
|
+
lineHeight: theme.sizes.$chip.lineHeight,
|
|
1682
|
+
},
|
|
1683
|
+
|
|
1684
|
+
intent: {
|
|
1685
|
+
color: theme.$intents.dark,
|
|
1686
|
+
},
|
|
1687
|
+
},
|
|
1688
|
+
},
|
|
1689
|
+
}));
|
|
1690
|
+
\`\`\`
|
|
1691
|
+
|
|
1692
|
+
## createIteratorStyles()
|
|
1693
|
+
|
|
1694
|
+
Alternative to defineStyle for custom components:
|
|
1695
|
+
|
|
1696
|
+
\`\`\`typescript
|
|
1697
|
+
import { createIteratorStyles } from '@idealyst/theme';
|
|
1698
|
+
|
|
1699
|
+
export const styles = createIteratorStyles((theme) => ({
|
|
1700
|
+
box: {
|
|
1701
|
+
variants: {
|
|
1702
|
+
intent: {
|
|
1703
|
+
backgroundColor: theme.$intents.light,
|
|
1704
|
+
},
|
|
1705
|
+
},
|
|
1706
|
+
},
|
|
1707
|
+
}));
|
|
1708
|
+
\`\`\`
|
|
1709
|
+
|
|
1710
|
+
## Benefits
|
|
1711
|
+
|
|
1712
|
+
1. **DRY Code**: Define once, expand to many
|
|
1713
|
+
2. **Type Safety**: TypeScript validates iterator properties
|
|
1714
|
+
3. **Maintainable**: Adding new sizes/intents to theme auto-expands
|
|
1715
|
+
4. **Zero Runtime Cost**: Expansion happens at build time
|
|
1048
1716
|
`,
|
|
1049
1717
|
};
|
|
1050
1718
|
//# sourceMappingURL=framework-guides.js.map
|