@shohojdhara/atomix 0.3.10 → 0.3.12
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/CHANGELOG.md +9 -1
- package/dist/atomix.css +9 -6
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +9 -6
- package/dist/atomix.min.css.map +1 -1
- package/dist/charts.js +82 -60
- package/dist/charts.js.map +1 -1
- package/dist/core.js +82 -60
- package/dist/core.js.map +1 -1
- package/dist/forms.js +82 -60
- package/dist/forms.js.map +1 -1
- package/dist/heavy.js +82 -60
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +11 -107
- package/dist/index.esm.js +165 -407
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +169 -412
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/theme.d.ts +1 -32
- package/dist/theme.js +12 -207
- package/dist/theme.js.map +1 -1
- package/package.json +1 -1
- package/src/components/AtomixGlass/AtomixGlass.tsx +124 -127
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +28 -32
- package/src/components/AtomixGlass/GlassFilter.tsx +15 -4
- package/src/components/EdgePanel/EdgePanel.stories.tsx +2 -7
- package/src/components/EdgePanel/EdgePanel.tsx +0 -10
- package/src/components/Form/Radio.stories.tsx +235 -103
- package/src/components/Navigation/Nav/NavDropdown.tsx +8 -4
- package/src/components/Navigation/SideMenu/SideMenu.tsx +2 -22
- package/src/components/Navigation/SideMenu/SideMenuItem.tsx +11 -15
- package/src/lib/config/index.ts +5 -5
- package/src/lib/theme/config/index.ts +1 -1
- package/src/lib/theme/core/createTheme.ts +11 -40
- package/src/lib/theme/generators/index.ts +1 -4
- package/src/lib/theme/index.ts +4 -16
- package/src/lib/theme/runtime/ThemeProvider.tsx +1 -16
- package/src/lib/types/components.ts +2 -26
- package/src/styles/06-components/_components.edge-panel.scss +4 -4
- package/src/styles/06-components/_components.nav.scss +3 -0
- package/src/lib/config/loader.ts +0 -147
- package/src/lib/theme/config/__tests__/configLoader.test.ts +0 -207
- package/src/lib/theme/config/configLoader.ts +0 -113
- package/src/lib/theme/config/loader.ts +0 -293
- package/src/lib/theme/generators/cssFile.ts +0 -79
|
@@ -52,6 +52,7 @@ export const Basic: Story = {
|
|
|
52
52
|
label: 'Option 1',
|
|
53
53
|
name: 'option',
|
|
54
54
|
value: 'option1',
|
|
55
|
+
onChange: () => {},
|
|
55
56
|
},
|
|
56
57
|
};
|
|
57
58
|
|
|
@@ -62,38 +63,98 @@ export const Checked: Story = {
|
|
|
62
63
|
name: 'option',
|
|
63
64
|
value: 'option1',
|
|
64
65
|
checked: true,
|
|
66
|
+
onChange: () => {},
|
|
65
67
|
},
|
|
66
68
|
};
|
|
67
69
|
|
|
68
70
|
// Radio button group
|
|
69
71
|
export const RadioGroup: Story = {
|
|
70
|
-
render: (args: any) =>
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
<
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
render: (args: any) => {
|
|
73
|
+
const [selectedValue, setSelectedValue] = React.useState('option1');
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<div className="u-d-flex u-flex-column u-gap-2">
|
|
77
|
+
<Radio
|
|
78
|
+
label="Option 1"
|
|
79
|
+
name="radioGroup"
|
|
80
|
+
value="option1"
|
|
81
|
+
checked={selectedValue === 'option1'}
|
|
82
|
+
onChange={() => setSelectedValue('option1')}
|
|
83
|
+
/>
|
|
84
|
+
<Radio
|
|
85
|
+
label="Option 2"
|
|
86
|
+
name="radioGroup"
|
|
87
|
+
value="option2"
|
|
88
|
+
checked={selectedValue === 'option2'}
|
|
89
|
+
onChange={() => setSelectedValue('option2')}
|
|
90
|
+
/>
|
|
91
|
+
<Radio
|
|
92
|
+
label="Option 3"
|
|
93
|
+
name="radioGroup"
|
|
94
|
+
value="option3"
|
|
95
|
+
checked={selectedValue === 'option3'}
|
|
96
|
+
onChange={() => setSelectedValue('option3')}
|
|
97
|
+
/>
|
|
98
|
+
</div>
|
|
99
|
+
);
|
|
100
|
+
},
|
|
77
101
|
};
|
|
78
102
|
|
|
79
103
|
// Radio button states
|
|
80
104
|
export const States: Story = {
|
|
81
|
-
render: (args: any) =>
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
<
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
105
|
+
render: (args: any) => {
|
|
106
|
+
const [selectedValue, setSelectedValue] = React.useState('default');
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<div className="u-d-flex u-flex-column u-gap-2">
|
|
110
|
+
<Radio
|
|
111
|
+
label="Default radio"
|
|
112
|
+
name="states"
|
|
113
|
+
value="default"
|
|
114
|
+
checked={selectedValue === 'default'}
|
|
115
|
+
onChange={() => setSelectedValue('default')}
|
|
116
|
+
/>
|
|
117
|
+
<Radio
|
|
118
|
+
label="Checked radio"
|
|
119
|
+
name="states"
|
|
120
|
+
value="checked"
|
|
121
|
+
checked={selectedValue === 'checked'}
|
|
122
|
+
onChange={() => setSelectedValue('checked')}
|
|
123
|
+
/>
|
|
124
|
+
<Radio
|
|
125
|
+
label="Disabled radio"
|
|
126
|
+
name="states"
|
|
127
|
+
value="disabled"
|
|
128
|
+
disabled
|
|
129
|
+
onChange={() => {}}
|
|
130
|
+
/>
|
|
131
|
+
<Radio
|
|
132
|
+
label="Disabled and checked radio"
|
|
133
|
+
name="states"
|
|
134
|
+
value="disabledChecked"
|
|
135
|
+
disabled
|
|
136
|
+
checked
|
|
137
|
+
onChange={() => {}}
|
|
138
|
+
/>
|
|
139
|
+
<Radio
|
|
140
|
+
label="Valid radio"
|
|
141
|
+
name="states"
|
|
142
|
+
value="valid"
|
|
143
|
+
valid
|
|
144
|
+
checked={selectedValue === 'valid'}
|
|
145
|
+
onChange={() => setSelectedValue('valid')}
|
|
146
|
+
/>
|
|
147
|
+
<Radio
|
|
148
|
+
label="Invalid radio"
|
|
149
|
+
name="states"
|
|
150
|
+
value="invalid"
|
|
151
|
+
invalid
|
|
152
|
+
checked={selectedValue === 'invalid'}
|
|
153
|
+
onChange={() => setSelectedValue('invalid')}
|
|
154
|
+
/>
|
|
155
|
+
</div>
|
|
156
|
+
);
|
|
157
|
+
},
|
|
97
158
|
};
|
|
98
159
|
|
|
99
160
|
// Without label
|
|
@@ -102,6 +163,7 @@ export const WithoutLabel: Story = {
|
|
|
102
163
|
name: 'noLabel',
|
|
103
164
|
value: 'noLabel',
|
|
104
165
|
ariaLabel: 'Radio button without visible label',
|
|
166
|
+
onChange: () => {},
|
|
105
167
|
},
|
|
106
168
|
};
|
|
107
169
|
|
|
@@ -112,6 +174,7 @@ export const Glass: Story = {
|
|
|
112
174
|
name: 'glass',
|
|
113
175
|
value: 'glass',
|
|
114
176
|
glass: true,
|
|
177
|
+
onChange: () => {},
|
|
115
178
|
},
|
|
116
179
|
render: (args: any) => (
|
|
117
180
|
<div
|
|
@@ -143,6 +206,7 @@ export const GlassCustom: Story = {
|
|
|
143
206
|
aberrationIntensity: 0.8,
|
|
144
207
|
cornerRadius: 12,
|
|
145
208
|
} as any,
|
|
209
|
+
onChange: () => {},
|
|
146
210
|
},
|
|
147
211
|
render: (args: any) => (
|
|
148
212
|
<div
|
|
@@ -166,91 +230,159 @@ export const GlassCustom: Story = {
|
|
|
166
230
|
|
|
167
231
|
// Glass radio group
|
|
168
232
|
export const GlassGroup: Story = {
|
|
169
|
-
render: () =>
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
<
|
|
233
|
+
render: () => {
|
|
234
|
+
const [selectedValue, setSelectedValue] = React.useState('option1');
|
|
235
|
+
|
|
236
|
+
return (
|
|
237
|
+
<div
|
|
238
|
+
style={{
|
|
239
|
+
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
240
|
+
padding: '2rem',
|
|
241
|
+
borderRadius: '12px',
|
|
242
|
+
minHeight: '300px',
|
|
243
|
+
display: 'flex',
|
|
244
|
+
alignItems: 'center',
|
|
245
|
+
justifyContent: 'center',
|
|
246
|
+
}}
|
|
247
|
+
>
|
|
248
|
+
<div>
|
|
249
|
+
<h3
|
|
250
|
+
style={{
|
|
251
|
+
color: 'white',
|
|
252
|
+
marginBottom: '2rem',
|
|
253
|
+
textAlign: 'center',
|
|
254
|
+
textShadow: '0 2px 4px rgba(0,0,0,0.5)',
|
|
255
|
+
}}
|
|
256
|
+
>
|
|
257
|
+
Glass Radio Group
|
|
258
|
+
</h3>
|
|
259
|
+
<div className="u-d-flex u-flex-column u-gap-2">
|
|
260
|
+
<Radio
|
|
261
|
+
label="Glass Option 1"
|
|
262
|
+
name="glassGroup"
|
|
263
|
+
value="option1"
|
|
264
|
+
checked={selectedValue === 'option1'}
|
|
265
|
+
onChange={() => setSelectedValue('option1')}
|
|
266
|
+
glass
|
|
267
|
+
/>
|
|
268
|
+
<Radio
|
|
269
|
+
label="Glass Option 2"
|
|
270
|
+
name="glassGroup"
|
|
271
|
+
value="option2"
|
|
272
|
+
checked={selectedValue === 'option2'}
|
|
273
|
+
onChange={() => setSelectedValue('option2')}
|
|
274
|
+
glass
|
|
275
|
+
/>
|
|
276
|
+
<Radio
|
|
277
|
+
label="Glass Option 3"
|
|
278
|
+
name="glassGroup"
|
|
279
|
+
value="option3"
|
|
280
|
+
checked={selectedValue === 'option3'}
|
|
281
|
+
onChange={() => setSelectedValue('option3')}
|
|
282
|
+
glass
|
|
283
|
+
/>
|
|
284
|
+
</div>
|
|
196
285
|
</div>
|
|
197
286
|
</div>
|
|
198
|
-
|
|
199
|
-
|
|
287
|
+
);
|
|
288
|
+
},
|
|
200
289
|
};
|
|
201
290
|
|
|
202
291
|
// Glass states
|
|
203
292
|
export const GlassStates: Story = {
|
|
204
|
-
render: () =>
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
<
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
293
|
+
render: () => {
|
|
294
|
+
const [selectedValue, setSelectedValue] = React.useState('default');
|
|
295
|
+
|
|
296
|
+
return (
|
|
297
|
+
<div
|
|
298
|
+
style={{
|
|
299
|
+
background: 'linear-gradient(45deg, #ff6b6b, #4ecdc4, #45b7d1, #96ceb4, #feca57)',
|
|
300
|
+
backgroundSize: '400% 400%',
|
|
301
|
+
animation: 'gradient 15s ease infinite',
|
|
302
|
+
padding: '2rem',
|
|
303
|
+
borderRadius: '12px',
|
|
304
|
+
minHeight: '500px',
|
|
305
|
+
display: 'flex',
|
|
306
|
+
alignItems: 'center',
|
|
307
|
+
justifyContent: 'center',
|
|
308
|
+
}}
|
|
309
|
+
>
|
|
310
|
+
<style>
|
|
311
|
+
{`
|
|
312
|
+
@keyframes gradient {
|
|
313
|
+
0% { background-position: 0% 50%; }
|
|
314
|
+
50% { background-position: 100% 50%; }
|
|
315
|
+
100% { background-position: 0% 50%; }
|
|
316
|
+
}
|
|
317
|
+
`}
|
|
318
|
+
</style>
|
|
319
|
+
<div>
|
|
320
|
+
<h3
|
|
321
|
+
style={{
|
|
322
|
+
color: 'white',
|
|
323
|
+
marginBottom: '2rem',
|
|
324
|
+
textAlign: 'center',
|
|
325
|
+
textShadow: '0 2px 4px rgba(0,0,0,0.5)',
|
|
326
|
+
}}
|
|
327
|
+
>
|
|
328
|
+
Glass Radio States
|
|
329
|
+
</h3>
|
|
330
|
+
<div className="u-d-flex u-flex-column u-gap-2">
|
|
331
|
+
<Radio
|
|
332
|
+
label="Glass Default"
|
|
333
|
+
name="glassStates"
|
|
334
|
+
value="default"
|
|
335
|
+
checked={selectedValue === 'default'}
|
|
336
|
+
onChange={() => setSelectedValue('default')}
|
|
337
|
+
glass
|
|
338
|
+
/>
|
|
339
|
+
<Radio
|
|
340
|
+
label="Glass Checked"
|
|
341
|
+
name="glassStates"
|
|
342
|
+
value="checked"
|
|
343
|
+
checked={selectedValue === 'checked'}
|
|
344
|
+
onChange={() => setSelectedValue('checked')}
|
|
345
|
+
glass
|
|
346
|
+
/>
|
|
347
|
+
<Radio
|
|
348
|
+
label="Glass Disabled"
|
|
349
|
+
name="glassStates"
|
|
350
|
+
value="disabled"
|
|
351
|
+
disabled
|
|
352
|
+
checked={selectedValue === 'disabled'}
|
|
353
|
+
onChange={() => setSelectedValue('disabled')}
|
|
354
|
+
glass
|
|
355
|
+
/>
|
|
356
|
+
<Radio
|
|
357
|
+
label="Glass Disabled and Checked"
|
|
358
|
+
name="glassStates"
|
|
359
|
+
value="disabledChecked"
|
|
360
|
+
disabled
|
|
361
|
+
checked={selectedValue === 'disabledChecked'}
|
|
362
|
+
onChange={() => setSelectedValue('disabledChecked')}
|
|
363
|
+
glass
|
|
364
|
+
/>
|
|
365
|
+
<Radio
|
|
366
|
+
label="Glass Valid"
|
|
367
|
+
name="glassStates"
|
|
368
|
+
value="valid"
|
|
369
|
+
valid
|
|
370
|
+
checked={selectedValue === 'valid'}
|
|
371
|
+
onChange={() => setSelectedValue('valid')}
|
|
372
|
+
glass
|
|
373
|
+
/>
|
|
374
|
+
<Radio
|
|
375
|
+
label="Glass Invalid"
|
|
376
|
+
name="glassStates"
|
|
377
|
+
value="invalid"
|
|
378
|
+
invalid
|
|
379
|
+
checked={selectedValue === 'invalid'}
|
|
380
|
+
onChange={() => setSelectedValue('invalid')}
|
|
381
|
+
glass
|
|
382
|
+
/>
|
|
383
|
+
</div>
|
|
252
384
|
</div>
|
|
253
385
|
</div>
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
};
|
|
386
|
+
);
|
|
387
|
+
},
|
|
388
|
+
};
|
|
@@ -23,7 +23,7 @@ export const NavDropdown: React.FC<NavDropdownProps> = forwardRef<HTMLLIElement,
|
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
const [isActive, setIsActive] = useState(false);
|
|
26
|
-
const dropdownRef = useRef<
|
|
26
|
+
const dropdownRef = useRef<HTMLElement>(null);
|
|
27
27
|
|
|
28
28
|
const dropdownMenuClass = generateDropdownMenuClass({
|
|
29
29
|
alignment,
|
|
@@ -82,11 +82,15 @@ export const NavDropdown: React.FC<NavDropdownProps> = forwardRef<HTMLLIElement,
|
|
|
82
82
|
</>
|
|
83
83
|
);
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
const MenuTag = megaMenu ? 'div' : 'ul';
|
|
86
86
|
const menuContent = (
|
|
87
|
-
<
|
|
87
|
+
<MenuTag
|
|
88
|
+
className={dropdownMenuClass}
|
|
89
|
+
ref={dropdownRef as any}
|
|
90
|
+
aria-hidden={!isActive}
|
|
91
|
+
>
|
|
88
92
|
{children}
|
|
89
|
-
</
|
|
93
|
+
</MenuTag>
|
|
90
94
|
);
|
|
91
95
|
|
|
92
96
|
return (
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState, useEffect, useRef, forwardRef
|
|
1
|
+
import React, { useState, useEffect, useRef, forwardRef } from 'react';
|
|
2
2
|
import { SideMenuProps } from '../../../lib/types/components';
|
|
3
3
|
import { useSideMenu } from '../../../lib/composables/useSideMenu';
|
|
4
4
|
import { Icon } from '../../Icon';
|
|
@@ -7,25 +7,7 @@ import useForkRef from '../../../lib/utils/useForkRef';
|
|
|
7
7
|
import SideMenuList from './SideMenuList';
|
|
8
8
|
import SideMenuItem from './SideMenuItem';
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
const SideMenuContext = createContext<{
|
|
12
|
-
LinkComponent?: React.ComponentType<{
|
|
13
|
-
href?: string;
|
|
14
|
-
to?: string;
|
|
15
|
-
children: React.ReactNode;
|
|
16
|
-
className?: string;
|
|
17
|
-
onClick?: (event: React.MouseEvent) => void;
|
|
18
|
-
target?: string;
|
|
19
|
-
rel?: string;
|
|
20
|
-
'aria-disabled'?: boolean;
|
|
21
|
-
'aria-current'?: string;
|
|
22
|
-
tabIndex?: number;
|
|
23
|
-
ref?: React.Ref<HTMLAnchorElement>;
|
|
24
|
-
}>;
|
|
25
|
-
}>({});
|
|
26
|
-
|
|
27
|
-
// Hook to use SideMenu context
|
|
28
|
-
export const useSideMenuContext = () => useContext(SideMenuContext);
|
|
10
|
+
|
|
29
11
|
|
|
30
12
|
/**
|
|
31
13
|
* SideMenu component provides a collapsible navigation menu with title and menu items.
|
|
@@ -235,7 +217,6 @@ export const SideMenu = forwardRef<HTMLDivElement, SideMenuProps>(
|
|
|
235
217
|
id={id ? `${id}-content` : undefined}
|
|
236
218
|
aria-hidden={shouldShowToggler ? !isOpenState : false}
|
|
237
219
|
>
|
|
238
|
-
<SideMenuContext.Provider value={{ LinkComponent }}>
|
|
239
220
|
<div ref={innerRef} className="c-side-menu__inner">
|
|
240
221
|
{children}
|
|
241
222
|
{menuItems?.map((item, index) => {
|
|
@@ -321,7 +302,6 @@ export const SideMenu = forwardRef<HTMLDivElement, SideMenuProps>(
|
|
|
321
302
|
);
|
|
322
303
|
})}
|
|
323
304
|
</div>
|
|
324
|
-
</SideMenuContext.Provider>
|
|
325
305
|
</div>
|
|
326
306
|
</>
|
|
327
307
|
);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React, { forwardRef } from 'react';
|
|
2
2
|
import { SideMenuItemProps } from '../../../lib/types/components';
|
|
3
3
|
import { useSideMenuItem } from '../../../lib/composables/useSideMenu';
|
|
4
|
-
import { useSideMenuContext } from './SideMenu';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* SideMenuItem component represents a single navigation item in a side menu.
|
|
@@ -17,7 +16,13 @@ import { useSideMenuContext } from './SideMenu';
|
|
|
17
16
|
* Click me
|
|
18
17
|
* </SideMenuItem>
|
|
19
18
|
*
|
|
20
|
-
* // With icon
|
|
19
|
+
* // With icon and custom link component
|
|
20
|
+
* import Link from 'next/link';
|
|
21
|
+
* <SideMenuItem href="/settings" icon={<Icon name="Settings" />} LinkComponent={Link}>
|
|
22
|
+
* Settings
|
|
23
|
+
* </SideMenuItem>
|
|
24
|
+
*
|
|
25
|
+
* // With icon and custom link component
|
|
21
26
|
* <SideMenuItem href="/settings" icon={<Icon name="Settings" />}>
|
|
22
27
|
* Settings
|
|
23
28
|
* </SideMenuItem>
|
|
@@ -44,9 +49,6 @@ export const SideMenuItem = forwardRef<HTMLAnchorElement | HTMLButtonElement, Si
|
|
|
44
49
|
},
|
|
45
50
|
ref
|
|
46
51
|
) => {
|
|
47
|
-
const { LinkComponent: LinkComponentFromContext } = useSideMenuContext();
|
|
48
|
-
// Use LinkComponent from props first, then fall back to context
|
|
49
|
-
const LinkComponent = LinkComponentProp ?? LinkComponentFromContext;
|
|
50
52
|
|
|
51
53
|
const { generateSideMenuItemClass, handleClick } = useSideMenuItem({
|
|
52
54
|
active,
|
|
@@ -58,12 +60,8 @@ export const SideMenuItem = forwardRef<HTMLAnchorElement | HTMLButtonElement, Si
|
|
|
58
60
|
|
|
59
61
|
// Render as link if href is provided
|
|
60
62
|
if (href) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const Component = LinkComponent;
|
|
64
|
-
|
|
65
|
-
// Build link props - support both 'href' (Next.js) and 'to' (React Router)
|
|
66
|
-
// The Link component will use whichever prop it needs
|
|
63
|
+
if (LinkComponentProp) {
|
|
64
|
+
const LinkComp = LinkComponentProp as React.ComponentType<any>;
|
|
67
65
|
const linkProps: {
|
|
68
66
|
ref?: React.Ref<HTMLAnchorElement>;
|
|
69
67
|
className?: string;
|
|
@@ -88,16 +86,14 @@ export const SideMenuItem = forwardRef<HTMLAnchorElement | HTMLButtonElement, Si
|
|
|
88
86
|
target: target,
|
|
89
87
|
rel: rel,
|
|
90
88
|
tabIndex: disabled ? -1 : 0,
|
|
91
|
-
// Support both Next.js (href) and React Router (to) Link components
|
|
92
|
-
// Pass both props - the Link component will use whichever it needs
|
|
93
89
|
...(disabled ? {} : { href, to: href }),
|
|
94
90
|
};
|
|
95
91
|
|
|
96
92
|
return (
|
|
97
|
-
|
|
93
|
+
<LinkComp {...linkProps}>
|
|
98
94
|
{icon && <span className="c-side-menu__link-icon">{icon}</span>}
|
|
99
95
|
<span className="c-side-menu__link-text">{children}</span>
|
|
100
|
-
</
|
|
96
|
+
</LinkComp>
|
|
101
97
|
);
|
|
102
98
|
}
|
|
103
99
|
|
package/src/lib/config/index.ts
CHANGED
|
@@ -192,7 +192,7 @@ export interface AtomixConfig {
|
|
|
192
192
|
* Example: prefix: 'myapp' → --myapp-primary instead of --atomix-primary
|
|
193
193
|
*/
|
|
194
194
|
prefix?: string;
|
|
195
|
-
|
|
195
|
+
|
|
196
196
|
/**
|
|
197
197
|
* Theme customization (Tailwind-like)
|
|
198
198
|
*
|
|
@@ -207,7 +207,7 @@ export interface AtomixConfig {
|
|
|
207
207
|
* Your values will override or extend the base tokens.
|
|
208
208
|
*/
|
|
209
209
|
extend?: ThemeTokens;
|
|
210
|
-
|
|
210
|
+
|
|
211
211
|
/**
|
|
212
212
|
* Override the default tokens entirely (advanced)
|
|
213
213
|
*
|
|
@@ -215,7 +215,7 @@ export interface AtomixConfig {
|
|
|
215
215
|
* Most users should use `extend` instead.
|
|
216
216
|
*/
|
|
217
217
|
tokens?: ThemeTokens;
|
|
218
|
-
|
|
218
|
+
|
|
219
219
|
/**
|
|
220
220
|
* Register custom themes (optional)
|
|
221
221
|
*
|
|
@@ -223,7 +223,7 @@ export interface AtomixConfig {
|
|
|
223
223
|
*/
|
|
224
224
|
themes?: Record<string, ThemeDefinition>;
|
|
225
225
|
};
|
|
226
|
-
|
|
226
|
+
|
|
227
227
|
// Internal configurations (for library development only)
|
|
228
228
|
// These are not needed for external developers
|
|
229
229
|
/** @internal Build configuration (internal use only) */
|
|
@@ -270,6 +270,6 @@ export function defineConfig(config: AtomixConfig): AtomixConfig {
|
|
|
270
270
|
}
|
|
271
271
|
|
|
272
272
|
// Export loader functions
|
|
273
|
-
|
|
273
|
+
// Loader functions removed to prevent bundling Node.js modules in browser
|
|
274
274
|
|
|
275
275
|
export default AtomixConfig;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Exports for theme configuration loading and validation
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
// Loader exports removed
|
|
8
8
|
export { validateConfig } from './validator';
|
|
9
9
|
export type {
|
|
10
10
|
ConfigLoaderOptions,
|
|
@@ -66,47 +66,18 @@ export function createTheme(
|
|
|
66
66
|
|
|
67
67
|
// Determine tokens based on input
|
|
68
68
|
let tokens: Partial<DesignTokens>;
|
|
69
|
-
|
|
69
|
+
|
|
70
70
|
if (!input) {
|
|
71
|
-
//
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Load from config when no input provided
|
|
81
|
-
let loadThemeFromConfigSync: any;
|
|
82
|
-
let loadAtomixConfig: any;
|
|
83
|
-
|
|
84
|
-
try {
|
|
85
|
-
const configLoaderModule = require('../config/configLoader');
|
|
86
|
-
const loaderModule = require('../../config/loader');
|
|
87
|
-
|
|
88
|
-
loadThemeFromConfigSync = configLoaderModule.loadThemeFromConfigSync;
|
|
89
|
-
loadAtomixConfig = loaderModule.loadAtomixConfig;
|
|
90
|
-
|
|
91
|
-
tokens = loadThemeFromConfigSync();
|
|
92
|
-
|
|
93
|
-
// Get prefix from config if needed
|
|
94
|
-
if (!options?.prefix) {
|
|
95
|
-
try {
|
|
96
|
-
const config = loadAtomixConfig({ configPath: 'atomix.config.ts', required: false });
|
|
97
|
-
options = { ...options, prefix: config?.prefix || 'atomix' };
|
|
98
|
-
} catch (error) {
|
|
99
|
-
// If config loading fails, use default prefix
|
|
100
|
-
options = { ...options, prefix: 'atomix' };
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
} catch (error) {
|
|
104
|
-
throw new ThemeError(
|
|
105
|
-
'No input provided and config loading is not available in this environment. Please provide tokens explicitly.',
|
|
106
|
-
ThemeErrorCode.CONFIG_LOAD_FAILED,
|
|
107
|
-
{ error: error instanceof Error ? error.message : String(error) }
|
|
108
|
-
);
|
|
71
|
+
// Auto-loading config from file system is removed for browser compatibility.
|
|
72
|
+
// If no input is provided, we return an empty theme (using defaults only) or user must provide tokens.
|
|
73
|
+
// This allows createTheme to be isomorphic.
|
|
74
|
+
|
|
75
|
+
// Warn in development if no input provided
|
|
76
|
+
if (process.env.NODE_ENV !== 'production' && typeof window !== 'undefined') {
|
|
77
|
+
console.warn('Atomix: createTheme() called without tokens. Using default tokens only.');
|
|
109
78
|
}
|
|
79
|
+
|
|
80
|
+
tokens = {};
|
|
110
81
|
} else {
|
|
111
82
|
// Validate input tokens structure
|
|
112
83
|
if (typeof input !== 'object' || input === null || Array.isArray(input)) {
|
|
@@ -116,7 +87,7 @@ export function createTheme(
|
|
|
116
87
|
{ inputType: typeof input }
|
|
117
88
|
);
|
|
118
89
|
}
|
|
119
|
-
|
|
90
|
+
|
|
120
91
|
// Use DesignTokens directly
|
|
121
92
|
tokens = input;
|
|
122
93
|
}
|