@shohojdhara/atomix 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/dist/atomix.css +95 -69
  2. package/dist/atomix.css.map +1 -1
  3. package/dist/atomix.min.css +1 -1
  4. package/dist/atomix.min.css.map +1 -1
  5. package/dist/charts.d.ts +1 -0
  6. package/dist/charts.js +231 -332
  7. package/dist/charts.js.map +1 -1
  8. package/dist/core.d.ts +1 -0
  9. package/dist/core.js +232 -333
  10. package/dist/core.js.map +1 -1
  11. package/dist/forms.d.ts +1 -0
  12. package/dist/forms.js +231 -332
  13. package/dist/forms.js.map +1 -1
  14. package/dist/heavy.d.ts +11 -2
  15. package/dist/heavy.js +233 -334
  16. package/dist/heavy.js.map +1 -1
  17. package/dist/index.d.ts +13 -2
  18. package/dist/index.esm.js +228 -327
  19. package/dist/index.esm.js.map +1 -1
  20. package/dist/index.js +227 -326
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.min.js +1 -1
  23. package/dist/index.min.js.map +1 -1
  24. package/package.json +11 -1
  25. package/src/components/AtomixGlass/AtomixGlass.tsx +188 -128
  26. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +62 -90
  27. package/src/components/AtomixGlass/PerformanceDashboard.tsx +153 -201
  28. package/src/components/AtomixGlass/glass-utils.ts +50 -0
  29. package/src/components/AtomixGlass/stories/AnimationFeatures.stories.tsx +52 -46
  30. package/src/components/AtomixGlass/stories/Examples.stories.tsx +573 -236
  31. package/src/components/AtomixGlass/stories/Playground.stories.tsx +88 -41
  32. package/src/components/AtomixGlass/stories/argTypes.ts +19 -19
  33. package/src/components/AtomixGlass/stories/shared-components.tsx +7 -12
  34. package/src/components/AtomixGlass/stories/types.ts +3 -3
  35. package/src/lib/composables/useAtomixGlass.ts +108 -71
  36. package/src/lib/composables/useAtomixGlassStyles.ts +0 -2
  37. package/src/lib/constants/components.ts +1 -0
  38. package/src/lib/types/components.ts +1 -0
  39. package/src/lib/utils/displacement-generator.ts +1 -1
  40. package/src/styles/06-components/_components.atomix-glass.scss +158 -97
  41. package/scripts/cli/__tests__/README.md +0 -81
  42. package/scripts/cli/__tests__/basic.test.js +0 -116
  43. package/scripts/cli/__tests__/clean.test.js +0 -278
  44. package/scripts/cli/__tests__/component-generator.test.js +0 -332
  45. package/scripts/cli/__tests__/component-validator.test.js +0 -433
  46. package/scripts/cli/__tests__/generator.test.js +0 -613
  47. package/scripts/cli/__tests__/glass-motion.test.js +0 -256
  48. package/scripts/cli/__tests__/integration.test.js +0 -938
  49. package/scripts/cli/__tests__/migrate.test.js +0 -74
  50. package/scripts/cli/__tests__/security.test.js +0 -206
  51. package/scripts/cli/__tests__/test-setup.js +0 -135
  52. package/scripts/cli/__tests__/theme-bridge.test.js +0 -507
  53. package/scripts/cli/__tests__/token-manager.test.js +0 -251
  54. package/scripts/cli/__tests__/token-provider.test.js +0 -361
  55. package/scripts/cli/__tests__/utils.test.js +0 -165
  56. package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +0 -216
  57. package/src/components/AtomixGlass/stories/AnimationTests.stories.tsx +0 -95
  58. package/src/components/AtomixGlass/stories/CardExamples.stories.tsx +0 -212
  59. package/src/components/AtomixGlass/stories/Customization.stories.tsx +0 -131
  60. package/src/components/AtomixGlass/stories/DashboardExamples.stories.tsx +0 -348
  61. package/src/components/AtomixGlass/stories/EcommerceExamples.stories.tsx +0 -410
  62. package/src/components/AtomixGlass/stories/FormExamples.stories.tsx +0 -436
  63. package/src/components/AtomixGlass/stories/HeroExamples.stories.tsx +0 -264
  64. package/src/components/AtomixGlass/stories/InteractivePlayground.stories.tsx +0 -247
  65. package/src/components/AtomixGlass/stories/MobileUIExamples.stories.tsx +0 -418
  66. package/src/components/AtomixGlass/stories/ModalExamples.stories.tsx +0 -402
  67. package/src/components/AtomixGlass/stories/Modes.stories.tsx +0 -1082
  68. package/src/components/AtomixGlass/stories/Overview.stories.tsx +0 -497
  69. package/src/components/AtomixGlass/stories/Performance.stories.tsx +0 -103
  70. package/src/components/AtomixGlass/stories/PresetGallery.stories.tsx +0 -335
  71. package/src/components/AtomixGlass/stories/Shaders.stories.tsx +0 -395
  72. package/src/components/AtomixGlass/stories/WidgetExamples.stories.tsx +0 -441
  73. package/src/components/TypedButton/TypedButton.stories.tsx +0 -59
  74. package/src/components/TypedButton/TypedButton.tsx +0 -39
  75. package/src/components/TypedButton/index.ts +0 -2
  76. package/src/lib/composables/useTypedButton.ts +0 -66
@@ -1,441 +0,0 @@
1
- /**
2
- * WidgetExamples.stories.tsx
3
- *
4
- * Interactive widget examples for AtomixGlass including music players,
5
- * chat interfaces, notifications, and utility widgets.
6
- *
7
- * @package Atomix
8
- * @component AtomixGlass
9
- */
10
- import React from 'react';
11
- import { useState } from 'react';
12
- import { Meta, StoryObj } from '@storybook/react';
13
- import AtomixGlass from '../AtomixGlass';
14
- import { BackgroundWrapper, backgroundImages, StoryErrorBoundary } from './shared-components';
15
- import { baseArgTypes } from './argTypes';
16
-
17
- import { Button } from '../../Button';
18
- import { Badge } from '../../Badge';
19
- import { Input } from '../../../Form/Input';
20
-
21
- const meta: Meta<typeof AtomixGlass> = {
22
- title: 'Components/AtomixGlass/Examples/Widget Examples',
23
- component: AtomixGlass,
24
- parameters: {
25
- layout: 'centered',
26
- docs: {
27
- description: {
28
- component:
29
- 'Interactive widget examples demonstrating AtomixGlass for media players, chat interfaces, and utility components.',
30
- },
31
- },
32
- },
33
- tags: ['!autodocs'],
34
- argTypes: {
35
- ...baseArgTypes,
36
- children: { control: false },
37
- },
38
- };
39
-
40
- export default meta;
41
- type Story = StoryObj<typeof AtomixGlass>;
42
-
43
- /**
44
- * Music Player Widget
45
- *
46
- * Premium music player interface with playback controls, progress tracking, and volume control.
47
- */
48
- export const MusicPlayer: Story = {
49
- render: () => {
50
- const [isPlaying, setIsPlaying] = useState(false);
51
- const [currentTime, setCurrentTime] = useState(125);
52
- const [volume, setVolume] = useState(70);
53
-
54
- const totalDuration = 248;
55
-
56
- const formatTime = (seconds: number) => {
57
- const mins = Math.floor(seconds / 60);
58
- const secs = seconds % 60;
59
- return `${mins}:${secs.toString().padStart(2, '0')}`;
60
- };
61
-
62
- return (
63
- <StoryErrorBoundary>
64
- <BackgroundWrapper backgroundImage={backgroundImages[3]} overlay overlayOpacity={0.3}>
65
- <div style={{ maxWidth: '380px' }} className="u-mx-auto">
66
- <AtomixGlass
67
- displacementScale={55}
68
- blurAmount={3}
69
- borderRadius={28}
70
- mode="standard"
71
- padding="24px"
72
- >
73
- <div className="u-text-white">
74
- {/* Album Art */}
75
- <div
76
- style={{
77
- aspectRatio: '1:1',
78
- borderRadius: '20px',
79
- background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
80
- marginBottom: '24px',
81
- display: 'flex',
82
- alignItems: 'center',
83
- justifyContent: 'center',
84
- fontSize: '80px',
85
- boxShadow: '0 20px 40px rgba(102, 126, 234, 0.4)',
86
- }}
87
- aria-label="Album art"
88
- >
89
- 🎵
90
- </div>
91
-
92
- {/* Track Info */}
93
- <div className="u-text-center u-mb-4">
94
- <h2 className="u-m-0 u-mb-2 u-text-2xl u-font-bold">Summer Vibes</h2>
95
- <p className="u-m-0 u-opacity-80 u-text-sm">The Atomix Band</p>
96
- </div>
97
-
98
- {/* Progress Bar */}
99
- <div className="u-mb-4">
100
- <div
101
- style={{
102
- height: '6px',
103
- background: 'rgba(255,255,255,0.1)',
104
- borderRadius: '3px',
105
- overflow: 'hidden',
106
- cursor: 'pointer',
107
- }}
108
- onClick={(e) => {
109
- const rect = e.currentTarget.getBoundingClientRect();
110
- const x = e.clientX - rect.left;
111
- const percentage = x / rect.width;
112
- setCurrentTime(Math.floor(totalDuration * percentage));
113
- }}
114
- role="slider"
115
- aria-valuenow={currentTime}
116
- aria-valuemin={0}
117
- aria-valuemax={totalDuration}
118
- tabIndex={0}
119
- >
120
- <div
121
- style={{
122
- height: '100%',
123
- width: `${(currentTime / totalDuration) * 100}%`,
124
- background: 'linear-gradient(90deg, #667eea 0%, #764ba2 100%)',
125
- }}
126
- />
127
- </div>
128
- <div
129
- style={{
130
- display: 'flex',
131
- justifyContent: 'space-between',
132
- marginTop: '8px',
133
- fontSize: '13px',
134
- opacity: 0.7,
135
- }}
136
- >
137
- <span>{formatTime(currentTime)}</span>
138
- <span>{formatTime(totalDuration)}</span>
139
- </div>
140
- </div>
141
-
142
- {/* Playback Controls */}
143
- <div
144
- style={{
145
- display: 'flex',
146
- alignItems: 'center',
147
- justifyContent: 'center',
148
- gap: '16px',
149
- marginBottom: '20px',
150
- }}
151
- >
152
- <button
153
- onClick={() => setIsPlaying(!isPlaying)}
154
- style={{
155
- width: '64px',
156
- height: '64px',
157
- borderRadius: '50%',
158
- border: 'none',
159
- background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
160
- color: 'white',
161
- cursor: 'pointer',
162
- fontSize: '28px',
163
- display: 'flex',
164
- alignItems: 'center',
165
- justifyContent: 'center',
166
- boxShadow: '0 8px 20px rgba(102, 126, 234, 0.4)',
167
- }}
168
- aria-label={isPlaying ? 'Pause' : 'Play'}
169
- >
170
- {isPlaying ? '⏸️' : '▶️'}
171
- </button>
172
- </div>
173
-
174
- {/* Volume Control */}
175
- <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
176
- <span style={{ fontSize: '18px', opacity: 0.7 }} aria-hidden="true">
177
- 🔊
178
- </span>
179
- <input
180
- type="range"
181
- min="0"
182
- max="100"
183
- value={volume}
184
- onChange={(e) => setVolume(Number(e.target.value))}
185
- style={{
186
- flex: 1,
187
- accentColor: '#667eea',
188
- cursor: 'pointer',
189
- }}
190
- aria-label="Volume"
191
- />
192
- <span style={{ fontSize: '14px', opacity: 0.7, minWidth: '35px' }}>
193
- {volume}%
194
- </span>
195
- </div>
196
- </div>
197
- </AtomixGlass>
198
- </div>
199
- </BackgroundWrapper>
200
- </StoryErrorBoundary>
201
- );
202
- },
203
- parameters: {
204
- docs: {
205
- description: {
206
- story:
207
- 'Music player widget with play/pause controls, progress bar, and volume slider in a premium glass interface.',
208
- },
209
- },
210
- },
211
- };
212
-
213
- /**
214
- * Chat Interface Widget
215
- *
216
- * Real-time chat interface with message history and input field.
217
- */
218
- export const ChatInterface: Story = {
219
- render: () => {
220
- const [message, setMessage] = useState('');
221
- const [messages, setMessages] = useState([
222
- { id: 1, text: 'Hey! How are you?', sender: 'them', time: '10:30 AM' },
223
- { id: 2, text: "I'm doing great! Working on something cool.", sender: 'me', time: '10:32 AM' },
224
- { id: 3, text: 'Oh really? What is it?', sender: 'them', time: '10:33 AM' },
225
- ]);
226
-
227
- const handleSend = () => {
228
- if (!message.trim()) return;
229
- setMessages([
230
- ...messages,
231
- { id: messages.length + 1, text: message, sender: 'me', time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) },
232
- ]);
233
- setMessage('');
234
- };
235
-
236
- return (
237
- <StoryErrorBoundary>
238
- <BackgroundWrapper backgroundImage={backgroundImages[5]} overlay overlayOpacity={0.4}>
239
- <div style={{ maxWidth: '400px', height: '500px' }}>
240
- <AtomixGlass
241
- displacementScale={60}
242
- blurAmount={0.75}
243
- saturation={140}
244
- borderRadius={24}
245
- mode="standard"
246
- >
247
- <div className="u-text-white" style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
248
- {/* Header */}
249
- <div
250
- style={{
251
- padding: '20px',
252
- borderBottom: '1px solid rgba(255,255,255,0.1)',
253
- display: 'flex',
254
- alignItems: 'center',
255
- gap: '12px',
256
- }}
257
- >
258
- <div
259
- style={{
260
- width: '40px',
261
- height: '40px',
262
- borderRadius: '50%',
263
- background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
264
- display: 'flex',
265
- alignItems: 'center',
266
- justifyContent: 'center',
267
- fontSize: '20px',
268
- }}
269
- aria-hidden="true"
270
- >
271
- 💬
272
- </div>
273
- <div>
274
- <h3 className="u-m-0 u-font-semibold">Chat</h3>
275
- <p className="u-m-0 u-text-xs u-opacity-70">3 messages</p>
276
- </div>
277
- </div>
278
-
279
- {/* Messages */}
280
- <div style={{ flex: 1, padding: '20px', overflowY: 'auto' }}>
281
- {messages.map((msg) => (
282
- <div
283
- key={msg.id}
284
- style={{
285
- marginBottom: '16px',
286
- display: 'flex',
287
- justifyContent: msg.sender === 'me' ? 'flex-end' : 'flex-start',
288
- }}
289
- >
290
- <div
291
- style={{
292
- maxWidth: '75%',
293
- padding: '12px 16px',
294
- borderRadius: '16px',
295
- background: msg.sender === 'me'
296
- ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)'
297
- : 'rgba(255,255,255,0.1)',
298
- boxShadow: msg.sender === 'me' ? '0 4px 12px rgba(102, 126, 234, 0.3)' : 'none',
299
- }}
300
- >
301
- <p className="u-m-0 u-text-sm" style={{ lineHeight: 1.5 }}>{msg.text}</p>
302
- <p className="u-m-0 u-text-xs u-opacity-60 u-mt-1" style={{ textAlign: 'right' }}>
303
- {msg.time}
304
- </p>
305
- </div>
306
- </div>
307
- ))}
308
- </div>
309
-
310
- {/* Input */}
311
- <div
312
- style={{
313
- padding: '16px',
314
- borderTop: '1px solid rgba(255,255,255,0.1)',
315
- display: 'flex',
316
- gap: '12px',
317
- }}
318
- >
319
- <Input
320
- type="text"
321
- value={message}
322
- onChange={(e) => setMessage(e.target.value)}
323
- placeholder="Type a message..."
324
- onKeyDown={(e) => e.key === 'Enter' && handleSend()}
325
- glass={{ elasticity: 0 }}
326
- className="u-flex-1"
327
- />
328
- <Button
329
- variant="primary"
330
- glass={{ elasticity: 0 }}
331
- onClick={handleSend}
332
- disabled={!message.trim()}
333
- >
334
- Send
335
- </Button>
336
- </div>
337
- </div>
338
- </AtomixGlass>
339
- </div>
340
- </BackgroundWrapper>
341
- </StoryErrorBoundary>
342
- );
343
- },
344
- parameters: {
345
- docs: {
346
- description: {
347
- story:
348
- 'Real-time chat interface with message history, timestamps, and live input for modern messaging applications.',
349
- },
350
- },
351
- },
352
- };
353
-
354
- /**
355
- * Notification Center Widget
356
- *
357
- * Centralized notification panel with multiple notification types.
358
- */
359
- export const NotificationCenter: Story = {
360
- render: () => {
361
- const [notifications, setNotifications] = useState([
362
- { id: 1, type: 'success', title: 'Payment Received', message: '$250.00 from John Doe', time: '2m ago' },
363
- { id: 2, type: 'warning', title: 'Storage Almost Full', message: '85% of your storage is used', time: '1h ago' },
364
- { id: 3, type: 'info', title: 'New Feature Available', message: 'Check out the latest updates', time: '3h ago' },
365
- ]);
366
-
367
- const getTypeIcon = (type: string) => {
368
- switch (type) {
369
- case 'success': return '✅';
370
- case 'warning': return '⚠️';
371
- case 'info': return 'ℹ️';
372
- default: return '📢';
373
- }
374
- };
375
-
376
- return (
377
- <StoryErrorBoundary>
378
- <BackgroundWrapper backgroundImage={backgroundImages[0]} overlay overlayOpacity={0.4}>
379
- <div style={{ maxWidth: '420px' }}>
380
- <AtomixGlass
381
- displacementScale={65}
382
- blurAmount={0.75}
383
- saturation={140}
384
- borderRadius={24}
385
- mode="standard"
386
- >
387
- <div className="u-text-white" style={{ padding: '24px' }}>
388
- <div className="u-flex u-items-center u-justify-between u-mb-4">
389
- <h2 className="u-m-0 u-text-xl u-font-bold">Notifications</h2>
390
- <Badge variant="primary">{notifications.length}</Badge>
391
- </div>
392
-
393
- <div className="u-divide-y" style={{ borderColor: 'rgba(255,255,255,0.1)' }}>
394
- {notifications.map((notification) => (
395
- <div
396
- key={notification.id}
397
- className="u-py-3 u-flex u-gap-3"
398
- style={{ cursor: 'pointer' }}
399
- >
400
- <div
401
- style={{
402
- fontSize: '24px',
403
- flexShrink: 0,
404
- }}
405
- aria-hidden="true"
406
- >
407
- {getTypeIcon(notification.type)}
408
- </div>
409
- <div className="u-flex-1">
410
- <p className="u-m-0 u-font-semibold u-text-sm">{notification.title}</p>
411
- <p className="u-m-0 u-text-xs u-opacity-80 u-mt-1">{notification.message}</p>
412
- </div>
413
- <span className="u-text-xs u-opacity-60">{notification.time}</span>
414
- </div>
415
- ))}
416
- </div>
417
-
418
- <Button
419
- variant="outline-light"
420
- glass={{ elasticity: 0 }}
421
- size="sm"
422
- className="u-block u-w-full u-mt-4"
423
- >
424
- Mark All as Read
425
- </Button>
426
- </div>
427
- </AtomixGlass>
428
- </div>
429
- </BackgroundWrapper>
430
- </StoryErrorBoundary>
431
- );
432
- },
433
- parameters: {
434
- docs: {
435
- description: {
436
- story:
437
- 'Notification center panel displaying success, warning, and info notifications with timestamps.',
438
- },
439
- },
440
- },
441
- };
@@ -1,59 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react';
2
- import { TypedButton } from './TypedButton';
3
-
4
- const meta: Meta<typeof TypedButton> = {
5
- title: 'Components/TypedButton',
6
- component: TypedButton,
7
- parameters: {
8
- layout: 'centered',
9
- },
10
- tags: ['autodocs'],
11
- argTypes: {
12
- size: {
13
- control: 'select',
14
- options: ['sm', 'md', 'lg'],
15
- },
16
- variant: {
17
- control: 'select',
18
- options: ['primary', 'secondary', 'success', 'error'],
19
- },
20
- disabled: {
21
- control: 'boolean',
22
- },
23
- glass: {
24
- control: 'boolean',
25
- },
26
- },
27
- };
28
-
29
- export default meta;
30
- type Story = StoryObj<typeof meta>;
31
-
32
- export const Default: Story = {
33
- args: {
34
- children: 'TypedButton Component',
35
- size: 'md',
36
- variant: 'primary',
37
- },
38
- };
39
-
40
- export const Small: Story = {
41
- args: {
42
- ...Default.args,
43
- size: 'sm',
44
- },
45
- };
46
-
47
- export const Large: Story = {
48
- args: {
49
- ...Default.args,
50
- size: 'lg',
51
- },
52
- };
53
-
54
- export const Glass: Story = {
55
- args: {
56
- ...Default.args,
57
- glass: true,
58
- },
59
- };
@@ -1,39 +0,0 @@
1
- import React, { forwardRef, useId, memo } from 'react';
2
- import { TYPEDBUTTON } from '../../lib/constants/components';
3
- import { useTypedButton } from '../../lib/composables/useTypedButton';
4
- import { AtomixGlass } from '../AtomixGlass/AtomixGlass';
5
- import type { TypedButtonProps } from '../../lib/types/components';
6
-
7
- /**
8
- * TypedButton - Medium Presentational Component
9
- *
10
- * @param {TypedButtonProps} props - Component properties
11
- * @returns {JSX.Element} The rendered component
12
- */
13
- export const TypedButton = memo(
14
- forwardRef<HTMLDivElement, TypedButtonProps>(
15
- ({ children, className = '', disabled = false, glass, style, 'aria-label': ariaLabel, ...props }, ref) => {
16
- const instanceId = useId();
17
- const { generateClassNames } = useTypedButton({ disabled });
18
-
19
- const content = (
20
- <div
21
- ref={ref}
22
- className={generateClassNames(className)}
23
- style={style}
24
- aria-label={ariaLabel}
25
- aria-disabled={disabled}
26
- {...props}
27
- >
28
- {children}
29
- </div>
30
- );
31
-
32
- return glass ? <AtomixGlass {...(glass === true ? {} : glass)}>{content}</AtomixGlass> : content;
33
- }
34
- )
35
- );
36
-
37
- TypedButton.displayName = 'TypedButton';
38
-
39
- export default TypedButton;
@@ -1,2 +0,0 @@
1
- export { default as TypedButton } from './TypedButton';
2
- export type { TypedButtonProps } from './TypedButton';
@@ -1,66 +0,0 @@
1
- import { TypedButtonProps } from '../types/components';
2
- import { TYPEDBUTTON } from '../constants/components';
3
-
4
- /**
5
- * TypedButton state and functionality
6
- * @param initialProps - Initial typedbutton properties
7
- * @returns TypedButton state and methods
8
- */
9
- export function useTypedButton(initialProps?: Partial<TypedButtonProps>) {
10
- // Default typedbutton properties
11
- const defaultProps: Partial<TypedButtonProps> = {
12
- variant: 'primary',
13
- size: 'md',
14
- disabled: false,
15
- ...initialProps,
16
- };
17
-
18
- /**
19
- * Generate typedbutton class based on properties
20
- * @param props - TypedButton properties
21
- * @returns Class string
22
- */
23
- const generateClassNames = (props: Partial<TypedButtonProps> = {}): string => {
24
- const {
25
- variant = defaultProps.variant,
26
- size = defaultProps.size,
27
- disabled = defaultProps.disabled,
28
- glass = defaultProps.glass,
29
- className = '',
30
- } = props;
31
-
32
- const sizeClass = size === 'md' ? '' : `c-typedbutton--${size}`;
33
- const disabledClass = disabled ? 'c-typedbutton--disabled' : '';
34
- const glassClass = glass ? 'c-typedbutton--glass' : '';
35
-
36
- return [
37
- TYPEDBUTTON.BASE_CLASS,
38
- `c-typedbutton--${variant}`,
39
- sizeClass,
40
- disabledClass,
41
- glassClass,
42
- className,
43
- ]
44
- .filter(Boolean)
45
- .join(' ');
46
- };
47
-
48
- /**
49
- * Handle typedbutton click with disabled check
50
- * @param handler - Click handler function
51
- * @returns Function that respects disabled state
52
- */
53
- const handleClick = (handler?: (event: React.MouseEvent<HTMLDivElement>) => void) => {
54
- return (event: React.MouseEvent<HTMLDivElement>) => {
55
- if (!defaultProps.disabled && handler) {
56
- handler(event);
57
- }
58
- };
59
- };
60
-
61
- return {
62
- defaultProps,
63
- generateClassNames,
64
- handleClick,
65
- };
66
- }