@udixio/ui-react 2.10.13 → 2.10.15
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/package.json +4 -2
- package/.eslintrc.mjs +0 -22
- package/.storybook/main.ts +0 -20
- package/.storybook/preview.ts +0 -1
- package/CHANGELOG.md +0 -1144
- package/postcss.config.mjs +0 -5
- package/src/index.css +0 -4
- package/src/index.ts +0 -1
- package/src/lib/components/AnchorPositioner.tsx +0 -185
- package/src/lib/components/Button.tsx +0 -208
- package/src/lib/components/Card.tsx +0 -47
- package/src/lib/components/Carousel.tsx +0 -437
- package/src/lib/components/CarouselItem.tsx +0 -61
- package/src/lib/components/Checkbox.tsx +0 -120
- package/src/lib/components/Chip.tsx +0 -341
- package/src/lib/components/Chips.tsx +0 -331
- package/src/lib/components/ContextMenu.tsx +0 -109
- package/src/lib/components/DatePicker.tsx +0 -432
- package/src/lib/components/Divider.tsx +0 -20
- package/src/lib/components/Fab.tsx +0 -127
- package/src/lib/components/FabMenu.tsx +0 -239
- package/src/lib/components/IconButton.tsx +0 -146
- package/src/lib/components/Menu.tsx +0 -88
- package/src/lib/components/MenuGroup.tsx +0 -34
- package/src/lib/components/MenuHeadline.tsx +0 -9
- package/src/lib/components/MenuItem.tsx +0 -215
- package/src/lib/components/NavigationRail.tsx +0 -186
- package/src/lib/components/NavigationRailItem.tsx +0 -227
- package/src/lib/components/ProgressIndicator.tsx +0 -214
- package/src/lib/components/SideSheet.tsx +0 -135
- package/src/lib/components/Slider.tsx +0 -374
- package/src/lib/components/Snackbar.tsx +0 -77
- package/src/lib/components/Switch.tsx +0 -107
- package/src/lib/components/Tab.tsx +0 -123
- package/src/lib/components/TabGroup.tsx +0 -66
- package/src/lib/components/TabGroupContext.tsx +0 -16
- package/src/lib/components/TabPanel.tsx +0 -27
- package/src/lib/components/TabPanels.tsx +0 -76
- package/src/lib/components/Tabs.tsx +0 -105
- package/src/lib/components/TextField.tsx +0 -586
- package/src/lib/components/Tooltip.tsx +0 -217
- package/src/lib/components/index.ts +0 -34
- package/src/lib/config/config.interface.ts +0 -9
- package/src/lib/config/define-config.ts +0 -16
- package/src/lib/config/index.ts +0 -2
- package/src/lib/effects/AnimateOnScroll.ts +0 -391
- package/src/lib/effects/State.tsx +0 -90
- package/src/lib/effects/SyncedFixedWrapper.tsx +0 -62
- package/src/lib/effects/ThemeProvider.tsx +0 -174
- package/src/lib/effects/block-scroll.effect.tsx +0 -313
- package/src/lib/effects/custom-scroll/custom-scroll.effect.tsx +0 -407
- package/src/lib/effects/custom-scroll/custom-scroll.interface.ts +0 -29
- package/src/lib/effects/custom-scroll/custom-scroll.style.ts +0 -32
- package/src/lib/effects/custom-scroll/index.ts +0 -3
- package/src/lib/effects/index.ts +0 -7
- package/src/lib/effects/ripple/RippleEffect.tsx +0 -116
- package/src/lib/effects/ripple/index.tsx +0 -1
- package/src/lib/effects/scrollDriven.ts +0 -239
- package/src/lib/effects/smooth-scroll.effect.tsx +0 -112
- package/src/lib/effects/theme.worker.ts +0 -97
- package/src/lib/hooks/index.ts +0 -10
- package/src/lib/hooks/useTooltipTrigger.ts +0 -270
- package/src/lib/icon/icon.tsx +0 -125
- package/src/lib/icon/index.ts +0 -1
- package/src/lib/index.ts +0 -8
- package/src/lib/interfaces/button.interface.ts +0 -65
- package/src/lib/interfaces/card.interface.ts +0 -11
- package/src/lib/interfaces/carousel-item.interface.ts +0 -12
- package/src/lib/interfaces/carousel.interface.ts +0 -41
- package/src/lib/interfaces/checkbox.interface.ts +0 -39
- package/src/lib/interfaces/chip.interface.ts +0 -97
- package/src/lib/interfaces/chips.interface.ts +0 -37
- package/src/lib/interfaces/date-picker.interface.ts +0 -79
- package/src/lib/interfaces/divider.interface.ts +0 -7
- package/src/lib/interfaces/fab-menu.interface.ts +0 -12
- package/src/lib/interfaces/fab.interface.ts +0 -27
- package/src/lib/interfaces/icon-button.interface.ts +0 -38
- package/src/lib/interfaces/index.ts +0 -26
- package/src/lib/interfaces/menu-group.interface.ts +0 -13
- package/src/lib/interfaces/menu-item.interface.ts +0 -29
- package/src/lib/interfaces/menu.interface.ts +0 -19
- package/src/lib/interfaces/navigation-rail-item.interface.ts +0 -39
- package/src/lib/interfaces/navigation-rail.interface.ts +0 -39
- package/src/lib/interfaces/progress-indicator.interface.ts +0 -41
- package/src/lib/interfaces/side-sheet.interface.tsx +0 -28
- package/src/lib/interfaces/slider.interface.ts +0 -27
- package/src/lib/interfaces/snackbar.interface.ts +0 -13
- package/src/lib/interfaces/switch.interface.ts +0 -14
- package/src/lib/interfaces/tab-group.interface.ts +0 -13
- package/src/lib/interfaces/tab-panels.interface.ts +0 -21
- package/src/lib/interfaces/tab.interface.ts +0 -31
- package/src/lib/interfaces/tabs.interface.ts +0 -22
- package/src/lib/interfaces/text-field.interface.ts +0 -61
- package/src/lib/interfaces/tooltip.interface.ts +0 -61
- package/src/lib/styles/button.style.ts +0 -136
- package/src/lib/styles/card.style.ts +0 -29
- package/src/lib/styles/carousel-item.style.ts +0 -24
- package/src/lib/styles/carousel.style.ts +0 -22
- package/src/lib/styles/checkbox.style.ts +0 -64
- package/src/lib/styles/chip.style.ts +0 -62
- package/src/lib/styles/chips.style.ts +0 -20
- package/src/lib/styles/date-picker.style.ts +0 -43
- package/src/lib/styles/divider.style.ts +0 -31
- package/src/lib/styles/fab-menu.style.ts +0 -29
- package/src/lib/styles/fab.style.ts +0 -49
- package/src/lib/styles/icon-button.style.ts +0 -168
- package/src/lib/styles/index.ts +0 -25
- package/src/lib/styles/menu-group.style.ts +0 -34
- package/src/lib/styles/menu-headline.style.ts +0 -20
- package/src/lib/styles/menu-item.style.ts +0 -45
- package/src/lib/styles/menu.style.ts +0 -32
- package/src/lib/styles/navigation-rail-item.style.ts +0 -56
- package/src/lib/styles/navigation-rail.style.ts +0 -36
- package/src/lib/styles/progress-indicator.style.ts +0 -72
- package/src/lib/styles/side-sheet.style.ts +0 -45
- package/src/lib/styles/slider.style.ts +0 -41
- package/src/lib/styles/snackbar.style.ts +0 -26
- package/src/lib/styles/switch.style.ts +0 -67
- package/src/lib/styles/tab-panels.style.ts +0 -35
- package/src/lib/styles/tab.style.ts +0 -78
- package/src/lib/styles/tabs.style.ts +0 -22
- package/src/lib/styles/text-field.style.ts +0 -115
- package/src/lib/styles/tooltip.style.ts +0 -48
- package/src/lib/utils/component-helper.ts +0 -134
- package/src/lib/utils/component.ts +0 -34
- package/src/lib/utils/index.ts +0 -7
- package/src/lib/utils/string.ts +0 -9
- package/src/lib/utils/styles/classnames.ts +0 -49
- package/src/lib/utils/styles/get-classname.ts +0 -96
- package/src/lib/utils/styles/index.ts +0 -4
- package/src/lib/utils/styles/use-classnames.ts +0 -25
- package/src/stories/action/button.stories.tsx +0 -86
- package/src/stories/action/fab.stories.tsx +0 -54
- package/src/stories/action/icon-button.stories.tsx +0 -134
- package/src/stories/assets/accessibility.png +0 -0
- package/src/stories/assets/accessibility.svg +0 -5
- package/src/stories/assets/addon-library.png +0 -0
- package/src/stories/assets/assets.png +0 -0
- package/src/stories/assets/context.png +0 -0
- package/src/stories/assets/discord.svg +0 -15
- package/src/stories/assets/docs.png +0 -0
- package/src/stories/assets/figma-plugin.png +0 -0
- package/src/stories/assets/github.svg +0 -3
- package/src/stories/assets/share.png +0 -0
- package/src/stories/assets/styling.png +0 -0
- package/src/stories/assets/testing.png +0 -0
- package/src/stories/assets/theming.png +0 -0
- package/src/stories/assets/tutorials.svg +0 -12
- package/src/stories/assets/youtube.svg +0 -4
- package/src/stories/communication/ProgressIndicator.stories.tsx +0 -57
- package/src/stories/communication/SnackBar.stories.tsx +0 -32
- package/src/stories/communication/tool-tip.stories.tsx +0 -133
- package/src/stories/containment/card.stories.tsx +0 -42
- package/src/stories/containment/carousel.stories.tsx +0 -65
- package/src/stories/containment/divider.stories.tsx +0 -35
- package/src/stories/containment/slide-sheet.stories.tsx +0 -45
- package/src/stories/effect/smooth-scroll.stories.tsx +0 -54
- package/src/stories/navigation/navigation-rail/navigation-rail-item.stories.tsx +0 -65
- package/src/stories/navigation/navigation-rail/navigation-rail.stories.tsx +0 -122
- package/src/stories/navigation/tabs/tab.stories.tsx +0 -57
- package/src/stories/navigation/tabs/tabs.stories.tsx +0 -102
- package/src/stories/selection/slider.stories.tsx +0 -85
- package/src/stories/selection/switch.stories.tsx +0 -46
- package/src/stories/text-inputs/text-field.stories.tsx +0 -135
- package/src/tests/Button.spec.tsx +0 -67
- package/src/tests/useClassNames.spec.tsx +0 -82
- package/src/udixio.css +0 -120
- package/theme.config.ts +0 -7
- package/tsconfig.json +0 -16
- package/tsconfig.lib.json +0 -51
- package/tsconfig.spec.json +0 -37
- package/tsconfig.storybook.json +0 -38
- package/vite.config.ts +0 -96
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
import { useCallback, useEffect, useId, useRef, useState } from 'react';
|
|
2
|
-
|
|
3
|
-
type Trigger = 'hover' | 'click' | 'focus' | null;
|
|
4
|
-
|
|
5
|
-
type TooltipState = 'hidden' | 'hovered' | 'focused' | 'clicked';
|
|
6
|
-
|
|
7
|
-
export interface UseTooltipTriggerOptions {
|
|
8
|
-
trigger?: Trigger | Trigger[];
|
|
9
|
-
isOpen?: boolean;
|
|
10
|
-
defaultOpen?: boolean;
|
|
11
|
-
onOpenChange?: (open: boolean) => void;
|
|
12
|
-
openDelay?: number;
|
|
13
|
-
closeDelay?: number;
|
|
14
|
-
id?: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface UseTooltipTriggerReturn {
|
|
18
|
-
triggerProps: {
|
|
19
|
-
'aria-describedby': string | undefined;
|
|
20
|
-
onMouseEnter: () => void;
|
|
21
|
-
onMouseLeave: () => void;
|
|
22
|
-
onFocus: () => void;
|
|
23
|
-
onBlur: () => void;
|
|
24
|
-
onClick: () => void;
|
|
25
|
-
onKeyDown: (event: React.KeyboardEvent) => void;
|
|
26
|
-
};
|
|
27
|
-
tooltipProps: {
|
|
28
|
-
id: string;
|
|
29
|
-
role: 'tooltip';
|
|
30
|
-
'aria-hidden': boolean;
|
|
31
|
-
onMouseEnter: () => void;
|
|
32
|
-
onMouseLeave: () => void;
|
|
33
|
-
};
|
|
34
|
-
isOpen: boolean;
|
|
35
|
-
state: TooltipState;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Hook to manage tooltip trigger state machine, events, and accessibility props.
|
|
40
|
-
*
|
|
41
|
-
* State Machine:
|
|
42
|
-
* - States: hidden | hovered | focused | clicked
|
|
43
|
-
* - Priority: clicked > focused > hovered > hidden
|
|
44
|
-
* - Focus takes priority over hover (don't close on mouse leave if focused)
|
|
45
|
-
* - Escape key closes tooltip from any open state
|
|
46
|
-
* - Click toggles for 'click' trigger
|
|
47
|
-
*/
|
|
48
|
-
export function useTooltipTrigger({
|
|
49
|
-
trigger = ['hover', 'focus'],
|
|
50
|
-
isOpen: isOpenProp,
|
|
51
|
-
defaultOpen = false,
|
|
52
|
-
onOpenChange,
|
|
53
|
-
openDelay = 400,
|
|
54
|
-
closeDelay = 150,
|
|
55
|
-
id: idProp,
|
|
56
|
-
}: UseTooltipTriggerOptions = {}): UseTooltipTriggerReturn {
|
|
57
|
-
const generatedId = useId();
|
|
58
|
-
const tooltipId = idProp ?? `tooltip-${generatedId}`;
|
|
59
|
-
|
|
60
|
-
// Normalize trigger to array
|
|
61
|
-
const triggers = Array.isArray(trigger) ? trigger : [trigger];
|
|
62
|
-
|
|
63
|
-
// Controlled vs uncontrolled state
|
|
64
|
-
const isControlled = typeof isOpenProp === 'boolean';
|
|
65
|
-
const [internalState, setInternalState] = useState<TooltipState>(
|
|
66
|
-
defaultOpen ? 'hovered' : 'hidden',
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
// Track if tooltip content is being hovered (for pointer intent)
|
|
70
|
-
const [isTooltipHovered, setIsTooltipHovered] = useState(false);
|
|
71
|
-
|
|
72
|
-
// Timeout refs for delayed open/close
|
|
73
|
-
const openTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
74
|
-
const closeTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
75
|
-
|
|
76
|
-
// Clear all timeouts
|
|
77
|
-
const clearTimeouts = useCallback(() => {
|
|
78
|
-
if (openTimeoutRef.current) {
|
|
79
|
-
clearTimeout(openTimeoutRef.current);
|
|
80
|
-
openTimeoutRef.current = null;
|
|
81
|
-
}
|
|
82
|
-
if (closeTimeoutRef.current) {
|
|
83
|
-
clearTimeout(closeTimeoutRef.current);
|
|
84
|
-
closeTimeoutRef.current = null;
|
|
85
|
-
}
|
|
86
|
-
}, []);
|
|
87
|
-
|
|
88
|
-
// Cleanup on unmount
|
|
89
|
-
useEffect(() => {
|
|
90
|
-
return () => clearTimeouts();
|
|
91
|
-
}, [clearTimeouts]);
|
|
92
|
-
|
|
93
|
-
// State transition function
|
|
94
|
-
const transition = useCallback(
|
|
95
|
-
(newState: TooltipState) => {
|
|
96
|
-
if (isControlled) {
|
|
97
|
-
// In controlled mode, notify parent of desired state change
|
|
98
|
-
const shouldBeOpen = newState !== 'hidden';
|
|
99
|
-
onOpenChange?.(shouldBeOpen);
|
|
100
|
-
} else {
|
|
101
|
-
setInternalState(newState);
|
|
102
|
-
const shouldBeOpen = newState !== 'hidden';
|
|
103
|
-
onOpenChange?.(shouldBeOpen);
|
|
104
|
-
}
|
|
105
|
-
},
|
|
106
|
-
[isControlled, onOpenChange],
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
// Compute actual state and isOpen
|
|
110
|
-
const state = isControlled
|
|
111
|
-
? isOpenProp
|
|
112
|
-
? 'hovered' // Simplified: in controlled mode, we just track open/closed
|
|
113
|
-
: 'hidden'
|
|
114
|
-
: internalState;
|
|
115
|
-
|
|
116
|
-
const isOpen = state !== 'hidden';
|
|
117
|
-
|
|
118
|
-
// Get state priority for comparison
|
|
119
|
-
const getStatePriority = (s: TooltipState): number => {
|
|
120
|
-
switch (s) {
|
|
121
|
-
case 'hidden':
|
|
122
|
-
return 0;
|
|
123
|
-
case 'hovered':
|
|
124
|
-
return 1;
|
|
125
|
-
case 'focused':
|
|
126
|
-
return 2;
|
|
127
|
-
case 'clicked':
|
|
128
|
-
return 3;
|
|
129
|
-
default:
|
|
130
|
-
return 0;
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
// Schedule opening with delay
|
|
135
|
-
const scheduleOpen = useCallback(
|
|
136
|
-
(targetState: TooltipState) => {
|
|
137
|
-
clearTimeouts();
|
|
138
|
-
|
|
139
|
-
// Only transition if new state has higher priority
|
|
140
|
-
if (getStatePriority(targetState) <= getStatePriority(state)) {
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
openTimeoutRef.current = setTimeout(() => {
|
|
145
|
-
transition(targetState);
|
|
146
|
-
}, openDelay);
|
|
147
|
-
},
|
|
148
|
-
[clearTimeouts, openDelay, state, transition],
|
|
149
|
-
);
|
|
150
|
-
|
|
151
|
-
// Schedule closing with delay
|
|
152
|
-
const scheduleClose = useCallback(
|
|
153
|
-
(fromState: TooltipState) => {
|
|
154
|
-
clearTimeouts();
|
|
155
|
-
|
|
156
|
-
closeTimeoutRef.current = setTimeout(() => {
|
|
157
|
-
// Only close if we're still in the same state (or lower priority)
|
|
158
|
-
if (
|
|
159
|
-
!isControlled &&
|
|
160
|
-
getStatePriority(internalState) <= getStatePriority(fromState)
|
|
161
|
-
) {
|
|
162
|
-
transition('hidden');
|
|
163
|
-
} else if (isControlled) {
|
|
164
|
-
transition('hidden');
|
|
165
|
-
}
|
|
166
|
-
}, closeDelay);
|
|
167
|
-
},
|
|
168
|
-
[clearTimeouts, closeDelay, internalState, isControlled, transition],
|
|
169
|
-
);
|
|
170
|
-
|
|
171
|
-
// Event handlers for trigger element
|
|
172
|
-
const handleMouseEnter = useCallback(() => {
|
|
173
|
-
if (!triggers.includes('hover')) return;
|
|
174
|
-
scheduleOpen('hovered');
|
|
175
|
-
}, [triggers, scheduleOpen]);
|
|
176
|
-
|
|
177
|
-
const handleMouseLeave = useCallback(() => {
|
|
178
|
-
if (!triggers.includes('hover')) return;
|
|
179
|
-
|
|
180
|
-
// Don't close if focused (focus has higher priority)
|
|
181
|
-
if (state === 'focused' || state === 'clicked') return;
|
|
182
|
-
|
|
183
|
-
// Don't close immediately if tooltip itself is hovered
|
|
184
|
-
if (isTooltipHovered) return;
|
|
185
|
-
|
|
186
|
-
scheduleClose('hovered');
|
|
187
|
-
}, [triggers, state, isTooltipHovered, scheduleClose]);
|
|
188
|
-
|
|
189
|
-
const handleFocus = useCallback(() => {
|
|
190
|
-
if (!triggers.includes('focus')) return;
|
|
191
|
-
clearTimeouts();
|
|
192
|
-
transition('focused');
|
|
193
|
-
}, [triggers, clearTimeouts, transition]);
|
|
194
|
-
|
|
195
|
-
const handleBlur = useCallback(() => {
|
|
196
|
-
if (!triggers.includes('focus')) return;
|
|
197
|
-
|
|
198
|
-
// Don't close if clicked (clicked has higher priority)
|
|
199
|
-
if (state === 'clicked') return;
|
|
200
|
-
|
|
201
|
-
// If also hovering, transition to hovered state
|
|
202
|
-
if (triggers.includes('hover') && isTooltipHovered) {
|
|
203
|
-
transition('hovered');
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
scheduleClose('focused');
|
|
208
|
-
}, [triggers, state, isTooltipHovered, scheduleClose, transition]);
|
|
209
|
-
|
|
210
|
-
const handleClick = useCallback(() => {
|
|
211
|
-
if (!triggers.includes('click')) return;
|
|
212
|
-
|
|
213
|
-
clearTimeouts();
|
|
214
|
-
|
|
215
|
-
// Toggle behavior for click trigger
|
|
216
|
-
if (state === 'clicked') {
|
|
217
|
-
transition('hidden');
|
|
218
|
-
} else {
|
|
219
|
-
transition('clicked');
|
|
220
|
-
}
|
|
221
|
-
}, [triggers, state, clearTimeouts, transition]);
|
|
222
|
-
|
|
223
|
-
const handleKeyDown = useCallback(
|
|
224
|
-
(event: React.KeyboardEvent) => {
|
|
225
|
-
// Escape closes tooltip from any open state
|
|
226
|
-
if (event.key === 'Escape' && isOpen) {
|
|
227
|
-
clearTimeouts();
|
|
228
|
-
transition('hidden');
|
|
229
|
-
event.preventDefault();
|
|
230
|
-
}
|
|
231
|
-
},
|
|
232
|
-
[isOpen, clearTimeouts, transition],
|
|
233
|
-
);
|
|
234
|
-
|
|
235
|
-
// Event handlers for tooltip element (pointer intent)
|
|
236
|
-
const handleTooltipMouseEnter = useCallback(() => {
|
|
237
|
-
setIsTooltipHovered(true);
|
|
238
|
-
clearTimeouts();
|
|
239
|
-
}, [clearTimeouts]);
|
|
240
|
-
|
|
241
|
-
const handleTooltipMouseLeave = useCallback(() => {
|
|
242
|
-
setIsTooltipHovered(false);
|
|
243
|
-
|
|
244
|
-
// If trigger includes hover and we're in hover state, schedule close
|
|
245
|
-
if (triggers.includes('hover') && state === 'hovered') {
|
|
246
|
-
scheduleClose('hovered');
|
|
247
|
-
}
|
|
248
|
-
}, [triggers, state, scheduleClose]);
|
|
249
|
-
|
|
250
|
-
return {
|
|
251
|
-
triggerProps: {
|
|
252
|
-
'aria-describedby': isOpen ? tooltipId : undefined,
|
|
253
|
-
onMouseEnter: handleMouseEnter,
|
|
254
|
-
onMouseLeave: handleMouseLeave,
|
|
255
|
-
onFocus: handleFocus,
|
|
256
|
-
onBlur: handleBlur,
|
|
257
|
-
onClick: handleClick,
|
|
258
|
-
onKeyDown: handleKeyDown,
|
|
259
|
-
},
|
|
260
|
-
tooltipProps: {
|
|
261
|
-
id: tooltipId,
|
|
262
|
-
role: 'tooltip',
|
|
263
|
-
'aria-hidden': !isOpen,
|
|
264
|
-
onMouseEnter: handleTooltipMouseEnter,
|
|
265
|
-
onMouseLeave: handleTooltipMouseLeave,
|
|
266
|
-
},
|
|
267
|
-
isOpen,
|
|
268
|
-
state,
|
|
269
|
-
};
|
|
270
|
-
}
|
package/src/lib/icon/icon.tsx
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import type React from 'react';
|
|
2
|
-
import { IconDefinition } from '@fortawesome/fontawesome-svg-core';
|
|
3
|
-
import { classNames } from '../utils';
|
|
4
|
-
|
|
5
|
-
export type Icon = IconDefinition | SvgImport | string;
|
|
6
|
-
|
|
7
|
-
interface SvgImport {
|
|
8
|
-
src: string;
|
|
9
|
-
width: number;
|
|
10
|
-
height: number;
|
|
11
|
-
format: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
interface Props {
|
|
15
|
-
icon: Icon;
|
|
16
|
-
colors?: string[];
|
|
17
|
-
className?: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export const Icon: React.FC<Props> = ({
|
|
21
|
-
icon,
|
|
22
|
-
colors = [],
|
|
23
|
-
className,
|
|
24
|
-
...restProps
|
|
25
|
-
}) => {
|
|
26
|
-
// Si c'est une chaîne de caractères (SVG raw)
|
|
27
|
-
if (typeof icon === 'string') {
|
|
28
|
-
let svgContent = icon;
|
|
29
|
-
let colorAttrs = '';
|
|
30
|
-
|
|
31
|
-
if (colors[0]) {
|
|
32
|
-
colorAttrs = ` fill="${colors[0]}" color="${colors[0]}"`;
|
|
33
|
-
// Remplacer les paths existants pour utiliser currentColor
|
|
34
|
-
svgContent = svgContent.replace(
|
|
35
|
-
/<path([^>]*?)>/g,
|
|
36
|
-
'<path$1 fill="currentColor">',
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Remplacer la balise <svg> ouvrante pour :
|
|
41
|
-
// 1. Supprimer width/height existants
|
|
42
|
-
// 2. Ajouter width="100%" height="100%"
|
|
43
|
-
// 3. Ajouter les attributs de couleur si nécessaire
|
|
44
|
-
svgContent = svgContent.replace(/<svg([^>]*)>/, (_, attributes) => {
|
|
45
|
-
// Supprime width="..." ou height="..." (avec guillemets simples ou doubles)
|
|
46
|
-
const cleanAttrs = attributes.replace(
|
|
47
|
-
/\s+(width|height)=["'][^"']*["']/g,
|
|
48
|
-
'',
|
|
49
|
-
);
|
|
50
|
-
return `<svg${cleanAttrs} width="100%" height="100%"${colorAttrs}>`;
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
return (
|
|
54
|
-
<div
|
|
55
|
-
className={classNames(
|
|
56
|
-
'size-5 box-content inline-flex fill-current',
|
|
57
|
-
className,
|
|
58
|
-
)}
|
|
59
|
-
style={{ color: colors[0] || '' }}
|
|
60
|
-
dangerouslySetInnerHTML={{ __html: svgContent }}
|
|
61
|
-
/>
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Si c'est un objet SVG importé (cas précédent)
|
|
66
|
-
if (icon && typeof icon === 'object' && 'src' in icon) {
|
|
67
|
-
const svgImport = icon as SvgImport;
|
|
68
|
-
return (
|
|
69
|
-
<img
|
|
70
|
-
src={svgImport.src}
|
|
71
|
-
width={svgImport.width}
|
|
72
|
-
height={svgImport.height}
|
|
73
|
-
className={classNames('size-5 box-content', className)}
|
|
74
|
-
style={{
|
|
75
|
-
filter: colors[0]
|
|
76
|
-
? `brightness(0) saturate(100%) invert(1)`
|
|
77
|
-
: undefined,
|
|
78
|
-
}}
|
|
79
|
-
alt=""
|
|
80
|
-
aria-hidden="true"
|
|
81
|
-
/>
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Si c'est une IconDefinition FontAwesome
|
|
86
|
-
const faIcon = icon as IconDefinition;
|
|
87
|
-
if (!faIcon?.prefix) {
|
|
88
|
-
throw new Error(`Invalid icon type: ${typeof icon}`);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const { icon: iconData } = faIcon;
|
|
92
|
-
const [width, height, , , svgPathData] = iconData || [];
|
|
93
|
-
|
|
94
|
-
const getColorStyle = (colors: string[]): React.CSSProperties => {
|
|
95
|
-
switch (colors.length) {
|
|
96
|
-
case 2:
|
|
97
|
-
return {
|
|
98
|
-
'--fa-primary-color': colors[0] || 'inherit',
|
|
99
|
-
'--fa-secondary-color': colors[1] || 'inherit',
|
|
100
|
-
} as React.CSSProperties;
|
|
101
|
-
case 1:
|
|
102
|
-
return { color: colors[0] } as React.CSSProperties;
|
|
103
|
-
default:
|
|
104
|
-
return {};
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
return (
|
|
109
|
-
<svg
|
|
110
|
-
className={classNames('size-5 box-content', className)}
|
|
111
|
-
style={{ ...getColorStyle(colors) }}
|
|
112
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
113
|
-
viewBox={`0 0 ${width} ${height}`}
|
|
114
|
-
role="img"
|
|
115
|
-
aria-hidden="true"
|
|
116
|
-
{...restProps}
|
|
117
|
-
>
|
|
118
|
-
{typeof svgPathData === 'string' ? (
|
|
119
|
-
<path className={'fill-current'} d={svgPathData} />
|
|
120
|
-
) : (
|
|
121
|
-
svgPathData.map((d, index) => <path key={index} d={d} />)
|
|
122
|
-
)}
|
|
123
|
-
</svg>
|
|
124
|
-
);
|
|
125
|
-
};
|
package/src/lib/icon/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './icon';
|
package/src/lib/index.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { ActionOrLink } from '../utils';
|
|
2
|
-
import { Transition } from 'motion';
|
|
3
|
-
import { Icon } from '../icon';
|
|
4
|
-
|
|
5
|
-
type ButtonVariant = 'filled' | 'elevated' | 'tonal' | 'outlined' | 'text';
|
|
6
|
-
type ButtonVariantAlias = 'primary' | 'secondary';
|
|
7
|
-
|
|
8
|
-
type Props = {
|
|
9
|
-
/**
|
|
10
|
-
* The label is the text that is displayed on the button.
|
|
11
|
-
*/
|
|
12
|
-
label?: string;
|
|
13
|
-
|
|
14
|
-
children?: string;
|
|
15
|
-
|
|
16
|
-
size?: 'xSmall' | 'small' | 'medium' | 'large' | 'xLarge';
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* The button variant determines the style of the button.
|
|
20
|
-
* Aliases: 'primary' maps to 'filled', 'secondary' maps to 'tonal'
|
|
21
|
-
*/
|
|
22
|
-
variant?: ButtonVariant | ButtonVariantAlias;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Disables the button if set to true.
|
|
26
|
-
*/
|
|
27
|
-
disabled?: boolean;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Controls whether negative margins are applied to text variant buttons.
|
|
31
|
-
* When true, removes the default negative horizontal margins.
|
|
32
|
-
* Only applies to 'text' variant buttons.
|
|
33
|
-
*/
|
|
34
|
-
disableTextMargins?: boolean;
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* An optional icon to display in the button.
|
|
38
|
-
*/
|
|
39
|
-
icon?: Icon;
|
|
40
|
-
|
|
41
|
-
iconPosition?: 'left' | 'right';
|
|
42
|
-
|
|
43
|
-
loading?: boolean;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* The shape of the button defines whether it is squared or rounded.
|
|
47
|
-
*/
|
|
48
|
-
shape?: 'squared' | 'rounded';
|
|
49
|
-
|
|
50
|
-
allowShapeTransformation?: boolean;
|
|
51
|
-
|
|
52
|
-
transition?: Transition;
|
|
53
|
-
|
|
54
|
-
onToggle?: (isActive: boolean) => void;
|
|
55
|
-
activated?: boolean;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
type Elements = ['button', 'touchTarget', 'stateLayer', 'icon', 'label'];
|
|
59
|
-
|
|
60
|
-
export type ButtonInterface = ActionOrLink<Props> & {
|
|
61
|
-
elements: Elements;
|
|
62
|
-
states: {
|
|
63
|
-
isActive: boolean;
|
|
64
|
-
};
|
|
65
|
-
};
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { ReactElement } from 'react';
|
|
2
|
-
import { CarouselItem } from '../components';
|
|
3
|
-
|
|
4
|
-
export interface CarouselMetrics {
|
|
5
|
-
total: number;
|
|
6
|
-
selectedIndex: number;
|
|
7
|
-
visibleApprox: number; // fractional approximate number of visible items
|
|
8
|
-
visibleFull: number; // floored count of fully visible-width items
|
|
9
|
-
stepHalf: number; // suggested step = half of visibleFull (>=1)
|
|
10
|
-
canPrev: boolean;
|
|
11
|
-
canNext: boolean;
|
|
12
|
-
scrollProgress: number; // 0..1 (smoothed)
|
|
13
|
-
viewportWidth: number;
|
|
14
|
-
itemMaxWidth: number;
|
|
15
|
-
gap: number;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface CarouselInterface {
|
|
19
|
-
type: 'div';
|
|
20
|
-
props: {
|
|
21
|
-
children?: ReactElement<typeof CarouselItem>[];
|
|
22
|
-
marginPourcent?: number;
|
|
23
|
-
onChange?: (index: number) => void;
|
|
24
|
-
/**
|
|
25
|
-
* Receive live metrics to better control the carousel externally
|
|
26
|
-
*/
|
|
27
|
-
onMetricsChange?: (metrics: CarouselMetrics) => void;
|
|
28
|
-
index?: number; // Controlled index for programmatic centering
|
|
29
|
-
variant?:
|
|
30
|
-
| 'hero'
|
|
31
|
-
| 'center-aligned'
|
|
32
|
-
| 'multi-browse'
|
|
33
|
-
| 'un-contained'
|
|
34
|
-
| 'full-screen';
|
|
35
|
-
scrollSensitivity?: number;
|
|
36
|
-
gap?: number;
|
|
37
|
-
inputRange?: [number, number];
|
|
38
|
-
outputRange?: [number, number];
|
|
39
|
-
};
|
|
40
|
-
elements: ['carousel', 'track'];
|
|
41
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
type Props = {
|
|
4
|
-
checked?: boolean;
|
|
5
|
-
defaultChecked?: boolean;
|
|
6
|
-
indeterminate?: boolean;
|
|
7
|
-
disabled?: boolean;
|
|
8
|
-
error?: boolean;
|
|
9
|
-
onChange?: React.ChangeEventHandler<HTMLInputElement>;
|
|
10
|
-
name?: string;
|
|
11
|
-
id?: string;
|
|
12
|
-
value?: string;
|
|
13
|
-
style?: React.CSSProperties;
|
|
14
|
-
className?: string;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export type CheckboxStates = {
|
|
18
|
-
isChecked: boolean;
|
|
19
|
-
isIndeterminate: boolean;
|
|
20
|
-
isDisabled: boolean;
|
|
21
|
-
isError: boolean;
|
|
22
|
-
isFocused: boolean;
|
|
23
|
-
isHovered: boolean;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export interface CheckboxInterface {
|
|
27
|
-
type: 'div';
|
|
28
|
-
props: Props;
|
|
29
|
-
states: CheckboxStates;
|
|
30
|
-
elements: [
|
|
31
|
-
'checkbox',
|
|
32
|
-
'input',
|
|
33
|
-
'container',
|
|
34
|
-
'box',
|
|
35
|
-
'icon',
|
|
36
|
-
'stateLayer',
|
|
37
|
-
'ripple',
|
|
38
|
-
];
|
|
39
|
-
}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { ActionOrLink } from '../utils';
|
|
2
|
-
import { Transition } from 'motion';
|
|
3
|
-
import { Icon } from '../icon';
|
|
4
|
-
|
|
5
|
-
type ChipVariant = 'outlined' | 'elevated';
|
|
6
|
-
|
|
7
|
-
export type ChipProps = {
|
|
8
|
-
/**
|
|
9
|
-
* The label is the text that is displayed on the chip.
|
|
10
|
-
*/
|
|
11
|
-
label?: string;
|
|
12
|
-
|
|
13
|
-
children?: string;
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* The chip variant determines the style.
|
|
17
|
-
*/
|
|
18
|
-
variant?: ChipVariant;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Disables the chip if set to true.
|
|
22
|
-
*/
|
|
23
|
-
disabled?: boolean;
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* An optional icon to display in the chip.
|
|
27
|
-
*/
|
|
28
|
-
icon?: Icon;
|
|
29
|
-
|
|
30
|
-
transition?: Transition;
|
|
31
|
-
|
|
32
|
-
onToggle?: (isActive: boolean) => void;
|
|
33
|
-
|
|
34
|
-
activated?: boolean;
|
|
35
|
-
|
|
36
|
-
onRemove?: () => void;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Enable native HTML drag and drop on the chip.
|
|
40
|
-
*/
|
|
41
|
-
draggable?: boolean;
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Called when drag starts (composed with internal handler that sets isDragging).
|
|
45
|
-
*/
|
|
46
|
-
onDragStart?: (e: React.DragEvent) => void;
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Called when drag ends (composed with internal handler that clears isDragging).
|
|
50
|
-
*/
|
|
51
|
-
onDragEnd?: (e: React.DragEvent) => void;
|
|
52
|
-
} & (
|
|
53
|
-
| {
|
|
54
|
-
editable?: false;
|
|
55
|
-
editing?: never;
|
|
56
|
-
onEditStart?: never;
|
|
57
|
-
onEditCommit: never;
|
|
58
|
-
onEditCancel?: never;
|
|
59
|
-
onChange?: never;
|
|
60
|
-
}
|
|
61
|
-
| {
|
|
62
|
-
/** Enable label inline edition for this chip (used by Chips variant="input"). */
|
|
63
|
-
editable?: true;
|
|
64
|
-
|
|
65
|
-
/** Affirms that the chip is currently being edited. */
|
|
66
|
-
editing?: boolean;
|
|
67
|
-
|
|
68
|
-
/** Request to start editing (e.g., double-click, Enter/F2). */
|
|
69
|
-
onEditStart?: () => void;
|
|
70
|
-
|
|
71
|
-
/** Commit edition with the new label. */
|
|
72
|
-
onEditCommit: (nextLabel: string) => void;
|
|
73
|
-
|
|
74
|
-
/** Cancel edition and restore previous label. */
|
|
75
|
-
onEditCancel?: () => void;
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Fired on each edit keystroke when content changes (only while editing).
|
|
79
|
-
* Useful for live formatting, suggestions, validation, etc.
|
|
80
|
-
*/
|
|
81
|
-
onChange?: (nextLabel: string) => void;
|
|
82
|
-
}
|
|
83
|
-
);
|
|
84
|
-
|
|
85
|
-
type Elements = ['chip', 'stateLayer', 'leadingIcon', 'trailingIcon', 'label'];
|
|
86
|
-
|
|
87
|
-
export type ChipInterface = ActionOrLink<ChipProps> & {
|
|
88
|
-
elements: Elements;
|
|
89
|
-
states: {
|
|
90
|
-
isActive: boolean;
|
|
91
|
-
trailingIcon?: boolean;
|
|
92
|
-
isFocused: boolean;
|
|
93
|
-
isInteractive: boolean;
|
|
94
|
-
isDragging?: boolean;
|
|
95
|
-
isEditing?: boolean;
|
|
96
|
-
};
|
|
97
|
-
};
|