@shohojdhara/atomix 0.3.2 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -21
- package/dist/atomix.css +96 -121
- package/dist/atomix.min.css +3 -3
- package/dist/index.d.ts +7937 -7765
- package/dist/index.esm.js +3677 -4031
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +3648 -3952
- 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 +44 -16
- package/scripts/atomix-cli.js +1764 -0
- package/scripts/build-themes.js +208 -0
- package/scripts/cli/interactive-init.js +520 -0
- package/scripts/cli/migration-tools.js +603 -0
- package/scripts/cli/theme-bridge.js +129 -0
- package/scripts/cli/token-manager.js +519 -0
- package/scripts/sync-theme-config.js +309 -0
- package/src/components/Button/Button.tsx +36 -1
- package/src/components/List/ListGroup.tsx +1 -2
- package/src/components/Popover/Popover.tsx +2 -2
- package/src/components/Tooltip/Tooltip.stories.tsx +49 -12
- package/src/components/Tooltip/Tooltip.tsx +32 -58
- package/src/lib/composables/useTooltip.ts +285 -0
- package/src/lib/config/index.ts +275 -0
- package/src/lib/config/loader.ts +105 -0
- package/src/lib/constants/cssVariables.ts +390 -0
- package/src/lib/hooks/__tests__/useComponentCustomization.test.ts +151 -0
- package/src/lib/hooks/index.ts +19 -0
- package/src/lib/hooks/useComponentCustomization.ts +175 -0
- package/src/lib/index.ts +14 -1
- package/src/lib/patterns/__tests__/slots.test.ts +108 -0
- package/src/lib/patterns/index.ts +35 -0
- package/src/lib/patterns/slots.tsx +421 -0
- package/src/lib/theme/composeTheme.ts +0 -5
- package/src/lib/theme/config/index.ts +1 -1
- package/src/lib/theme/config/loader.ts +75 -41
- package/src/lib/theme/config/types.ts +21 -7
- package/src/lib/theme/config/validator.ts +1 -1
- package/src/lib/theme/constants.ts +12 -2
- package/src/lib/theme/createTheme.ts +2 -135
- package/src/lib/theme/createThemeFromConfig.ts +132 -0
- package/src/lib/theme/cssVariableMapper.ts +261 -0
- package/src/lib/theme/devtools/CLI.ts +161 -76
- package/src/lib/theme/devtools/Comparator.tsx +343 -0
- package/src/lib/theme/devtools/IMPROVEMENTS.md +429 -0
- package/src/lib/theme/devtools/Inspector.tsx +21 -6
- package/src/lib/theme/devtools/LiveEditor.tsx +393 -0
- package/src/lib/theme/devtools/README.md +433 -0
- package/src/lib/theme/devtools/index.ts +12 -11
- package/src/lib/theme/generateCSSVariables.ts +79 -38
- package/src/lib/theme/index.ts +45 -246
- package/src/lib/theme/runtime/ThemeApplicator.ts +252 -0
- package/src/lib/theme/runtime/ThemeManager.test.ts +17 -1
- package/src/lib/theme/runtime/ThemeManager.ts +7 -7
- package/src/lib/theme/themeUtils.ts +27 -5
- package/src/lib/theme/types.ts +59 -1
- package/src/lib/theme-tools.ts +125 -0
- package/src/lib/types/components.ts +260 -72
- package/src/lib/types/partProps.ts +426 -0
- package/src/lib/utils/__tests__/componentUtils.test.ts +144 -0
- package/src/lib/utils/componentUtils.ts +163 -0
- package/src/lib/utils/index.ts +17 -57
- package/src/styles/01-settings/_settings.colors.scss +10 -10
- package/src/styles/01-settings/_settings.navbar.scss +1 -1
- package/src/styles/01-settings/_settings.tooltip.scss +1 -1
- package/src/styles/03-generic/_generated-root.css +5 -0
- package/src/styles/06-components/_components.navbar.scss +12 -5
- package/src/styles/06-components/_components.tooltip.scss +31 -81
- package/src/themes/README.md +442 -0
- package/src/themes/themes.config.js +35 -0
- package/src/lib/theme/errors.test.ts +0 -207
- package/src/lib/theme/generators/CSSGenerator.ts +0 -311
- package/src/lib/theme/generators/ConfigGenerator.ts +0 -287
- package/src/lib/theme/generators/TypeGenerator.ts +0 -228
- package/src/lib/theme/generators/index.ts +0 -21
- package/src/lib/theme/monitoring/ThemeAnalytics.ts +0 -409
- package/src/lib/theme/monitoring/index.ts +0 -17
- package/src/lib/theme/overrides/ComponentOverrides.ts +0 -243
- package/src/lib/theme/overrides/index.ts +0 -15
- package/src/lib/theme/studio/ThemeStudio.tsx +0 -312
- package/src/lib/theme/studio/index.ts +0 -8
- package/src/lib/theme/whitelabel/WhiteLabelManager.ts +0 -364
- package/src/lib/theme/whitelabel/index.ts +0 -13
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSS Variables Constants
|
|
3
|
+
*
|
|
4
|
+
* Comprehensive CSS custom property definitions for all components.
|
|
5
|
+
* These provide type-safe access to component styling variables.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Button CSS Variables
|
|
10
|
+
*/
|
|
11
|
+
export const BUTTON_CSS_VARS = {
|
|
12
|
+
// Base properties
|
|
13
|
+
'--atomix-button-bg': 'background-color',
|
|
14
|
+
'--atomix-button-color': 'text color',
|
|
15
|
+
'--atomix-button-padding-x': 'horizontal padding',
|
|
16
|
+
'--atomix-button-padding-y': 'vertical padding',
|
|
17
|
+
'--atomix-button-border-radius': 'border radius',
|
|
18
|
+
'--atomix-button-border-width': 'border width',
|
|
19
|
+
'--atomix-button-border-color': 'border color',
|
|
20
|
+
'--atomix-button-font-size': 'font size',
|
|
21
|
+
'--atomix-button-font-weight': 'font weight',
|
|
22
|
+
'--atomix-button-font-family': 'font family',
|
|
23
|
+
'--atomix-button-line-height': 'line height',
|
|
24
|
+
'--atomix-button-min-width': 'minimum width',
|
|
25
|
+
'--atomix-button-min-height': 'minimum height',
|
|
26
|
+
'--atomix-button-transition': 'transition',
|
|
27
|
+
|
|
28
|
+
// State properties
|
|
29
|
+
'--atomix-button-hover-bg': 'hover background',
|
|
30
|
+
'--atomix-button-hover-color': 'hover text color',
|
|
31
|
+
'--atomix-button-hover-border-color': 'hover border color',
|
|
32
|
+
'--atomix-button-active-bg': 'active background',
|
|
33
|
+
'--atomix-button-active-color': 'active text color',
|
|
34
|
+
'--atomix-button-focus-ring-color': 'focus ring color',
|
|
35
|
+
'--atomix-button-focus-ring-width': 'focus ring width',
|
|
36
|
+
'--atomix-button-disabled-opacity': 'disabled opacity',
|
|
37
|
+
'--atomix-button-disabled-bg': 'disabled background',
|
|
38
|
+
|
|
39
|
+
// Part properties
|
|
40
|
+
'--atomix-button-icon-size': 'icon size',
|
|
41
|
+
'--atomix-button-icon-gap': 'icon spacing',
|
|
42
|
+
'--atomix-button-spinner-size': 'spinner size',
|
|
43
|
+
'--atomix-button-label-font-weight': 'label font weight',
|
|
44
|
+
} as const;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Card CSS Variables
|
|
48
|
+
*/
|
|
49
|
+
export const CARD_CSS_VARS = {
|
|
50
|
+
// Base properties
|
|
51
|
+
'--atomix-card-bg': 'background color',
|
|
52
|
+
'--atomix-card-color': 'text color',
|
|
53
|
+
'--atomix-card-padding': 'padding',
|
|
54
|
+
'--atomix-card-border-radius': 'border radius',
|
|
55
|
+
'--atomix-card-border-width': 'border width',
|
|
56
|
+
'--atomix-card-border-color': 'border color',
|
|
57
|
+
'--atomix-card-box-shadow': 'box shadow',
|
|
58
|
+
'--atomix-card-width': 'width',
|
|
59
|
+
'--atomix-card-max-width': 'maximum width',
|
|
60
|
+
|
|
61
|
+
// State properties
|
|
62
|
+
'--atomix-card-hover-bg': 'hover background',
|
|
63
|
+
'--atomix-card-hover-shadow': 'hover shadow',
|
|
64
|
+
'--atomix-card-hover-transform': 'hover transform',
|
|
65
|
+
|
|
66
|
+
// Part properties - Header
|
|
67
|
+
'--atomix-card-header-padding': 'header padding',
|
|
68
|
+
'--atomix-card-header-bg': 'header background',
|
|
69
|
+
'--atomix-card-header-border-bottom': 'header border bottom',
|
|
70
|
+
|
|
71
|
+
// Part properties - Body
|
|
72
|
+
'--atomix-card-body-padding': 'body padding',
|
|
73
|
+
'--atomix-card-body-font-size': 'body font size',
|
|
74
|
+
|
|
75
|
+
// Part properties - Footer
|
|
76
|
+
'--atomix-card-footer-padding': 'footer padding',
|
|
77
|
+
'--atomix-card-footer-bg': 'footer background',
|
|
78
|
+
'--atomix-card-footer-border-top': 'footer border top',
|
|
79
|
+
|
|
80
|
+
// Part properties - Title
|
|
81
|
+
'--atomix-card-title-font-size': 'title font size',
|
|
82
|
+
'--atomix-card-title-font-weight': 'title font weight',
|
|
83
|
+
'--atomix-card-title-color': 'title color',
|
|
84
|
+
'--atomix-card-title-margin-bottom': 'title margin bottom',
|
|
85
|
+
|
|
86
|
+
// Part properties - Image
|
|
87
|
+
'--atomix-card-image-border-radius': 'image border radius',
|
|
88
|
+
'--atomix-card-image-max-height': 'image max height',
|
|
89
|
+
} as const;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Input CSS Variables
|
|
93
|
+
*/
|
|
94
|
+
export const INPUT_CSS_VARS = {
|
|
95
|
+
// Base properties
|
|
96
|
+
'--atomix-input-bg': 'background color',
|
|
97
|
+
'--atomix-input-color': 'text color',
|
|
98
|
+
'--atomix-input-padding-x': 'horizontal padding',
|
|
99
|
+
'--atomix-input-padding-y': 'vertical padding',
|
|
100
|
+
'--atomix-input-border-radius': 'border radius',
|
|
101
|
+
'--atomix-input-border-width': 'border width',
|
|
102
|
+
'--atomix-input-border-color': 'border color',
|
|
103
|
+
'--atomix-input-font-size': 'font size',
|
|
104
|
+
'--atomix-input-font-family': 'font family',
|
|
105
|
+
'--atomix-input-line-height': 'line height',
|
|
106
|
+
'--atomix-input-height': 'height',
|
|
107
|
+
'--atomix-input-placeholder-color': 'placeholder color',
|
|
108
|
+
|
|
109
|
+
// State properties
|
|
110
|
+
'--atomix-input-hover-border-color': 'hover border color',
|
|
111
|
+
'--atomix-input-focus-border-color': 'focus border color',
|
|
112
|
+
'--atomix-input-focus-ring-color': 'focus ring color',
|
|
113
|
+
'--atomix-input-focus-ring-width': 'focus ring width',
|
|
114
|
+
'--atomix-input-disabled-bg': 'disabled background',
|
|
115
|
+
'--atomix-input-disabled-opacity': 'disabled opacity',
|
|
116
|
+
'--atomix-input-invalid-border-color': 'invalid border color',
|
|
117
|
+
'--atomix-input-valid-border-color': 'valid border color',
|
|
118
|
+
} as const;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Modal CSS Variables
|
|
122
|
+
*/
|
|
123
|
+
export const MODAL_CSS_VARS = {
|
|
124
|
+
// Base properties
|
|
125
|
+
'--atomix-modal-bg': 'background color',
|
|
126
|
+
'--atomix-modal-color': 'text color',
|
|
127
|
+
'--atomix-modal-padding': 'padding',
|
|
128
|
+
'--atomix-modal-border-radius': 'border radius',
|
|
129
|
+
'--atomix-modal-box-shadow': 'box shadow',
|
|
130
|
+
'--atomix-modal-width': 'width',
|
|
131
|
+
'--atomix-modal-max-width': 'maximum width',
|
|
132
|
+
'--atomix-modal-max-height': 'maximum height',
|
|
133
|
+
|
|
134
|
+
// Backdrop properties
|
|
135
|
+
'--atomix-modal-backdrop-bg': 'backdrop background',
|
|
136
|
+
'--atomix-modal-backdrop-opacity': 'backdrop opacity',
|
|
137
|
+
'--atomix-modal-backdrop-blur': 'backdrop blur',
|
|
138
|
+
|
|
139
|
+
// Part properties - Header
|
|
140
|
+
'--atomix-modal-header-padding': 'header padding',
|
|
141
|
+
'--atomix-modal-header-border-bottom': 'header border bottom',
|
|
142
|
+
'--atomix-modal-title-font-size': 'title font size',
|
|
143
|
+
'--atomix-modal-title-font-weight': 'title font weight',
|
|
144
|
+
|
|
145
|
+
// Part properties - Body
|
|
146
|
+
'--atomix-modal-body-padding': 'body padding',
|
|
147
|
+
'--atomix-modal-body-font-size': 'body font size',
|
|
148
|
+
|
|
149
|
+
// Part properties - Footer
|
|
150
|
+
'--atomix-modal-footer-padding': 'footer padding',
|
|
151
|
+
'--atomix-modal-footer-border-top': 'footer border top',
|
|
152
|
+
'--atomix-modal-footer-gap': 'footer button gap',
|
|
153
|
+
|
|
154
|
+
// Part properties - Close button
|
|
155
|
+
'--atomix-modal-close-size': 'close button size',
|
|
156
|
+
'--atomix-modal-close-color': 'close button color',
|
|
157
|
+
'--atomix-modal-close-hover-color': 'close button hover color',
|
|
158
|
+
} as const;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Dropdown CSS Variables
|
|
162
|
+
*/
|
|
163
|
+
export const DROPDOWN_CSS_VARS = {
|
|
164
|
+
// Base properties
|
|
165
|
+
'--atomix-dropdown-bg': 'background color',
|
|
166
|
+
'--atomix-dropdown-color': 'text color',
|
|
167
|
+
'--atomix-dropdown-border-radius': 'border radius',
|
|
168
|
+
'--atomix-dropdown-border-width': 'border width',
|
|
169
|
+
'--atomix-dropdown-border-color': 'border color',
|
|
170
|
+
'--atomix-dropdown-box-shadow': 'box shadow',
|
|
171
|
+
'--atomix-dropdown-min-width': 'minimum width',
|
|
172
|
+
'--atomix-dropdown-max-height': 'maximum height',
|
|
173
|
+
'--atomix-dropdown-padding': 'padding',
|
|
174
|
+
|
|
175
|
+
// Part properties - Item
|
|
176
|
+
'--atomix-dropdown-item-padding': 'item padding',
|
|
177
|
+
'--atomix-dropdown-item-font-size': 'item font size',
|
|
178
|
+
'--atomix-dropdown-item-hover-bg': 'item hover background',
|
|
179
|
+
'--atomix-dropdown-item-hover-color': 'item hover color',
|
|
180
|
+
'--atomix-dropdown-item-active-bg': 'item active background',
|
|
181
|
+
'--atomix-dropdown-item-active-color': 'item active color',
|
|
182
|
+
'--atomix-dropdown-item-disabled-opacity': 'item disabled opacity',
|
|
183
|
+
|
|
184
|
+
// Part properties - Divider
|
|
185
|
+
'--atomix-dropdown-divider-color': 'divider color',
|
|
186
|
+
'--atomix-dropdown-divider-margin': 'divider margin',
|
|
187
|
+
|
|
188
|
+
// Part properties - Header
|
|
189
|
+
'--atomix-dropdown-header-padding': 'header padding',
|
|
190
|
+
'--atomix-dropdown-header-font-size': 'header font size',
|
|
191
|
+
'--atomix-dropdown-header-font-weight': 'header font weight',
|
|
192
|
+
'--atomix-dropdown-header-color': 'header color',
|
|
193
|
+
} as const;
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Badge CSS Variables
|
|
197
|
+
*/
|
|
198
|
+
export const BADGE_CSS_VARS = {
|
|
199
|
+
// Base properties
|
|
200
|
+
'--atomix-badge-bg': 'background color',
|
|
201
|
+
'--atomix-badge-color': 'text color',
|
|
202
|
+
'--atomix-badge-padding-x': 'horizontal padding',
|
|
203
|
+
'--atomix-badge-padding-y': 'vertical padding',
|
|
204
|
+
'--atomix-badge-border-radius': 'border radius',
|
|
205
|
+
'--atomix-badge-font-size': 'font size',
|
|
206
|
+
'--atomix-badge-font-weight': 'font weight',
|
|
207
|
+
'--atomix-badge-line-height': 'line height',
|
|
208
|
+
|
|
209
|
+
// Part properties
|
|
210
|
+
'--atomix-badge-icon-size': 'icon size',
|
|
211
|
+
'--atomix-badge-icon-gap': 'icon spacing',
|
|
212
|
+
} as const;
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Tabs CSS Variables
|
|
216
|
+
*/
|
|
217
|
+
export const TABS_CSS_VARS = {
|
|
218
|
+
// Base properties
|
|
219
|
+
'--atomix-tabs-bg': 'background color',
|
|
220
|
+
'--atomix-tabs-border-color': 'border color',
|
|
221
|
+
'--atomix-tabs-border-width': 'border width',
|
|
222
|
+
|
|
223
|
+
// Part properties - Nav
|
|
224
|
+
'--atomix-tabs-nav-gap': 'nav gap',
|
|
225
|
+
'--atomix-tabs-nav-padding': 'nav padding',
|
|
226
|
+
|
|
227
|
+
// Part properties - Tab button
|
|
228
|
+
'--atomix-tabs-btn-padding-x': 'button horizontal padding',
|
|
229
|
+
'--atomix-tabs-btn-padding-y': 'button vertical padding',
|
|
230
|
+
'--atomix-tabs-btn-color': 'button color',
|
|
231
|
+
'--atomix-tabs-btn-font-size': 'button font size',
|
|
232
|
+
'--atomix-tabs-btn-font-weight': 'button font weight',
|
|
233
|
+
'--atomix-tabs-btn-hover-color': 'button hover color',
|
|
234
|
+
'--atomix-tabs-btn-active-color': 'button active color',
|
|
235
|
+
'--atomix-tabs-btn-active-border-color': 'button active border color',
|
|
236
|
+
'--atomix-tabs-btn-active-border-width': 'button active border width',
|
|
237
|
+
|
|
238
|
+
// Part properties - Panel
|
|
239
|
+
'--atomix-tabs-panel-padding': 'panel padding',
|
|
240
|
+
'--atomix-tabs-panel-bg': 'panel background',
|
|
241
|
+
} as const;
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Progress CSS Variables
|
|
245
|
+
*/
|
|
246
|
+
export const PROGRESS_CSS_VARS = {
|
|
247
|
+
// Base properties
|
|
248
|
+
'--atomix-progress-bg': 'background color',
|
|
249
|
+
'--atomix-progress-height': 'height',
|
|
250
|
+
'--atomix-progress-border-radius': 'border radius',
|
|
251
|
+
|
|
252
|
+
// Part properties - Bar
|
|
253
|
+
'--atomix-progress-bar-bg': 'bar background',
|
|
254
|
+
'--atomix-progress-bar-transition': 'bar transition',
|
|
255
|
+
} as const;
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Tooltip CSS Variables
|
|
259
|
+
*/
|
|
260
|
+
export const TOOLTIP_CSS_VARS = {
|
|
261
|
+
// Base properties
|
|
262
|
+
'--atomix-tooltip-bg': 'background color',
|
|
263
|
+
'--atomix-tooltip-color': 'text color',
|
|
264
|
+
'--atomix-tooltip-padding-x': 'horizontal padding',
|
|
265
|
+
'--atomix-tooltip-padding-y': 'vertical padding',
|
|
266
|
+
'--atomix-tooltip-border-radius': 'border radius',
|
|
267
|
+
'--atomix-tooltip-font-size': 'font size',
|
|
268
|
+
'--atomix-tooltip-max-width': 'maximum width',
|
|
269
|
+
'--atomix-tooltip-box-shadow': 'box shadow',
|
|
270
|
+
'--atomix-tooltip-z-index': 'z-index',
|
|
271
|
+
|
|
272
|
+
// Arrow properties
|
|
273
|
+
'--atomix-tooltip-arrow-size': 'arrow size',
|
|
274
|
+
'--atomix-tooltip-arrow-color': 'arrow color',
|
|
275
|
+
} as const;
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Checkbox CSS Variables
|
|
279
|
+
*/
|
|
280
|
+
export const CHECKBOX_CSS_VARS = {
|
|
281
|
+
// Base properties
|
|
282
|
+
'--atomix-checkbox-size': 'checkbox size',
|
|
283
|
+
'--atomix-checkbox-bg': 'background color',
|
|
284
|
+
'--atomix-checkbox-border-color': 'border color',
|
|
285
|
+
'--atomix-checkbox-border-width': 'border width',
|
|
286
|
+
'--atomix-checkbox-border-radius': 'border radius',
|
|
287
|
+
'--atomix-checkbox-transition': 'transition',
|
|
288
|
+
|
|
289
|
+
// State properties
|
|
290
|
+
'--atomix-checkbox-checked-bg': 'checked background',
|
|
291
|
+
'--atomix-checkbox-checked-border-color': 'checked border color',
|
|
292
|
+
'--atomix-checkbox-hover-border-color': 'hover border color',
|
|
293
|
+
'--atomix-checkbox-focus-ring-color': 'focus ring color',
|
|
294
|
+
'--atomix-checkbox-focus-ring-width': 'focus ring width',
|
|
295
|
+
'--atomix-checkbox-disabled-opacity': 'disabled opacity',
|
|
296
|
+
'--atomix-checkbox-invalid-border-color': 'invalid border color',
|
|
297
|
+
|
|
298
|
+
// Part properties
|
|
299
|
+
'--atomix-checkbox-icon-size': 'icon size',
|
|
300
|
+
'--atomix-checkbox-icon-color': 'icon color',
|
|
301
|
+
'--atomix-checkbox-label-gap': 'label spacing',
|
|
302
|
+
'--atomix-checkbox-label-font-size': 'label font size',
|
|
303
|
+
'--atomix-checkbox-label-color': 'label color',
|
|
304
|
+
} as const;
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Radio CSS Variables
|
|
308
|
+
*/
|
|
309
|
+
export const RADIO_CSS_VARS = {
|
|
310
|
+
// Base properties
|
|
311
|
+
'--atomix-radio-size': 'radio size',
|
|
312
|
+
'--atomix-radio-bg': 'background color',
|
|
313
|
+
'--atomix-radio-border-color': 'border color',
|
|
314
|
+
'--atomix-radio-border-width': 'border width',
|
|
315
|
+
'--atomix-radio-transition': 'transition',
|
|
316
|
+
|
|
317
|
+
// State properties
|
|
318
|
+
'--atomix-radio-checked-bg': 'checked background',
|
|
319
|
+
'--atomix-radio-checked-border-color': 'checked border color',
|
|
320
|
+
'--atomix-radio-hover-border-color': 'hover border color',
|
|
321
|
+
'--atomix-radio-focus-ring-color': 'focus ring color',
|
|
322
|
+
'--atomix-radio-focus-ring-width': 'focus ring width',
|
|
323
|
+
'--atomix-radio-disabled-opacity': 'disabled opacity',
|
|
324
|
+
'--atomix-radio-invalid-border-color': 'invalid border color',
|
|
325
|
+
|
|
326
|
+
// Part properties
|
|
327
|
+
'--atomix-radio-dot-size': 'dot size',
|
|
328
|
+
'--atomix-radio-dot-color': 'dot color',
|
|
329
|
+
'--atomix-radio-label-gap': 'label spacing',
|
|
330
|
+
'--atomix-radio-label-font-size': 'label font size',
|
|
331
|
+
'--atomix-radio-label-color': 'label color',
|
|
332
|
+
} as const;
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* All component CSS variables
|
|
336
|
+
*/
|
|
337
|
+
export const COMPONENT_CSS_VARS = {
|
|
338
|
+
Button: BUTTON_CSS_VARS,
|
|
339
|
+
Card: CARD_CSS_VARS,
|
|
340
|
+
Input: INPUT_CSS_VARS,
|
|
341
|
+
Modal: MODAL_CSS_VARS,
|
|
342
|
+
Dropdown: DROPDOWN_CSS_VARS,
|
|
343
|
+
Badge: BADGE_CSS_VARS,
|
|
344
|
+
Tabs: TABS_CSS_VARS,
|
|
345
|
+
Progress: PROGRESS_CSS_VARS,
|
|
346
|
+
Tooltip: TOOLTIP_CSS_VARS,
|
|
347
|
+
Checkbox: CHECKBOX_CSS_VARS,
|
|
348
|
+
Radio: RADIO_CSS_VARS,
|
|
349
|
+
} as const;
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Type-safe CSS variable keys by component
|
|
353
|
+
*/
|
|
354
|
+
export type ButtonCSSVariable = keyof typeof BUTTON_CSS_VARS;
|
|
355
|
+
export type CardCSSVariable = keyof typeof CARD_CSS_VARS;
|
|
356
|
+
export type InputCSSVariable = keyof typeof INPUT_CSS_VARS;
|
|
357
|
+
export type ModalCSSVariable = keyof typeof MODAL_CSS_VARS;
|
|
358
|
+
export type DropdownCSSVariable = keyof typeof DROPDOWN_CSS_VARS;
|
|
359
|
+
export type BadgeCSSVariable = keyof typeof BADGE_CSS_VARS;
|
|
360
|
+
export type TabsCSSVariable = keyof typeof TABS_CSS_VARS;
|
|
361
|
+
export type ProgressCSSVariable = keyof typeof PROGRESS_CSS_VARS;
|
|
362
|
+
export type TooltipCSSVariable = keyof typeof TOOLTIP_CSS_VARS;
|
|
363
|
+
export type CheckboxCSSVariable = keyof typeof CHECKBOX_CSS_VARS;
|
|
364
|
+
export type RadioCSSVariable = keyof typeof RADIO_CSS_VARS;
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Component name to CSS variable type mapping
|
|
368
|
+
*/
|
|
369
|
+
export type ComponentCSSVariables = {
|
|
370
|
+
Button: ButtonCSSVariable;
|
|
371
|
+
Card: CardCSSVariable;
|
|
372
|
+
Input: InputCSSVariable;
|
|
373
|
+
Modal: ModalCSSVariable;
|
|
374
|
+
Dropdown: DropdownCSSVariable;
|
|
375
|
+
Badge: BadgeCSSVariable;
|
|
376
|
+
Tabs: TabsCSSVariable;
|
|
377
|
+
Progress: ProgressCSSVariable;
|
|
378
|
+
Tooltip: TooltipCSSVariable;
|
|
379
|
+
Checkbox: CheckboxCSSVariable;
|
|
380
|
+
Radio: RadioCSSVariable;
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Get CSS variables for a component
|
|
385
|
+
*/
|
|
386
|
+
export function getComponentCSSVars<T extends keyof typeof COMPONENT_CSS_VARS>(
|
|
387
|
+
component: T
|
|
388
|
+
): typeof COMPONENT_CSS_VARS[T] {
|
|
389
|
+
return COMPONENT_CSS_VARS[component];
|
|
390
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vitest-environment jsdom
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { renderHook } from '@testing-library/react';
|
|
6
|
+
import { describe, it, expect } from 'vitest';
|
|
7
|
+
import { useComponentCustomization } from '../useComponentCustomization';
|
|
8
|
+
|
|
9
|
+
describe('useComponentCustomization', () => {
|
|
10
|
+
describe('CSS Variables', () => {
|
|
11
|
+
it('should merge component cssVars', () => {
|
|
12
|
+
const { result } = renderHook(() =>
|
|
13
|
+
useComponentCustomization('Button', {
|
|
14
|
+
cssVars: {
|
|
15
|
+
'--atomix-button-bg': '#FF0000',
|
|
16
|
+
'--atomix-button-border-radius': '20px',
|
|
17
|
+
},
|
|
18
|
+
})
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
expect(result.current.cssVars).toEqual({
|
|
22
|
+
'--atomix-button-bg': '#FF0000',
|
|
23
|
+
'--atomix-button-border-radius': '20px',
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should handle empty cssVars', () => {
|
|
28
|
+
const { result } = renderHook(() =>
|
|
29
|
+
useComponentCustomization('Button', {})
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
expect(result.current.cssVars).toEqual({});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should preserve cssVar types', () => {
|
|
36
|
+
const { result } = renderHook(() =>
|
|
37
|
+
useComponentCustomization('Button', {
|
|
38
|
+
cssVars: {
|
|
39
|
+
'--atomix-button-padding-x': 16,
|
|
40
|
+
'--atomix-button-border-radius': '20px',
|
|
41
|
+
},
|
|
42
|
+
})
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
expect(result.current.cssVars).toEqual({
|
|
46
|
+
'--atomix-button-padding-x': 16,
|
|
47
|
+
'--atomix-button-border-radius': '20px',
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('Part Styling', () => {
|
|
53
|
+
it('should merge component parts', () => {
|
|
54
|
+
const { result } = renderHook(() =>
|
|
55
|
+
useComponentCustomization('Button', {
|
|
56
|
+
parts: {
|
|
57
|
+
root: {
|
|
58
|
+
className: 'custom-root',
|
|
59
|
+
style: { boxShadow: '0 2px 8px rgba(0,0,0,0.1)' },
|
|
60
|
+
},
|
|
61
|
+
icon: {
|
|
62
|
+
style: { fontSize: '18px' },
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
})
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
expect(result.current.parts).toEqual({
|
|
69
|
+
root: {
|
|
70
|
+
className: 'custom-root',
|
|
71
|
+
style: { boxShadow: '0 2px 8px rgba(0,0,0,0.1)' },
|
|
72
|
+
},
|
|
73
|
+
icon: {
|
|
74
|
+
style: { fontSize: '18px' },
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should handle empty parts', () => {
|
|
80
|
+
const { result } = renderHook(() =>
|
|
81
|
+
useComponentCustomization('Button', {})
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
expect(result.current.parts).toEqual({});
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe('ClassName and Style', () => {
|
|
89
|
+
it('should merge className', () => {
|
|
90
|
+
const { result } = renderHook(() =>
|
|
91
|
+
useComponentCustomization('Button', {
|
|
92
|
+
className: 'custom-button',
|
|
93
|
+
})
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
expect(result.current.className).toBe('custom-button');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('should merge style', () => {
|
|
100
|
+
const { result } = renderHook(() =>
|
|
101
|
+
useComponentCustomization('Button', {
|
|
102
|
+
style: { marginTop: '10px' },
|
|
103
|
+
})
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
expect(result.current.style).toEqual({ marginTop: '10px' });
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('should handle both className and style', () => {
|
|
110
|
+
const { result } = renderHook(() =>
|
|
111
|
+
useComponentCustomization('Button', {
|
|
112
|
+
className: 'custom-button',
|
|
113
|
+
style: { marginTop: '10px' },
|
|
114
|
+
})
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
expect(result.current.className).toBe('custom-button');
|
|
118
|
+
expect(result.current.style).toEqual({ marginTop: '10px' });
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
describe('Combined Customization', () => {
|
|
123
|
+
it('should merge all customization options', () => {
|
|
124
|
+
const { result } = renderHook(() =>
|
|
125
|
+
useComponentCustomization('Button', {
|
|
126
|
+
cssVars: {
|
|
127
|
+
'--atomix-button-bg': '#FF0000',
|
|
128
|
+
},
|
|
129
|
+
parts: {
|
|
130
|
+
root: {
|
|
131
|
+
className: 'custom-root',
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
className: 'custom-button',
|
|
135
|
+
style: { marginTop: '10px' },
|
|
136
|
+
})
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
expect(result.current.cssVars).toEqual({
|
|
140
|
+
'--atomix-button-bg': '#FF0000',
|
|
141
|
+
});
|
|
142
|
+
expect(result.current.parts).toEqual({
|
|
143
|
+
root: {
|
|
144
|
+
className: 'custom-root',
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
expect(result.current.className).toBe('custom-button');
|
|
148
|
+
expect(result.current.style).toEqual({ marginTop: '10px' });
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hooks Exports
|
|
3
|
+
*
|
|
4
|
+
* Custom React hooks for component customization
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export {
|
|
8
|
+
useComponentCustomization,
|
|
9
|
+
useComponentDefaultProps,
|
|
10
|
+
useMergedProps,
|
|
11
|
+
mergeClassNames,
|
|
12
|
+
applyCSSVarsToStyle,
|
|
13
|
+
} from './useComponentCustomization';
|
|
14
|
+
|
|
15
|
+
export type {
|
|
16
|
+
ComponentName,
|
|
17
|
+
CustomizableComponentProps,
|
|
18
|
+
ComponentCustomization,
|
|
19
|
+
} from './useComponentCustomization';
|