@shohojdhara/atomix 0.4.8 → 0.5.0
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/atomix.config.ts +58 -1
- package/dist/atomix.css +148 -120
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +1 -1
- package/dist/atomix.min.css.map +1 -1
- package/dist/charts.d.ts +33 -0
- package/dist/charts.js +1227 -122
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +33 -10
- package/dist/core.js +1052 -41
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +33 -0
- package/dist/forms.js +2086 -1035
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +42 -1
- package/dist/heavy.js +1620 -600
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +441 -270
- package/dist/index.esm.js +1900 -638
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1935 -670
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +6 -3
- package/scripts/atomix-cli.js +148 -4
- package/scripts/cli/__tests__/basic.test.js +3 -2
- package/scripts/cli/__tests__/clean.test.js +278 -0
- package/scripts/cli/__tests__/component-validator.test.js +433 -0
- package/scripts/cli/__tests__/generator.test.js +613 -0
- package/scripts/cli/__tests__/glass-motion.test.js +256 -0
- package/scripts/cli/__tests__/integration.test.js +719 -108
- package/scripts/cli/__tests__/migrate.test.js +74 -0
- package/scripts/cli/__tests__/security.test.js +206 -0
- package/scripts/cli/__tests__/test-setup.js +3 -1
- package/scripts/cli/__tests__/theme-bridge.test.js +507 -0
- package/scripts/cli/__tests__/token-provider.test.js +361 -0
- package/scripts/cli/__tests__/utils.test.js +5 -5
- package/scripts/cli/commands/benchmark.js +105 -0
- package/scripts/cli/commands/build-theme.js +4 -1
- package/scripts/cli/commands/clean.js +109 -0
- package/scripts/cli/commands/doctor.js +88 -0
- package/scripts/cli/commands/generate.js +135 -14
- package/scripts/cli/commands/init.js +45 -18
- package/scripts/cli/commands/migrate.js +106 -0
- package/scripts/cli/commands/sync-tokens.js +206 -0
- package/scripts/cli/commands/theme-bridge.js +248 -0
- package/scripts/cli/commands/tokens.js +157 -0
- package/scripts/cli/commands/validate.js +194 -0
- package/scripts/cli/internal/ai-engine.js +156 -0
- package/scripts/cli/internal/component-validator.js +443 -0
- package/scripts/cli/internal/config-loader.js +162 -0
- package/scripts/cli/internal/filesystem.js +102 -2
- package/scripts/cli/internal/generator.js +359 -39
- package/scripts/cli/internal/glass-generator.js +398 -0
- package/scripts/cli/internal/hook-generator.js +369 -0
- package/scripts/cli/internal/hooks.js +61 -0
- package/scripts/cli/internal/itcss-generator.js +565 -0
- package/scripts/cli/internal/motion-generator.js +679 -0
- package/scripts/cli/internal/template-engine.js +301 -0
- package/scripts/cli/internal/theme-bridge.js +664 -0
- package/scripts/cli/internal/tokens/engine.js +122 -0
- package/scripts/cli/internal/tokens/provider.js +34 -0
- package/scripts/cli/internal/tokens/providers/figma.js +50 -0
- package/scripts/cli/internal/tokens/providers/style-dictionary.js +48 -0
- package/scripts/cli/internal/tokens/providers/w3c.js +48 -0
- package/scripts/cli/internal/tokens/token-provider.js +443 -0
- package/scripts/cli/internal/tokens/token-validator.js +513 -0
- package/scripts/cli/internal/validator.js +276 -0
- package/scripts/cli/internal/wizard.js +60 -6
- package/scripts/cli/mappings.js +23 -0
- package/scripts/cli/migration-tools.js +164 -94
- package/scripts/cli/plugins/style-dictionary.js +46 -0
- package/scripts/cli/templates/README.md +525 -95
- package/scripts/cli/templates/common-templates.js +40 -14
- package/scripts/cli/templates/components/react-component.ts +282 -0
- package/scripts/cli/templates/config/project-config.ts +112 -0
- package/scripts/cli/templates/hooks/use-component.ts +477 -0
- package/scripts/cli/templates/index.js +19 -4
- package/scripts/cli/templates/index.ts +171 -0
- package/scripts/cli/templates/next-templates.js +72 -0
- package/scripts/cli/templates/react-templates.js +70 -126
- package/scripts/cli/templates/scss-templates.js +35 -35
- package/scripts/cli/templates/stories/storybook-story.ts +241 -0
- package/scripts/cli/templates/styles/scss-component.ts +255 -0
- package/scripts/cli/templates/tests/vitest-test.ts +229 -0
- package/scripts/cli/templates/token-templates.js +337 -1
- package/scripts/cli/templates/tokens/token-generators.ts +1088 -0
- package/scripts/cli/templates/types/component-types.ts +145 -0
- package/scripts/cli/templates/utils/testing-utils.ts +144 -0
- package/scripts/cli/templates/vanilla-templates.js +39 -0
- package/scripts/cli/token-manager.js +8 -2
- package/scripts/cli/utils/cache-manager.js +240 -0
- package/scripts/cli/utils/detector.js +46 -0
- package/scripts/cli/utils/diagnostics.js +289 -0
- package/scripts/cli/utils/error.js +45 -3
- package/scripts/cli/utils/helpers.js +24 -0
- package/scripts/cli/utils/logger.js +1 -1
- package/scripts/cli/utils/security.js +302 -0
- package/scripts/cli/utils/telemetry.js +115 -0
- package/scripts/cli/utils/validation.js +4 -38
- package/scripts/cli/utils.js +46 -0
- package/src/components/Accordion/Accordion.stories.tsx +0 -18
- package/src/components/Accordion/Accordion.test.tsx +0 -17
- package/src/components/Accordion/Accordion.tsx +0 -4
- package/src/components/AtomixGlass/AtomixGlass.tsx +102 -2
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +125 -12
- package/src/components/AtomixGlass/PerformanceDashboard.tsx +219 -0
- package/src/components/AtomixGlass/README.md +25 -10
- package/src/components/AtomixGlass/animation-system.ts +578 -0
- package/src/components/AtomixGlass/shader-utils.ts +3 -0
- package/src/components/AtomixGlass/stories/AnimationFeatures.stories.tsx +653 -0
- package/src/components/AtomixGlass/stories/AnimationTests.stories.tsx +95 -0
- package/src/components/AtomixGlass/stories/CardExamples.stories.tsx +212 -0
- package/src/components/AtomixGlass/stories/DashboardExamples.stories.tsx +348 -0
- package/src/components/AtomixGlass/stories/EcommerceExamples.stories.tsx +410 -0
- package/src/components/AtomixGlass/stories/FormExamples.stories.tsx +436 -0
- package/src/components/AtomixGlass/stories/HeroExamples.stories.tsx +264 -0
- package/src/components/AtomixGlass/stories/InteractivePlayground.stories.tsx +247 -0
- package/src/components/AtomixGlass/stories/MobileUIExamples.stories.tsx +418 -0
- package/src/components/AtomixGlass/stories/ModalExamples.stories.tsx +402 -0
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +157 -6
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +658 -93
- package/src/components/AtomixGlass/stories/PresetGallery.stories.tsx +335 -0
- package/src/components/AtomixGlass/stories/WidgetExamples.stories.tsx +441 -0
- package/src/components/AtomixGlass/stories/argTypes.ts +384 -0
- package/src/components/AtomixGlass/stories/shared-components.tsx +91 -1
- package/src/components/AtomixGlass/stories/types.ts +127 -0
- package/src/components/Avatar/Avatar.tsx +1 -1
- package/src/components/Button/Button.stories.disabled-link.tsx +10 -0
- package/src/components/Button/Button.stories.tsx +10 -0
- package/src/components/Button/Button.test.tsx +16 -11
- package/src/components/Button/Button.tsx +4 -4
- package/src/components/Card/Card.tsx +1 -1
- package/src/components/Dropdown/Dropdown.tsx +12 -12
- package/src/components/Form/Select.tsx +62 -3
- package/src/components/Modal/Modal.tsx +14 -3
- package/src/components/Navigation/Navbar/Navbar.tsx +44 -0
- package/src/components/Slider/Slider.stories.tsx +3 -3
- package/src/components/Slider/Slider.tsx +38 -0
- package/src/components/Steps/Steps.tsx +3 -3
- package/src/components/Tabs/Tabs.tsx +77 -8
- package/src/components/Testimonial/Testimonial.tsx +1 -1
- package/src/components/TypedButton/TypedButton.stories.tsx +59 -0
- package/src/components/TypedButton/TypedButton.tsx +39 -0
- package/src/components/TypedButton/index.ts +2 -0
- package/src/components/VideoPlayer/VideoPlayer.tsx +11 -4
- package/src/lib/composables/index.ts +4 -7
- package/src/lib/composables/types.ts +45 -0
- package/src/lib/composables/useAccordion.ts +0 -7
- package/src/lib/composables/useAtomixGlass.ts +144 -5
- package/src/lib/composables/useChartExport.ts +3 -13
- package/src/lib/composables/useDropdown.ts +66 -0
- package/src/lib/composables/useFocusTrap.ts +80 -0
- package/src/lib/composables/usePerformanceMonitor.ts +448 -0
- package/src/lib/composables/useResponsiveGlass.presets.ts +192 -0
- package/src/lib/composables/useResponsiveGlass.ts +441 -0
- package/src/lib/composables/useTooltip.ts +16 -0
- package/src/lib/composables/useTypedButton.ts +66 -0
- package/src/lib/config/index.ts +62 -5
- package/src/lib/constants/components.ts +55 -0
- package/src/lib/theme/devtools/__tests__/useHistory.test.tsx +150 -0
- package/src/lib/theme/tokens/centralized-tokens.ts +120 -0
- package/src/lib/theme/utils/__tests__/domUtils.test.ts +101 -0
- package/src/lib/types/components.ts +37 -11
- package/src/lib/types/glass.ts +35 -0
- package/src/lib/types/index.ts +1 -0
- package/src/lib/utils/displacement-generator.ts +1 -1
- package/src/styles/01-settings/_settings.testtypecheck.scss +53 -0
- package/src/styles/01-settings/_settings.typedbutton.scss +53 -0
- package/src/styles/06-components/_components.testbutton.scss +212 -0
- package/src/styles/06-components/_components.testtypecheck.scss +212 -0
- package/src/styles/06-components/_components.typedbutton.scss +212 -0
- package/src/styles/99-utilities/_index.scss +1 -0
- package/src/styles/99-utilities/_utilities.text.scss +1 -1
- package/src/styles/99-utilities/_utilities.touch-target.scss +36 -0
- package/src/styles/06-components/old.chart.styles.scss +0 -2788
|
@@ -0,0 +1,1088 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token Generation Templates (TypeScript)
|
|
3
|
+
* Design system token generators following W3C DTCG format
|
|
4
|
+
*
|
|
5
|
+
* @module templates/tokens
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { CSSProperties } from 'react';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Token category types
|
|
12
|
+
*/
|
|
13
|
+
export type TokenCategory =
|
|
14
|
+
| 'color'
|
|
15
|
+
| 'spacing'
|
|
16
|
+
| 'typography'
|
|
17
|
+
| 'shadow'
|
|
18
|
+
| 'radius'
|
|
19
|
+
| 'animation'
|
|
20
|
+
| 'breakpoint'
|
|
21
|
+
| 'zIndex';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Token format options
|
|
25
|
+
*/
|
|
26
|
+
export type TokenFormat = 'scss' | 'css' | 'json' | 'ts';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Color token configuration
|
|
30
|
+
*/
|
|
31
|
+
export interface ColorTokenConfig {
|
|
32
|
+
brand?: {
|
|
33
|
+
primary?: string[];
|
|
34
|
+
secondary?: string[];
|
|
35
|
+
accent?: string[];
|
|
36
|
+
};
|
|
37
|
+
semantic?: {
|
|
38
|
+
success?: string;
|
|
39
|
+
warning?: string;
|
|
40
|
+
error?: string;
|
|
41
|
+
info?: string;
|
|
42
|
+
};
|
|
43
|
+
neutral?: string[];
|
|
44
|
+
background?: {
|
|
45
|
+
light?: string;
|
|
46
|
+
dark?: string;
|
|
47
|
+
};
|
|
48
|
+
text?: {
|
|
49
|
+
light?: string;
|
|
50
|
+
dark?: string;
|
|
51
|
+
};
|
|
52
|
+
border?: {
|
|
53
|
+
light?: string;
|
|
54
|
+
dark?: string;
|
|
55
|
+
};
|
|
56
|
+
focus?: {
|
|
57
|
+
light?: string;
|
|
58
|
+
dark?: string;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Spacing token configuration
|
|
64
|
+
*/
|
|
65
|
+
export interface SpacingTokenConfig {
|
|
66
|
+
baseUnit?: string; // e.g., '0.25rem' (4px)
|
|
67
|
+
scale?: number[]; // e.g., [0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40, 48, 56, 64]
|
|
68
|
+
componentSpecific?: {
|
|
69
|
+
buttonPaddingX?: string;
|
|
70
|
+
buttonPaddingY?: string;
|
|
71
|
+
cardPadding?: string;
|
|
72
|
+
modalPadding?: string;
|
|
73
|
+
};
|
|
74
|
+
layout?: {
|
|
75
|
+
containerPadding?: string;
|
|
76
|
+
gridGap?: string;
|
|
77
|
+
sectionSpacing?: string;
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Typography token configuration
|
|
83
|
+
*/
|
|
84
|
+
export interface TypographyTokenConfig {
|
|
85
|
+
fontFamilies?: {
|
|
86
|
+
sans?: string;
|
|
87
|
+
serif?: string;
|
|
88
|
+
mono?: string;
|
|
89
|
+
};
|
|
90
|
+
fontSizes?: Record<string, string>; // e.g., { xs: '0.75rem', sm: '0.875rem', ... }
|
|
91
|
+
lineHeights?: Record<string, number | string>;
|
|
92
|
+
fontWeights?: Record<string, number>;
|
|
93
|
+
letterSpacing?: Record<string, string>;
|
|
94
|
+
headings?: {
|
|
95
|
+
h1?: { fontSize?: string; lineHeight?: number };
|
|
96
|
+
h2?: { fontSize?: string; lineHeight?: number };
|
|
97
|
+
h3?: { fontSize?: string; lineHeight?: number };
|
|
98
|
+
h4?: { fontSize?: string; lineHeight?: number };
|
|
99
|
+
h5?: { fontSize?: string; lineHeight?: number };
|
|
100
|
+
h6?: { fontSize?: string; lineHeight?: number };
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Shadow token configuration
|
|
106
|
+
*/
|
|
107
|
+
export interface ShadowTokenConfig {
|
|
108
|
+
colors?: {
|
|
109
|
+
light?: string;
|
|
110
|
+
dark?: string;
|
|
111
|
+
};
|
|
112
|
+
shadows?: Record<string, string>;
|
|
113
|
+
componentSpecific?: {
|
|
114
|
+
button?: string;
|
|
115
|
+
buttonHover?: string;
|
|
116
|
+
card?: string;
|
|
117
|
+
dropdown?: string;
|
|
118
|
+
modal?: string;
|
|
119
|
+
popover?: string;
|
|
120
|
+
tooltip?: string;
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Radius token configuration
|
|
126
|
+
*/
|
|
127
|
+
export interface RadiusTokenConfig {
|
|
128
|
+
baseUnit?: string;
|
|
129
|
+
scale?: Record<string, string>;
|
|
130
|
+
componentSpecific?: {
|
|
131
|
+
button?: string;
|
|
132
|
+
card?: string;
|
|
133
|
+
input?: string;
|
|
134
|
+
badge?: string;
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Animation token configuration
|
|
140
|
+
*/
|
|
141
|
+
export interface AnimationTokenConfig {
|
|
142
|
+
durations?: Record<string, string>;
|
|
143
|
+
easings?: Record<string, string>;
|
|
144
|
+
presets?: {
|
|
145
|
+
fadeIn?: string;
|
|
146
|
+
slideInUp?: string;
|
|
147
|
+
scaleIn?: string;
|
|
148
|
+
pulse?: string;
|
|
149
|
+
shimmer?: string;
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Breakpoint token configuration
|
|
155
|
+
*/
|
|
156
|
+
export interface BreakpointTokenConfig {
|
|
157
|
+
breakpoints?: Record<string, string>;
|
|
158
|
+
containerMaxWidths?: Record<string, string>;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Z-Index token configuration
|
|
163
|
+
*/
|
|
164
|
+
export interface ZIndexTokenConfig {
|
|
165
|
+
scale?: Record<string, number>;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Generate color tokens in SCSS format
|
|
170
|
+
*
|
|
171
|
+
* @param config - Color token configuration
|
|
172
|
+
* @returns SCSS color tokens string
|
|
173
|
+
*/
|
|
174
|
+
export const generateColorTokens = (config: ColorTokenConfig = {}): string => {
|
|
175
|
+
const {
|
|
176
|
+
brand = {},
|
|
177
|
+
semantic = {},
|
|
178
|
+
neutral = [],
|
|
179
|
+
background = {},
|
|
180
|
+
text = {},
|
|
181
|
+
border = {},
|
|
182
|
+
focus = {},
|
|
183
|
+
} = config;
|
|
184
|
+
|
|
185
|
+
return `// Custom Color Tokens
|
|
186
|
+
// Generated by Atomix CLI
|
|
187
|
+
// =============================================================================
|
|
188
|
+
|
|
189
|
+
// Brand Colors
|
|
190
|
+
// Customize these to match your brand identity
|
|
191
|
+
${generateBrandColors(brand)}
|
|
192
|
+
|
|
193
|
+
// Semantic Colors
|
|
194
|
+
${generateSemanticColors(semantic)}
|
|
195
|
+
|
|
196
|
+
// Neutral Colors
|
|
197
|
+
${generateNeutralColors(neutral)}
|
|
198
|
+
|
|
199
|
+
// Background Colors
|
|
200
|
+
${generateBackgroundColors(background)}
|
|
201
|
+
|
|
202
|
+
// Text Colors
|
|
203
|
+
${generateTextColors(text)}
|
|
204
|
+
|
|
205
|
+
// Border Colors
|
|
206
|
+
${generateBorderColors(border)}
|
|
207
|
+
|
|
208
|
+
// Focus Colors
|
|
209
|
+
${generateFocusColors(focus)}
|
|
210
|
+
|
|
211
|
+
// Export custom colors to override defaults
|
|
212
|
+
$primary: $custom-primary-6 !default;
|
|
213
|
+
$success: $custom-success !default;
|
|
214
|
+
$warning: $custom-warning !default;
|
|
215
|
+
$error: $custom-error !default;
|
|
216
|
+
$info: $custom-info !default;
|
|
217
|
+
|
|
218
|
+
// Dark mode overrides
|
|
219
|
+
$body-bg-dark: $custom-body-bg-dark !default;
|
|
220
|
+
$body-color-dark: $custom-body-color-dark !default;
|
|
221
|
+
$border-color-dark: $custom-border-color-dark !default;
|
|
222
|
+
`;
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Generate spacing tokens in SCSS format
|
|
227
|
+
*
|
|
228
|
+
* @param config - Spacing token configuration
|
|
229
|
+
* @returns SCSS spacing tokens string
|
|
230
|
+
*/
|
|
231
|
+
export const generateSpacingTokens = (config: SpacingTokenConfig = {}): string => {
|
|
232
|
+
const {
|
|
233
|
+
baseUnit = '0.25rem',
|
|
234
|
+
scale = [0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40, 48, 56, 64],
|
|
235
|
+
componentSpecific = {},
|
|
236
|
+
layout = {},
|
|
237
|
+
} = config;
|
|
238
|
+
|
|
239
|
+
return `// Custom Spacing Tokens
|
|
240
|
+
// Generated by Atomix CLI
|
|
241
|
+
// =============================================================================
|
|
242
|
+
|
|
243
|
+
// Base spacing unit (change this to scale all spacing)
|
|
244
|
+
$custom-spacing-base: ${baseUnit} !default; // 4px
|
|
245
|
+
|
|
246
|
+
// Spacing scale
|
|
247
|
+
${generateSpacingScale(scale)}
|
|
248
|
+
|
|
249
|
+
// Component-specific spacing
|
|
250
|
+
${generateComponentSpacing(componentSpecific)}
|
|
251
|
+
|
|
252
|
+
// Layout spacing
|
|
253
|
+
${generateLayoutSpacing(layout)}
|
|
254
|
+
|
|
255
|
+
// Export to override defaults
|
|
256
|
+
$spacing-sizes: (
|
|
257
|
+
0: $custom-spacing-0,
|
|
258
|
+
1: $custom-spacing-1,
|
|
259
|
+
2: $custom-spacing-2,
|
|
260
|
+
3: $custom-spacing-3,
|
|
261
|
+
4: $custom-spacing-4,
|
|
262
|
+
5: $custom-spacing-5,
|
|
263
|
+
6: $custom-spacing-6,
|
|
264
|
+
8: $custom-spacing-8,
|
|
265
|
+
10: $custom-spacing-10,
|
|
266
|
+
12: $custom-spacing-12,
|
|
267
|
+
16: $custom-spacing-16,
|
|
268
|
+
20: $custom-spacing-20,
|
|
269
|
+
24: $custom-spacing-24,
|
|
270
|
+
32: $custom-spacing-32,
|
|
271
|
+
40: $custom-spacing-40,
|
|
272
|
+
48: $custom-spacing-48,
|
|
273
|
+
56: $custom-spacing-56,
|
|
274
|
+
64: $custom-spacing-64,
|
|
275
|
+
) !default;
|
|
276
|
+
`;
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Generate typography tokens in SCSS format
|
|
281
|
+
*
|
|
282
|
+
* @param config - Typography token configuration
|
|
283
|
+
* @returns SCSS typography tokens string
|
|
284
|
+
*/
|
|
285
|
+
export const generateTypographyTokens = (config: TypographyTokenConfig = {}): string => {
|
|
286
|
+
const {
|
|
287
|
+
fontFamilies = {},
|
|
288
|
+
fontSizes = {},
|
|
289
|
+
lineHeights = {},
|
|
290
|
+
fontWeights = {},
|
|
291
|
+
letterSpacing = {},
|
|
292
|
+
headings = {},
|
|
293
|
+
} = config;
|
|
294
|
+
|
|
295
|
+
return `// Custom Typography Tokens
|
|
296
|
+
// Generated by Atomix CLI
|
|
297
|
+
// =============================================================================
|
|
298
|
+
|
|
299
|
+
// Font Families
|
|
300
|
+
${generateFontFamilies(fontFamilies)}
|
|
301
|
+
|
|
302
|
+
// Font Size Scale
|
|
303
|
+
${generateFontSizes(fontSizes)}
|
|
304
|
+
|
|
305
|
+
// Line Heights
|
|
306
|
+
${generateLineHeights(lineHeights)}
|
|
307
|
+
|
|
308
|
+
// Font Weights
|
|
309
|
+
${generateFontWeights(fontWeights)}
|
|
310
|
+
|
|
311
|
+
// Letter Spacing
|
|
312
|
+
${generateLetterSpacing(letterSpacing)}
|
|
313
|
+
|
|
314
|
+
// Heading Sizes
|
|
315
|
+
${generateHeadingSizes(headings)}
|
|
316
|
+
|
|
317
|
+
// Export to override defaults
|
|
318
|
+
$font-family-base: $custom-font-family-sans !default;
|
|
319
|
+
$font-family-monospace: $custom-font-family-mono !default;
|
|
320
|
+
$font-size-base: $custom-font-size-base !default;
|
|
321
|
+
$line-height-base: $custom-line-height-base !default;
|
|
322
|
+
$font-weight-base: $custom-font-weight-normal !default;
|
|
323
|
+
|
|
324
|
+
// Heading overrides
|
|
325
|
+
$h1-font-size: $custom-h1-font-size !default;
|
|
326
|
+
$h2-font-size: $custom-h2-font-size !default;
|
|
327
|
+
$h3-font-size: $custom-h3-font-size !default;
|
|
328
|
+
$h4-font-size: $custom-h4-font-size !default;
|
|
329
|
+
$h5-font-size: $custom-h5-font-size !default;
|
|
330
|
+
$h6-font-size: $custom-h6-font-size !default;
|
|
331
|
+
`;
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Generate shadow tokens in SCSS format
|
|
336
|
+
*
|
|
337
|
+
* @param config - Shadow token configuration
|
|
338
|
+
* @returns SCSS shadow tokens string
|
|
339
|
+
*/
|
|
340
|
+
export const generateShadowTokens = (config: ShadowTokenConfig = {}): string => {
|
|
341
|
+
const {
|
|
342
|
+
colors = {},
|
|
343
|
+
shadows = {},
|
|
344
|
+
componentSpecific = {},
|
|
345
|
+
} = config;
|
|
346
|
+
|
|
347
|
+
return `// Custom Box Shadow Tokens
|
|
348
|
+
// Generated by Atomix CLI
|
|
349
|
+
// =============================================================================
|
|
350
|
+
|
|
351
|
+
// Shadow Colors
|
|
352
|
+
${generateShadowColors(colors)}
|
|
353
|
+
|
|
354
|
+
// Shadow Scale
|
|
355
|
+
${generateShadowScale(shadows)}
|
|
356
|
+
|
|
357
|
+
// Component-specific Shadows
|
|
358
|
+
${generateComponentShadows(componentSpecific)}
|
|
359
|
+
|
|
360
|
+
// Dark mode shadows
|
|
361
|
+
${generateDarkModeShadows()}
|
|
362
|
+
|
|
363
|
+
// Export to override defaults
|
|
364
|
+
$box-shadow: $custom-shadow-base !default;
|
|
365
|
+
$box-shadow-xs: $custom-shadow-xs !default;
|
|
366
|
+
$box-shadow-sm: $custom-shadow-sm !default;
|
|
367
|
+
$box-shadow-lg: $custom-shadow-lg !default;
|
|
368
|
+
$box-shadow-xl: $custom-shadow-xl !default;
|
|
369
|
+
$box-shadow-inset: $custom-shadow-inner !default;
|
|
370
|
+
|
|
371
|
+
// Dark mode exports
|
|
372
|
+
$box-shadow-dark: $custom-shadow-base-dark !default;
|
|
373
|
+
$box-shadow-xs-dark: $custom-shadow-xs-dark !default;
|
|
374
|
+
$box-shadow-sm-dark: $custom-shadow-sm-dark !default;
|
|
375
|
+
$box-shadow-lg-dark: $custom-shadow-lg-dark !default;
|
|
376
|
+
$box-shadow-xl-dark: $custom-shadow-xl-dark !default;
|
|
377
|
+
`;
|
|
378
|
+
};
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Generate border radius tokens in SCSS format
|
|
382
|
+
*
|
|
383
|
+
* @param config - Radius token configuration
|
|
384
|
+
* @returns SCSS radius tokens string
|
|
385
|
+
*/
|
|
386
|
+
export const generateRadiusTokens = (config: RadiusTokenConfig = {}): string => {
|
|
387
|
+
const {
|
|
388
|
+
baseUnit = '0.25rem',
|
|
389
|
+
scale = {},
|
|
390
|
+
componentSpecific = {},
|
|
391
|
+
} = config;
|
|
392
|
+
|
|
393
|
+
return `// Custom Border Radius Tokens
|
|
394
|
+
// Generated by Atomix CLI
|
|
395
|
+
// =============================================================================
|
|
396
|
+
|
|
397
|
+
// Base radius unit
|
|
398
|
+
$custom-radius-base: ${baseUnit} !default;
|
|
399
|
+
|
|
400
|
+
// Radius Scale
|
|
401
|
+
${generateRadiusScale(scale)}
|
|
402
|
+
|
|
403
|
+
// Component-specific Radius
|
|
404
|
+
${generateComponentRadius(componentSpecific)}
|
|
405
|
+
|
|
406
|
+
// Export to override defaults
|
|
407
|
+
$border-radius-base: $custom-radius-md !default;
|
|
408
|
+
$border-radius-sm: $custom-radius-sm !default;
|
|
409
|
+
$border-radius-lg: $custom-radius-lg !default;
|
|
410
|
+
$border-radius-xl: $custom-radius-xl !default;
|
|
411
|
+
$border-radius-full: $custom-radius-full !default;
|
|
412
|
+
`;
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Generate animation tokens in SCSS format
|
|
417
|
+
*
|
|
418
|
+
* @param config - Animation token configuration
|
|
419
|
+
* @returns SCSS animation tokens string
|
|
420
|
+
*/
|
|
421
|
+
export const generateAnimationTokens = (config: AnimationTokenConfig = {}): string => {
|
|
422
|
+
const {
|
|
423
|
+
durations = {},
|
|
424
|
+
easings = {},
|
|
425
|
+
presets = {},
|
|
426
|
+
} = config;
|
|
427
|
+
|
|
428
|
+
return `// Custom Animation Tokens
|
|
429
|
+
// Generated by Atomix CLI
|
|
430
|
+
// =============================================================================
|
|
431
|
+
|
|
432
|
+
// Animation Durations
|
|
433
|
+
${generateAnimationDurations(durations)}
|
|
434
|
+
|
|
435
|
+
// Easing Functions
|
|
436
|
+
${generateEasings(easings)}
|
|
437
|
+
|
|
438
|
+
// Animation Presets
|
|
439
|
+
${generateAnimationPresets(presets)}
|
|
440
|
+
|
|
441
|
+
// Keyframe Definitions
|
|
442
|
+
${generateKeyframes()}
|
|
443
|
+
`;
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Generate breakpoint tokens in SCSS format
|
|
448
|
+
*
|
|
449
|
+
* @param config - Breakpoint token configuration
|
|
450
|
+
* @returns SCSS breakpoint tokens string
|
|
451
|
+
*/
|
|
452
|
+
export const generateBreakpointTokens = (config: BreakpointTokenConfig = {}): string => {
|
|
453
|
+
const {
|
|
454
|
+
breakpoints = {},
|
|
455
|
+
containerMaxWidths = {},
|
|
456
|
+
} = config;
|
|
457
|
+
|
|
458
|
+
return `// Custom Breakpoint Tokens
|
|
459
|
+
// Generated by Atomix CLI
|
|
460
|
+
// =============================================================================
|
|
461
|
+
|
|
462
|
+
// Responsive Breakpoints
|
|
463
|
+
${generateBreakpoints(breakpoints)}
|
|
464
|
+
|
|
465
|
+
// Container Max Widths
|
|
466
|
+
${generateContainerMaxWidths(containerMaxWidths)}
|
|
467
|
+
|
|
468
|
+
// Media Query Mixins
|
|
469
|
+
${generateMediaQueryMixins(breakpoints)}
|
|
470
|
+
`;
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Generate z-index tokens in SCSS format
|
|
475
|
+
*
|
|
476
|
+
* @param config - Z-Index token configuration
|
|
477
|
+
* @returns SCSS z-index tokens string
|
|
478
|
+
*/
|
|
479
|
+
export const generateZIndexTokens = (config: ZIndexTokenConfig = {}): string => {
|
|
480
|
+
const {
|
|
481
|
+
scale = {},
|
|
482
|
+
} = config;
|
|
483
|
+
|
|
484
|
+
return `// Custom Z-Index Tokens
|
|
485
|
+
// Generated by Atomix CLI
|
|
486
|
+
// =============================================================================
|
|
487
|
+
|
|
488
|
+
// Z-Index Scale
|
|
489
|
+
${generateZIndexScale(scale)}
|
|
490
|
+
|
|
491
|
+
// Component Z-Indexes
|
|
492
|
+
$z-index-dropdown: 1000 !default;
|
|
493
|
+
$z-index-sticky: 1020 !default;
|
|
494
|
+
$z-index-fixed: 1030 !default;
|
|
495
|
+
$z-index-modal-backdrop: 1040 !default;
|
|
496
|
+
$z-index-modal: 1050 !default;
|
|
497
|
+
$z-index-popover: 1060 !default;
|
|
498
|
+
$z-index-tooltip: 1070 !default;
|
|
499
|
+
`;
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Generate complete design token set in JSON format (W3C DTCG)
|
|
504
|
+
*
|
|
505
|
+
* @param categories - Categories to include
|
|
506
|
+
* @returns JSON design tokens object
|
|
507
|
+
*/
|
|
508
|
+
export const generateJSONTokens = (categories: TokenCategory[] = []): Record<string, unknown> => {
|
|
509
|
+
const tokens: Record<string, unknown> = {
|
|
510
|
+
$schema: 'https://design-tokens.org/schema.json',
|
|
511
|
+
version: '1.0.0',
|
|
512
|
+
source: 'Atomix CLI',
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
if (categories.includes('color') || categories.length === 0) {
|
|
516
|
+
tokens.color = {
|
|
517
|
+
primary: {
|
|
518
|
+
1: { value: '#fff9e6', type: 'color' },
|
|
519
|
+
6: { value: '#ffb800', type: 'color' },
|
|
520
|
+
10: { value: '#997000', type: 'color' },
|
|
521
|
+
},
|
|
522
|
+
semantic: {
|
|
523
|
+
success: { value: '#22c55e', type: 'color' },
|
|
524
|
+
warning: { value: '#eab308', type: 'color' },
|
|
525
|
+
error: { value: '#ef4444', type: 'color' },
|
|
526
|
+
info: { value: '#3b82f6', type: 'color' },
|
|
527
|
+
},
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
if (categories.includes('spacing') || categories.length === 0) {
|
|
532
|
+
tokens.spacing = {
|
|
533
|
+
0: { value: '0', type: 'dimension' },
|
|
534
|
+
1: { value: '0.25rem', type: 'dimension' },
|
|
535
|
+
2: { value: '0.5rem', type: 'dimension' },
|
|
536
|
+
4: { value: '1rem', type: 'dimension' },
|
|
537
|
+
8: { value: '2rem', type: 'dimension' },
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
return tokens;
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* Generate CSS custom properties from tokens
|
|
546
|
+
*
|
|
547
|
+
* @param tokens - Token values
|
|
548
|
+
* @returns CSS custom properties string
|
|
549
|
+
*/
|
|
550
|
+
export const generateCSSTokens = (tokens: Record<string, string>): string => {
|
|
551
|
+
const cssVars = Object.entries(tokens)
|
|
552
|
+
.map(([key, value]) => ` --atomix-${key}: ${value};`)
|
|
553
|
+
.join('\n');
|
|
554
|
+
|
|
555
|
+
return `/* CSS Custom Properties */
|
|
556
|
+
/* Generated by Atomix CLI */
|
|
557
|
+
|
|
558
|
+
:root {
|
|
559
|
+
${cssVars}
|
|
560
|
+
}
|
|
561
|
+
`;
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
// ============================================================================
|
|
565
|
+
// Helper Functions
|
|
566
|
+
// ============================================================================
|
|
567
|
+
|
|
568
|
+
const generateBrandColors = (brand: ColorTokenConfig['brand']): string => {
|
|
569
|
+
const { primary = [], secondary = [], accent = [] } = brand;
|
|
570
|
+
|
|
571
|
+
let output = '';
|
|
572
|
+
|
|
573
|
+
if (primary.length > 0) {
|
|
574
|
+
output += '$custom-primary-1: ' + (primary[0] || '#fff9e6') + ' !default;\n';
|
|
575
|
+
output += '$custom-primary-6: ' + (primary[5] || '#ffb800') + ' !default; // Main brand color\n';
|
|
576
|
+
output += '$custom-primary-10: ' + (primary[9] || '#997000') + ' !default;\n';
|
|
577
|
+
} else {
|
|
578
|
+
output += `$custom-primary-1: #fff9e6 !default;
|
|
579
|
+
$custom-primary-2: #fff4cc !default;
|
|
580
|
+
$custom-primary-3: #ffe699 !default;
|
|
581
|
+
$custom-primary-4: #ffd966 !default;
|
|
582
|
+
$custom-primary-5: #ffcc33 !default;
|
|
583
|
+
$custom-primary-6: #ffb800 !default; // Main brand color
|
|
584
|
+
$custom-primary-7: #e6a600 !default;
|
|
585
|
+
$custom-primary-8: #cc9400 !default;
|
|
586
|
+
$custom-primary-9: #b38200 !default;
|
|
587
|
+
$custom-primary-10: #997000 !default;
|
|
588
|
+
`;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
return output;
|
|
592
|
+
};
|
|
593
|
+
|
|
594
|
+
const generateSemanticColors = (semantic: ColorTokenConfig['semantic']): string => {
|
|
595
|
+
const {
|
|
596
|
+
success = '#22c55e',
|
|
597
|
+
warning = '#eab308',
|
|
598
|
+
error = '#ef4444',
|
|
599
|
+
info = '#3b82f6',
|
|
600
|
+
} = semantic;
|
|
601
|
+
|
|
602
|
+
return `$custom-success: ${success} !default;
|
|
603
|
+
$custom-warning: ${warning} !default;
|
|
604
|
+
$custom-error: ${error} !default;
|
|
605
|
+
$custom-info: ${info} !default;
|
|
606
|
+
`;
|
|
607
|
+
};
|
|
608
|
+
|
|
609
|
+
const generateNeutralColors = (neutral: string[]): string => {
|
|
610
|
+
if (neutral.length === 0) {
|
|
611
|
+
return `$custom-gray-1: #f9fafb !default;
|
|
612
|
+
$custom-gray-2: #f3f4f6 !default;
|
|
613
|
+
$custom-gray-3: #e5e7eb !default;
|
|
614
|
+
$custom-gray-4: #d1d5db !default;
|
|
615
|
+
$custom-gray-5: #9ca3af !default;
|
|
616
|
+
$custom-gray-6: #6b7280 !default;
|
|
617
|
+
$custom-gray-7: #4b5563 !default;
|
|
618
|
+
$custom-gray-8: #374151 !default;
|
|
619
|
+
$custom-gray-9: #1f2937 !default;
|
|
620
|
+
$custom-gray-10: #111827 !default;
|
|
621
|
+
`;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
return neutral.map((color, i) => `$custom-gray-${i + 1}: ${color} !default;`).join('\n') + '\n';
|
|
625
|
+
};
|
|
626
|
+
|
|
627
|
+
const generateBackgroundColors = (background: ColorTokenConfig['background']): string => {
|
|
628
|
+
const { light = '#ffffff', dark = '#1f2937' } = background;
|
|
629
|
+
return `$custom-body-bg: ${light} !default;
|
|
630
|
+
$custom-body-bg-dark: ${dark} !default;
|
|
631
|
+
`;
|
|
632
|
+
};
|
|
633
|
+
|
|
634
|
+
const generateTextColors = (text: ColorTokenConfig['text']): string => {
|
|
635
|
+
const { light = '#111827', dark = '#ffffff' } = text;
|
|
636
|
+
return `$custom-body-color: ${light} !default;
|
|
637
|
+
$custom-body-color-dark: ${dark} !default;
|
|
638
|
+
`;
|
|
639
|
+
};
|
|
640
|
+
|
|
641
|
+
const generateBorderColors = (border: ColorTokenConfig['border']): string => {
|
|
642
|
+
const { light = '#e5e7eb', dark = '#4b5563' } = border;
|
|
643
|
+
return `$custom-border-color: ${light} !default;
|
|
644
|
+
$custom-border-color-dark: ${dark} !default;
|
|
645
|
+
`;
|
|
646
|
+
};
|
|
647
|
+
|
|
648
|
+
const generateFocusColors = (focus: ColorTokenConfig['focus']): string => {
|
|
649
|
+
const { light = '#ffcc33', dark = '#ffd966' } = focus;
|
|
650
|
+
return `$custom-focus-color: ${light} !default;
|
|
651
|
+
$custom-focus-color-dark: ${dark} !default;
|
|
652
|
+
`;
|
|
653
|
+
};
|
|
654
|
+
|
|
655
|
+
const generateSpacingScale = (scale: number[]): string => {
|
|
656
|
+
return scale
|
|
657
|
+
.map((value) => `$custom-spacing-${value}: calc($custom-spacing-base * ${value}) !default; // ${value * 4}px`)
|
|
658
|
+
.join('\n') + '\n';
|
|
659
|
+
};
|
|
660
|
+
|
|
661
|
+
const generateComponentSpacing = (componentSpecific: SpacingTokenConfig['componentSpecific']): string => {
|
|
662
|
+
const {
|
|
663
|
+
buttonPaddingX = '$custom-spacing-4',
|
|
664
|
+
buttonPaddingY = '$custom-spacing-2',
|
|
665
|
+
cardPadding = '$custom-spacing-6',
|
|
666
|
+
modalPadding = '$custom-spacing-8',
|
|
667
|
+
} = componentSpecific;
|
|
668
|
+
|
|
669
|
+
return `$custom-button-padding-x: ${buttonPaddingX} !default;
|
|
670
|
+
$custom-button-padding-y: ${buttonPaddingY} !default;
|
|
671
|
+
$custom-card-padding: ${cardPadding} !default;
|
|
672
|
+
$custom-modal-padding: ${modalPadding} !default;
|
|
673
|
+
`;
|
|
674
|
+
};
|
|
675
|
+
|
|
676
|
+
const generateLayoutSpacing = (layout: SpacingTokenConfig['layout']): string => {
|
|
677
|
+
const {
|
|
678
|
+
containerPadding = '$custom-spacing-4',
|
|
679
|
+
gridGap = '$custom-spacing-6',
|
|
680
|
+
sectionSpacing = '$custom-spacing-16',
|
|
681
|
+
} = layout;
|
|
682
|
+
|
|
683
|
+
return `$custom-container-padding: ${containerPadding} !default;
|
|
684
|
+
$custom-grid-gap: ${gridGap} !default;
|
|
685
|
+
$custom-section-spacing: ${sectionSpacing} !default;
|
|
686
|
+
`;
|
|
687
|
+
};
|
|
688
|
+
|
|
689
|
+
const generateFontFamilies = (fontFamilies: TypographyTokenConfig['fontFamilies']): string => {
|
|
690
|
+
const {
|
|
691
|
+
sans = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
|
|
692
|
+
serif = 'Georgia, "Times New Roman", Times, serif',
|
|
693
|
+
mono = 'SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',
|
|
694
|
+
} = fontFamilies;
|
|
695
|
+
|
|
696
|
+
return `$custom-font-family-sans: ${sans} !default;
|
|
697
|
+
$custom-font-family-serif: ${serif} !default;
|
|
698
|
+
$custom-font-family-mono: ${mono} !default;
|
|
699
|
+
`;
|
|
700
|
+
};
|
|
701
|
+
|
|
702
|
+
const generateFontSizes = (fontSizes: TypographyTokenConfig['fontSizes']): string => {
|
|
703
|
+
const defaultSizes: Record<string, string> = {
|
|
704
|
+
xs: '0.75rem',
|
|
705
|
+
sm: '0.875rem',
|
|
706
|
+
base: '1rem',
|
|
707
|
+
lg: '1.125rem',
|
|
708
|
+
xl: '1.25rem',
|
|
709
|
+
'2xl': '1.5rem',
|
|
710
|
+
'3xl': '1.875rem',
|
|
711
|
+
'4xl': '2.25rem',
|
|
712
|
+
'5xl': '3rem',
|
|
713
|
+
};
|
|
714
|
+
|
|
715
|
+
const sizes = { ...defaultSizes, ...fontSizes };
|
|
716
|
+
|
|
717
|
+
return Object.entries(sizes)
|
|
718
|
+
.map(([key, value]) => `$custom-font-size-${key}: ${value} !default;`)
|
|
719
|
+
.join('\n') + '\n';
|
|
720
|
+
};
|
|
721
|
+
|
|
722
|
+
const generateLineHeights = (lineHeights: TypographyTokenConfig['lineHeights']): string => {
|
|
723
|
+
const {
|
|
724
|
+
tight = 1.2,
|
|
725
|
+
base = 1.5,
|
|
726
|
+
relaxed = 1.75,
|
|
727
|
+
loose = 2,
|
|
728
|
+
} = lineHeights;
|
|
729
|
+
|
|
730
|
+
return `$custom-line-height-tight: ${tight} !default;
|
|
731
|
+
$custom-line-height-base: ${base} !default;
|
|
732
|
+
$custom-line-height-relaxed: ${relaxed} !default;
|
|
733
|
+
$custom-line-height-loose: ${loose} !default;
|
|
734
|
+
`;
|
|
735
|
+
};
|
|
736
|
+
|
|
737
|
+
const generateFontWeights = (fontWeights: TypographyTokenConfig['fontWeights']): string => {
|
|
738
|
+
const defaultWeights: Record<string, number> = {
|
|
739
|
+
light: 300,
|
|
740
|
+
normal: 400,
|
|
741
|
+
medium: 500,
|
|
742
|
+
semibold: 600,
|
|
743
|
+
bold: 700,
|
|
744
|
+
heavy: 800,
|
|
745
|
+
black: 900,
|
|
746
|
+
};
|
|
747
|
+
|
|
748
|
+
const weights = { ...defaultWeights, ...fontWeights };
|
|
749
|
+
|
|
750
|
+
return Object.entries(weights)
|
|
751
|
+
.map(([key, value]) => `$custom-font-weight-${key}: ${value} !default;`)
|
|
752
|
+
.join('\n') + '\n';
|
|
753
|
+
};
|
|
754
|
+
|
|
755
|
+
const generateLetterSpacing = (letterSpacing: TypographyTokenConfig['letterSpacing']): string => {
|
|
756
|
+
const {
|
|
757
|
+
tight = '-0.05em',
|
|
758
|
+
normal = '0',
|
|
759
|
+
wide = '0.025em',
|
|
760
|
+
wider = '0.05em',
|
|
761
|
+
widest = '0.1em',
|
|
762
|
+
} = letterSpacing;
|
|
763
|
+
|
|
764
|
+
return `$custom-letter-spacing-tight: ${tight} !default;
|
|
765
|
+
$custom-letter-spacing-normal: ${normal} !default;
|
|
766
|
+
$custom-letter-spacing-wide: ${wide} !default;
|
|
767
|
+
$custom-letter-spacing-wider: ${wider} !default;
|
|
768
|
+
$custom-letter-spacing-widest: ${widest} !default;
|
|
769
|
+
`;
|
|
770
|
+
};
|
|
771
|
+
|
|
772
|
+
const generateHeadingSizes = (headings: TypographyTokenConfig['headings']): string => {
|
|
773
|
+
const defaultHeadings = {
|
|
774
|
+
h1: { fontSize: '$custom-font-size-5xl' },
|
|
775
|
+
h2: { fontSize: '$custom-font-size-4xl' },
|
|
776
|
+
h3: { fontSize: '$custom-font-size-3xl' },
|
|
777
|
+
h4: { fontSize: '$custom-font-size-2xl' },
|
|
778
|
+
h5: { fontSize: '$custom-font-size-xl' },
|
|
779
|
+
h6: { fontSize: '$custom-font-size-lg' },
|
|
780
|
+
};
|
|
781
|
+
|
|
782
|
+
const mergedHeadings = { ...defaultHeadings, ...headings };
|
|
783
|
+
|
|
784
|
+
return Object.entries(mergedHeadings)
|
|
785
|
+
.map(([key, config]) => `$custom-${key}-font-size: ${(config as { fontSize?: string }).fontSize || '$custom-font-size-' + key} !default;`)
|
|
786
|
+
.join('\n') + '\n';
|
|
787
|
+
};
|
|
788
|
+
|
|
789
|
+
const generateShadowColors = (colors: ShadowTokenConfig['colors']): string => {
|
|
790
|
+
const {
|
|
791
|
+
light = 'rgba(0, 0, 0, 0.1)',
|
|
792
|
+
dark = 'rgba(0, 0, 0, 0.2)',
|
|
793
|
+
} = colors;
|
|
794
|
+
|
|
795
|
+
return `$custom-shadow-color: ${light} !default;
|
|
796
|
+
$custom-shadow-color-dark: ${dark} !default;
|
|
797
|
+
`;
|
|
798
|
+
};
|
|
799
|
+
|
|
800
|
+
const generateShadowScale = (shadows: ShadowTokenConfig['shadows']): string => {
|
|
801
|
+
const defaultShadows: Record<string, string> = {
|
|
802
|
+
xs: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
|
|
803
|
+
sm: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
|
|
804
|
+
base: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
|
|
805
|
+
md: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
|
|
806
|
+
lg: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
|
|
807
|
+
xl: '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
|
|
808
|
+
'2xl': '0 35px 60px -15px rgba(0, 0, 0, 0.3)',
|
|
809
|
+
inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',
|
|
810
|
+
none: 'none',
|
|
811
|
+
};
|
|
812
|
+
|
|
813
|
+
const mergedShadows = { ...defaultShadows, ...shadows };
|
|
814
|
+
|
|
815
|
+
return Object.entries(mergedShadows)
|
|
816
|
+
.map(([key, value]) => `$custom-shadow-${key}: ${value} !default;`)
|
|
817
|
+
.join('\n') + '\n';
|
|
818
|
+
};
|
|
819
|
+
|
|
820
|
+
const generateComponentShadows = (componentSpecific: ShadowTokenConfig['componentSpecific']): string => {
|
|
821
|
+
const {
|
|
822
|
+
button = '$custom-shadow-sm',
|
|
823
|
+
buttonHover = '$custom-shadow-md',
|
|
824
|
+
card = '$custom-shadow-base',
|
|
825
|
+
dropdown = '$custom-shadow-lg',
|
|
826
|
+
modal = '$custom-shadow-xl',
|
|
827
|
+
popover = '$custom-shadow-lg',
|
|
828
|
+
tooltip = '$custom-shadow-md',
|
|
829
|
+
} = componentSpecific;
|
|
830
|
+
|
|
831
|
+
return `$custom-button-shadow: ${button} !default;
|
|
832
|
+
$custom-button-shadow-hover: ${buttonHover} !default;
|
|
833
|
+
$custom-card-shadow: ${card} !default;
|
|
834
|
+
$custom-dropdown-shadow: ${dropdown} !default;
|
|
835
|
+
$custom-modal-shadow: ${modal} !default;
|
|
836
|
+
$custom-popover-shadow: ${popover} !default;
|
|
837
|
+
$custom-tooltip-shadow: ${tooltip} !default;
|
|
838
|
+
`;
|
|
839
|
+
};
|
|
840
|
+
|
|
841
|
+
const generateDarkModeShadows = (): string => {
|
|
842
|
+
return `$custom-shadow-xs-dark: 0 1px 2px 0 rgba(0, 0, 0, 0.3) !default;
|
|
843
|
+
$custom-shadow-sm-dark: 0 1px 3px 0 rgba(0, 0, 0, 0.4), 0 1px 2px 0 rgba(0, 0, 0, 0.3) !default;
|
|
844
|
+
$custom-shadow-base-dark: 0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -1px rgba(0, 0, 0, 0.3) !default;
|
|
845
|
+
$custom-shadow-lg-dark: 0 20px 25px -5px rgba(0, 0, 0, 0.5), 0 10px 10px -5px rgba(0, 0, 0, 0.4) !default;
|
|
846
|
+
$custom-shadow-xl-dark: 0 25px 50px -12px rgba(0, 0, 0, 0.6) !default;
|
|
847
|
+
`;
|
|
848
|
+
};
|
|
849
|
+
|
|
850
|
+
const generateRadiusScale = (scale: RadiusTokenConfig['scale']): string => {
|
|
851
|
+
const defaultScale: Record<string, string> = {
|
|
852
|
+
none: '0',
|
|
853
|
+
sm: '0.125rem',
|
|
854
|
+
md: '0.25rem',
|
|
855
|
+
lg: '0.5rem',
|
|
856
|
+
xl: '0.75rem',
|
|
857
|
+
'2xl': '1rem',
|
|
858
|
+
full: '9999px',
|
|
859
|
+
pill: '9999px',
|
|
860
|
+
};
|
|
861
|
+
|
|
862
|
+
const mergedScale = { ...defaultScale, ...scale };
|
|
863
|
+
|
|
864
|
+
return Object.entries(mergedScale)
|
|
865
|
+
.map(([key, value]) => `$custom-radius-${key}: ${value} !default;`)
|
|
866
|
+
.join('\n') + '\n';
|
|
867
|
+
};
|
|
868
|
+
|
|
869
|
+
const generateComponentRadius = (componentSpecific: RadiusTokenConfig['componentSpecific']): string => {
|
|
870
|
+
const {
|
|
871
|
+
button = '$custom-radius-md',
|
|
872
|
+
card = '$custom-radius-lg',
|
|
873
|
+
input = '$custom-radius-md',
|
|
874
|
+
badge = '$custom-radius-full',
|
|
875
|
+
} = componentSpecific;
|
|
876
|
+
|
|
877
|
+
return `$custom-button-radius: ${button} !default;
|
|
878
|
+
$custom-card-radius: ${card} !default;
|
|
879
|
+
$custom-input-radius: ${input} !default;
|
|
880
|
+
$custom-badge-radius: ${badge} !default;
|
|
881
|
+
`;
|
|
882
|
+
};
|
|
883
|
+
|
|
884
|
+
const generateAnimationDurations = (durations: AnimationTokenConfig['durations']): string => {
|
|
885
|
+
const defaultDurations: Record<string, string> = {
|
|
886
|
+
instant: '0ms',
|
|
887
|
+
fast: '150ms',
|
|
888
|
+
base: '300ms',
|
|
889
|
+
slow: '500ms',
|
|
890
|
+
slower: '750ms',
|
|
891
|
+
durationless: '0ms',
|
|
892
|
+
};
|
|
893
|
+
|
|
894
|
+
const mergedDurations = { ...defaultDurations, ...durations };
|
|
895
|
+
|
|
896
|
+
return Object.entries(mergedDurations)
|
|
897
|
+
.map(([key, value]) => `$custom-duration-${key}: ${value} !default;`)
|
|
898
|
+
.join('\n') + '\n';
|
|
899
|
+
};
|
|
900
|
+
|
|
901
|
+
const generateEasings = (easings: AnimationTokenConfig['easings']): string => {
|
|
902
|
+
const defaultEasings: Record<string, string> = {
|
|
903
|
+
linear: 'linear',
|
|
904
|
+
ease: 'ease',
|
|
905
|
+
'ease-in': 'cubic-bezier(0.4, 0, 1, 1)',
|
|
906
|
+
'ease-out': 'cubic-bezier(0, 0, 0.2, 1)',
|
|
907
|
+
'ease-in-out': 'cubic-bezier(0.4, 0, 0.2, 1)',
|
|
908
|
+
smooth: 'cubic-bezier(0.23, 1, 0.32, 1)', // Atomix Ease
|
|
909
|
+
bounce: 'cubic-bezier(0.68, -0.55, 0.265, 1.55)',
|
|
910
|
+
};
|
|
911
|
+
|
|
912
|
+
return Object.entries({ ...defaultEasings, ...easings })
|
|
913
|
+
.map(([key, value]) => `$custom-easing-${key}: ${value} !default;`)
|
|
914
|
+
.join('\n') + '\n';
|
|
915
|
+
};
|
|
916
|
+
|
|
917
|
+
const generateAnimationPresets = (presets: AnimationTokenConfig['presets']): string => {
|
|
918
|
+
const defaultPresets = {
|
|
919
|
+
fadeIn: 'atomix-fade-in var(--atomix-duration-base) var(--atomix-easing-smooth)',
|
|
920
|
+
slideInUp: 'atomix-slide-in-up var(--atomix-duration-slow) var(--atomix-easing-smooth)',
|
|
921
|
+
scaleIn: 'atomix-scale-in var(--atomix-duration-base) var(--atomix-easing-smooth)',
|
|
922
|
+
pulse: 'atomix-pulse 2s var(--atomix-easing-smooth) infinite',
|
|
923
|
+
shimmer: 'atomix-shimmer 2s linear infinite',
|
|
924
|
+
};
|
|
925
|
+
|
|
926
|
+
const mergedPresets = { ...defaultPresets, ...presets };
|
|
927
|
+
|
|
928
|
+
return Object.entries(mergedPresets)
|
|
929
|
+
.map(([key, value]) => `$custom-animation-${key}: ${value} !default;`)
|
|
930
|
+
.join('\n') + '\n';
|
|
931
|
+
};
|
|
932
|
+
|
|
933
|
+
const generateKeyframes = (): string => {
|
|
934
|
+
return `@keyframes atomix-fade-in {
|
|
935
|
+
from { opacity: 0; }
|
|
936
|
+
to { opacity: 1; }
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
@keyframes atomix-slide-in-up {
|
|
940
|
+
from {
|
|
941
|
+
opacity: 0;
|
|
942
|
+
transform: translateY(20px);
|
|
943
|
+
}
|
|
944
|
+
to {
|
|
945
|
+
opacity: 1;
|
|
946
|
+
transform: translateY(0);
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
@keyframes atomix-scale-in {
|
|
951
|
+
from {
|
|
952
|
+
opacity: 0;
|
|
953
|
+
transform: scale(0.9);
|
|
954
|
+
}
|
|
955
|
+
to {
|
|
956
|
+
opacity: 1;
|
|
957
|
+
transform: scale(1);
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
@keyframes atomix-pulse {
|
|
962
|
+
0%, 100% { opacity: 1; }
|
|
963
|
+
50% { opacity: 0.5; }
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
@keyframes atomix-shimmer {
|
|
967
|
+
0% { background-position: -200% 0; }
|
|
968
|
+
100% { background-position: 200% 0; }
|
|
969
|
+
}
|
|
970
|
+
`;
|
|
971
|
+
};
|
|
972
|
+
|
|
973
|
+
const generateBreakpoints = (breakpoints: BreakpointTokenConfig['breakpoints']): string => {
|
|
974
|
+
const defaultBreakpoints: Record<string, string> = {
|
|
975
|
+
sm: '640px',
|
|
976
|
+
md: '768px',
|
|
977
|
+
lg: '1024px',
|
|
978
|
+
xl: '1280px',
|
|
979
|
+
'2xl': '1536px',
|
|
980
|
+
};
|
|
981
|
+
|
|
982
|
+
const mergedBreakpoints = { ...defaultBreakpoints, ...breakpoints };
|
|
983
|
+
|
|
984
|
+
return Object.entries(mergedBreakpoints)
|
|
985
|
+
.map(([key, value]) => `$breakpoint-${key}: ${value} !default;`)
|
|
986
|
+
.join('\n') + '\n';
|
|
987
|
+
};
|
|
988
|
+
|
|
989
|
+
const generateContainerMaxWidths = (containerMaxWidths: BreakpointTokenConfig['containerMaxWidths']): string => {
|
|
990
|
+
const defaultMaxWidths: Record<string, string> = {
|
|
991
|
+
sm: '640px',
|
|
992
|
+
md: '768px',
|
|
993
|
+
lg: '1024px',
|
|
994
|
+
xl: '1280px',
|
|
995
|
+
'2xl': '1536px',
|
|
996
|
+
};
|
|
997
|
+
|
|
998
|
+
const mergedMaxWidths = { ...defaultMaxWidths, ...containerMaxWidths };
|
|
999
|
+
|
|
1000
|
+
return `$container-max-widths: (\n sm: ${mergedMaxWidths.sm || '640px'},\n md: ${mergedMaxWidths.md || '768px'},\n lg: ${mergedMaxWidths.lg || '1024px'},\n xl: ${mergedMaxWidths.xl || '1280px'},\n '2xl': ${mergedMaxWidths['2xl'] || '1536px'},\n) !default;\n`;
|
|
1001
|
+
};
|
|
1002
|
+
|
|
1003
|
+
const generateMediaQueryMixins = (breakpoints: BreakpointTokenConfig['breakpoints']): string => {
|
|
1004
|
+
const mergedBreakpoints = {
|
|
1005
|
+
sm: '640px',
|
|
1006
|
+
md: '768px',
|
|
1007
|
+
lg: '1024px',
|
|
1008
|
+
xl: '1280px',
|
|
1009
|
+
'2xl': '1536px',
|
|
1010
|
+
...breakpoints,
|
|
1011
|
+
};
|
|
1012
|
+
|
|
1013
|
+
return `// Media Query Mixins
|
|
1014
|
+
@mixin atomix-media-breakpoint-up($breakpoint) {
|
|
1015
|
+
@if map-has-key($breakpoint-map, $breakpoint) {
|
|
1016
|
+
$min-width: map-get($breakpoint-map, $breakpoint);
|
|
1017
|
+
@media (min-width: $min-width) {
|
|
1018
|
+
@content;
|
|
1019
|
+
}
|
|
1020
|
+
} @else {
|
|
1021
|
+
@warn "Unknown breakpoint: #{$breakpoint}";
|
|
1022
|
+
@content;
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
@mixin atomix-media-breakpoint-down($breakpoint) {
|
|
1027
|
+
@if map-has-key($breakpoint-map, $breakpoint) {
|
|
1028
|
+
$max-width: map-get($breakpoint-map, $breakpoint);
|
|
1029
|
+
@media (max-width: $max-width) {
|
|
1030
|
+
@content;
|
|
1031
|
+
}
|
|
1032
|
+
} @else {
|
|
1033
|
+
@warn "Unknown breakpoint: #{$breakpoint}";
|
|
1034
|
+
@content;
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
// Breakpoint map for mixins
|
|
1039
|
+
$breakpoint-map: (
|
|
1040
|
+
sm: ${mergedBreakpoints.sm},
|
|
1041
|
+
md: ${mergedBreakpoints.md},
|
|
1042
|
+
lg: ${mergedBreakpoints.lg},
|
|
1043
|
+
xl: ${mergedBreakpoints.xl},
|
|
1044
|
+
'2xl': ${mergedBreakpoints['2xl']},
|
|
1045
|
+
) !default;
|
|
1046
|
+
`;
|
|
1047
|
+
};
|
|
1048
|
+
|
|
1049
|
+
const generateZIndexScale = (scale: ZIndexTokenConfig['scale']): string => {
|
|
1050
|
+
const defaultScale: Record<string, number> = {
|
|
1051
|
+
hide: -1,
|
|
1052
|
+
base: 0,
|
|
1053
|
+
dropdown: 1000,
|
|
1054
|
+
sticky: 1020,
|
|
1055
|
+
fixed: 1030,
|
|
1056
|
+
modalBackdrop: 1040,
|
|
1057
|
+
modal: 1050,
|
|
1058
|
+
popover: 1060,
|
|
1059
|
+
tooltip: 1070,
|
|
1060
|
+
};
|
|
1061
|
+
|
|
1062
|
+
const mergedScale = { ...defaultScale, ...scale };
|
|
1063
|
+
|
|
1064
|
+
return Object.entries(mergedScale)
|
|
1065
|
+
.map(([key, value]) => `$z-index-${key.replace(/([A-Z])/g, '-$1').toLowerCase()}: ${value} !default;`)
|
|
1066
|
+
.join('\n') + '\n';
|
|
1067
|
+
};
|
|
1068
|
+
|
|
1069
|
+
/**
|
|
1070
|
+
* All token generation functions
|
|
1071
|
+
*/
|
|
1072
|
+
export const tokenGenerators = {
|
|
1073
|
+
color: generateColorTokens,
|
|
1074
|
+
spacing: generateSpacingTokens,
|
|
1075
|
+
typography: generateTypographyTokens,
|
|
1076
|
+
shadow: generateShadowTokens,
|
|
1077
|
+
radius: generateRadiusTokens,
|
|
1078
|
+
animation: generateAnimationTokens,
|
|
1079
|
+
breakpoint: generateBreakpointTokens,
|
|
1080
|
+
zIndex: generateZIndexTokens,
|
|
1081
|
+
json: generateJSONTokens,
|
|
1082
|
+
css: generateCSSTokens,
|
|
1083
|
+
};
|
|
1084
|
+
|
|
1085
|
+
/**
|
|
1086
|
+
* Type for token generators object
|
|
1087
|
+
*/
|
|
1088
|
+
export type TokenGenerators = typeof tokenGenerators;
|