@udixio/ui-react 2.10.12 → 2.10.14

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 (179) hide show
  1. package/dist/index.cjs +3 -3
  2. package/dist/index.js +2696 -2710
  3. package/dist/lib/effects/ThemeProvider.d.ts.map +1 -1
  4. package/dist/theme.worker.js +6633 -0
  5. package/package.json +4 -1
  6. package/.eslintrc.mjs +0 -22
  7. package/.storybook/main.ts +0 -20
  8. package/.storybook/preview.ts +0 -1
  9. package/CHANGELOG.md +0 -1130
  10. package/dist/scrollDriven-AP2yWhzi.js +0 -121
  11. package/postcss.config.mjs +0 -5
  12. package/src/index.css +0 -4
  13. package/src/index.ts +0 -1
  14. package/src/lib/components/AnchorPositioner.tsx +0 -185
  15. package/src/lib/components/Button.tsx +0 -208
  16. package/src/lib/components/Card.tsx +0 -47
  17. package/src/lib/components/Carousel.tsx +0 -437
  18. package/src/lib/components/CarouselItem.tsx +0 -61
  19. package/src/lib/components/Checkbox.tsx +0 -120
  20. package/src/lib/components/Chip.tsx +0 -341
  21. package/src/lib/components/Chips.tsx +0 -331
  22. package/src/lib/components/ContextMenu.tsx +0 -109
  23. package/src/lib/components/DatePicker.tsx +0 -432
  24. package/src/lib/components/Divider.tsx +0 -20
  25. package/src/lib/components/Fab.tsx +0 -127
  26. package/src/lib/components/FabMenu.tsx +0 -239
  27. package/src/lib/components/IconButton.tsx +0 -146
  28. package/src/lib/components/Menu.tsx +0 -88
  29. package/src/lib/components/MenuGroup.tsx +0 -34
  30. package/src/lib/components/MenuHeadline.tsx +0 -9
  31. package/src/lib/components/MenuItem.tsx +0 -215
  32. package/src/lib/components/NavigationRail.tsx +0 -186
  33. package/src/lib/components/NavigationRailItem.tsx +0 -227
  34. package/src/lib/components/ProgressIndicator.tsx +0 -214
  35. package/src/lib/components/SideSheet.tsx +0 -135
  36. package/src/lib/components/Slider.tsx +0 -374
  37. package/src/lib/components/Snackbar.tsx +0 -77
  38. package/src/lib/components/Switch.tsx +0 -107
  39. package/src/lib/components/Tab.tsx +0 -123
  40. package/src/lib/components/TabGroup.tsx +0 -66
  41. package/src/lib/components/TabGroupContext.tsx +0 -16
  42. package/src/lib/components/TabPanel.tsx +0 -27
  43. package/src/lib/components/TabPanels.tsx +0 -76
  44. package/src/lib/components/Tabs.tsx +0 -105
  45. package/src/lib/components/TextField.tsx +0 -586
  46. package/src/lib/components/Tooltip.tsx +0 -217
  47. package/src/lib/components/index.ts +0 -34
  48. package/src/lib/config/config.interface.ts +0 -9
  49. package/src/lib/config/define-config.ts +0 -16
  50. package/src/lib/config/index.ts +0 -2
  51. package/src/lib/effects/AnimateOnScroll.ts +0 -391
  52. package/src/lib/effects/State.tsx +0 -90
  53. package/src/lib/effects/SyncedFixedWrapper.tsx +0 -62
  54. package/src/lib/effects/ThemeProvider.tsx +0 -172
  55. package/src/lib/effects/block-scroll.effect.tsx +0 -313
  56. package/src/lib/effects/custom-scroll/custom-scroll.effect.tsx +0 -407
  57. package/src/lib/effects/custom-scroll/custom-scroll.interface.ts +0 -29
  58. package/src/lib/effects/custom-scroll/custom-scroll.style.ts +0 -32
  59. package/src/lib/effects/custom-scroll/index.ts +0 -3
  60. package/src/lib/effects/index.ts +0 -7
  61. package/src/lib/effects/ripple/RippleEffect.tsx +0 -116
  62. package/src/lib/effects/ripple/index.tsx +0 -1
  63. package/src/lib/effects/scrollDriven.ts +0 -239
  64. package/src/lib/effects/smooth-scroll.effect.tsx +0 -112
  65. package/src/lib/effects/theme.worker.ts +0 -97
  66. package/src/lib/hooks/index.ts +0 -10
  67. package/src/lib/hooks/useTooltipTrigger.ts +0 -270
  68. package/src/lib/icon/icon.tsx +0 -125
  69. package/src/lib/icon/index.ts +0 -1
  70. package/src/lib/index.ts +0 -8
  71. package/src/lib/interfaces/button.interface.ts +0 -65
  72. package/src/lib/interfaces/card.interface.ts +0 -11
  73. package/src/lib/interfaces/carousel-item.interface.ts +0 -12
  74. package/src/lib/interfaces/carousel.interface.ts +0 -41
  75. package/src/lib/interfaces/checkbox.interface.ts +0 -39
  76. package/src/lib/interfaces/chip.interface.ts +0 -97
  77. package/src/lib/interfaces/chips.interface.ts +0 -37
  78. package/src/lib/interfaces/date-picker.interface.ts +0 -79
  79. package/src/lib/interfaces/divider.interface.ts +0 -7
  80. package/src/lib/interfaces/fab-menu.interface.ts +0 -12
  81. package/src/lib/interfaces/fab.interface.ts +0 -27
  82. package/src/lib/interfaces/icon-button.interface.ts +0 -38
  83. package/src/lib/interfaces/index.ts +0 -26
  84. package/src/lib/interfaces/menu-group.interface.ts +0 -13
  85. package/src/lib/interfaces/menu-item.interface.ts +0 -29
  86. package/src/lib/interfaces/menu.interface.ts +0 -19
  87. package/src/lib/interfaces/navigation-rail-item.interface.ts +0 -39
  88. package/src/lib/interfaces/navigation-rail.interface.ts +0 -39
  89. package/src/lib/interfaces/progress-indicator.interface.ts +0 -41
  90. package/src/lib/interfaces/side-sheet.interface.tsx +0 -28
  91. package/src/lib/interfaces/slider.interface.ts +0 -27
  92. package/src/lib/interfaces/snackbar.interface.ts +0 -13
  93. package/src/lib/interfaces/switch.interface.ts +0 -14
  94. package/src/lib/interfaces/tab-group.interface.ts +0 -13
  95. package/src/lib/interfaces/tab-panels.interface.ts +0 -21
  96. package/src/lib/interfaces/tab.interface.ts +0 -31
  97. package/src/lib/interfaces/tabs.interface.ts +0 -22
  98. package/src/lib/interfaces/text-field.interface.ts +0 -61
  99. package/src/lib/interfaces/tooltip.interface.ts +0 -61
  100. package/src/lib/styles/button.style.ts +0 -136
  101. package/src/lib/styles/card.style.ts +0 -29
  102. package/src/lib/styles/carousel-item.style.ts +0 -24
  103. package/src/lib/styles/carousel.style.ts +0 -22
  104. package/src/lib/styles/checkbox.style.ts +0 -64
  105. package/src/lib/styles/chip.style.ts +0 -62
  106. package/src/lib/styles/chips.style.ts +0 -20
  107. package/src/lib/styles/date-picker.style.ts +0 -43
  108. package/src/lib/styles/divider.style.ts +0 -31
  109. package/src/lib/styles/fab-menu.style.ts +0 -29
  110. package/src/lib/styles/fab.style.ts +0 -49
  111. package/src/lib/styles/icon-button.style.ts +0 -168
  112. package/src/lib/styles/index.ts +0 -25
  113. package/src/lib/styles/menu-group.style.ts +0 -34
  114. package/src/lib/styles/menu-headline.style.ts +0 -20
  115. package/src/lib/styles/menu-item.style.ts +0 -45
  116. package/src/lib/styles/menu.style.ts +0 -32
  117. package/src/lib/styles/navigation-rail-item.style.ts +0 -56
  118. package/src/lib/styles/navigation-rail.style.ts +0 -36
  119. package/src/lib/styles/progress-indicator.style.ts +0 -72
  120. package/src/lib/styles/side-sheet.style.ts +0 -45
  121. package/src/lib/styles/slider.style.ts +0 -41
  122. package/src/lib/styles/snackbar.style.ts +0 -26
  123. package/src/lib/styles/switch.style.ts +0 -67
  124. package/src/lib/styles/tab-panels.style.ts +0 -35
  125. package/src/lib/styles/tab.style.ts +0 -78
  126. package/src/lib/styles/tabs.style.ts +0 -22
  127. package/src/lib/styles/text-field.style.ts +0 -115
  128. package/src/lib/styles/tooltip.style.ts +0 -48
  129. package/src/lib/utils/component-helper.ts +0 -134
  130. package/src/lib/utils/component.ts +0 -34
  131. package/src/lib/utils/index.ts +0 -7
  132. package/src/lib/utils/string.ts +0 -9
  133. package/src/lib/utils/styles/classnames.ts +0 -49
  134. package/src/lib/utils/styles/get-classname.ts +0 -96
  135. package/src/lib/utils/styles/index.ts +0 -4
  136. package/src/lib/utils/styles/use-classnames.ts +0 -25
  137. package/src/stories/action/button.stories.tsx +0 -86
  138. package/src/stories/action/fab.stories.tsx +0 -54
  139. package/src/stories/action/icon-button.stories.tsx +0 -134
  140. package/src/stories/assets/accessibility.png +0 -0
  141. package/src/stories/assets/accessibility.svg +0 -5
  142. package/src/stories/assets/addon-library.png +0 -0
  143. package/src/stories/assets/assets.png +0 -0
  144. package/src/stories/assets/context.png +0 -0
  145. package/src/stories/assets/discord.svg +0 -15
  146. package/src/stories/assets/docs.png +0 -0
  147. package/src/stories/assets/figma-plugin.png +0 -0
  148. package/src/stories/assets/github.svg +0 -3
  149. package/src/stories/assets/share.png +0 -0
  150. package/src/stories/assets/styling.png +0 -0
  151. package/src/stories/assets/testing.png +0 -0
  152. package/src/stories/assets/theming.png +0 -0
  153. package/src/stories/assets/tutorials.svg +0 -12
  154. package/src/stories/assets/youtube.svg +0 -4
  155. package/src/stories/communication/ProgressIndicator.stories.tsx +0 -57
  156. package/src/stories/communication/SnackBar.stories.tsx +0 -32
  157. package/src/stories/communication/tool-tip.stories.tsx +0 -133
  158. package/src/stories/containment/card.stories.tsx +0 -42
  159. package/src/stories/containment/carousel.stories.tsx +0 -65
  160. package/src/stories/containment/divider.stories.tsx +0 -35
  161. package/src/stories/containment/slide-sheet.stories.tsx +0 -45
  162. package/src/stories/effect/smooth-scroll.stories.tsx +0 -54
  163. package/src/stories/navigation/navigation-rail/navigation-rail-item.stories.tsx +0 -65
  164. package/src/stories/navigation/navigation-rail/navigation-rail.stories.tsx +0 -122
  165. package/src/stories/navigation/tabs/tab.stories.tsx +0 -57
  166. package/src/stories/navigation/tabs/tabs.stories.tsx +0 -102
  167. package/src/stories/selection/slider.stories.tsx +0 -85
  168. package/src/stories/selection/switch.stories.tsx +0 -46
  169. package/src/stories/text-inputs/text-field.stories.tsx +0 -135
  170. package/src/tests/Button.spec.tsx +0 -67
  171. package/src/tests/useClassNames.spec.tsx +0 -82
  172. package/src/udixio.css +0 -120
  173. package/theme.config.ts +0 -7
  174. package/tsconfig.json +0 -16
  175. package/tsconfig.lib.json +0 -51
  176. package/tsconfig.spec.json +0 -37
  177. package/tsconfig.storybook.json +0 -38
  178. package/vite.config.ts +0 -82
  179. /package/dist/{scrollDriven-DWAu7CR0.cjs → scrollDriven.js} +0 -0
@@ -1,586 +0,0 @@
1
- import React, { useEffect, useId, useMemo, useRef, useState } from 'react';
2
- import { Icon } from '../icon';
3
- import {
4
- faCalendarDays,
5
- faChevronDown,
6
- faChevronUp,
7
- faCircleExclamation,
8
- } from '@fortawesome/free-solid-svg-icons';
9
- import { motion } from 'motion/react';
10
- import { DatePicker } from './DatePicker';
11
- import { Button } from './Button';
12
- import { Menu } from './Menu';
13
- import { MenuItem } from './MenuItem';
14
- import { Divider } from './Divider';
15
- import { MenuHeadline } from './MenuHeadline';
16
-
17
- import TextareaAutosize from 'react-textarea-autosize';
18
- import { useTextFieldStyle } from '../styles/text-field.style';
19
- import { classNames } from '../utils';
20
- import { ReactProps } from '../utils/component';
21
- import { AnchorPositioner } from './AnchorPositioner';
22
- import { TextFieldInterface } from '../interfaces';
23
-
24
- /**
25
- * Text fields let users enter text into a UI
26
- * @status beta
27
- * @category Input
28
- * @devx
29
- * - Supports controlled (`value`) and uncontrolled (`defaultValue`) usage.
30
- * - `multiline` switches to textarea mode.
31
- * - `type="select" ` switches to select mode with `options`
32
- * @a11y
33
- * - `aria-describedby` links supporting text/error to input.
34
- */
35
- export const TextField = ({
36
- variant = 'filled',
37
- autoFocus,
38
- disabled = false,
39
- errorText,
40
- placeholder,
41
- suffix,
42
- name,
43
- label,
44
- className,
45
- supportingText,
46
- trailingIcon,
47
- leadingIcon,
48
- type = 'text',
49
- multiline = false,
50
- autoComplete = 'on',
51
- onChange,
52
- value: valueProp,
53
- defaultValue,
54
- showSupportingText,
55
- id: idProp,
56
- style,
57
- ref,
58
- onFocus,
59
- onBlur,
60
- options,
61
- children,
62
- ...restProps
63
- }: ReactProps<TextFieldInterface> & { children?: React.ReactNode }) => {
64
- const generatedId = useId();
65
- const id = idProp || generatedId;
66
- const helperTextId = `${id}-helper`;
67
-
68
- const isControlled = valueProp !== undefined;
69
- const [internalValue, setInternalValue] = useState(defaultValue ?? '');
70
- const value = isControlled ? valueProp : internalValue;
71
-
72
- const [isFocused, setIsFocused] = useState(false);
73
- const [showErrorIcon, setShowErrorIcon] = useState(!!errorText?.length);
74
-
75
- const internalRef = useRef<HTMLInputElement | HTMLTextAreaElement>(null);
76
- const inputRef = (ref as any) || internalRef;
77
-
78
- const textFieldRef = useRef<HTMLDivElement>(null);
79
- const calendarTriggerRef = useRef<HTMLDivElement>(null);
80
- const datePickerRef = useRef<HTMLDivElement>(null);
81
-
82
- const hasSupportingText =
83
- showSupportingText ?? (!!errorText?.length || !!supportingText?.length);
84
-
85
- useEffect(() => {
86
- setShowErrorIcon(!!errorText?.length);
87
- }, [errorText]);
88
-
89
- const focusInput = () => {
90
- if (inputRef.current && !isFocused && !disabled) {
91
- if (type !== 'select') {
92
- inputRef.current.focus();
93
- }
94
- }
95
- };
96
-
97
- useEffect(() => {
98
- if (!autoFocus || disabled) return;
99
-
100
- if (type !== 'select') {
101
- const rafId = window.requestAnimationFrame(() => {
102
- focusInput();
103
- });
104
- return () => window.cancelAnimationFrame(rafId);
105
- }
106
- }, [autoFocus, disabled, inputRef, type]);
107
-
108
- useEffect(() => {
109
- if (isFocused) {
110
- setShowErrorIcon(false);
111
- onFocus?.();
112
- } else {
113
- if (errorText?.length) {
114
- setShowErrorIcon(true);
115
- }
116
- onBlur?.();
117
- }
118
- }, [isFocused]);
119
-
120
- const handleChange = (
121
- event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
122
- ) => {
123
- const newValue = event.target.value;
124
-
125
- if (!isControlled) {
126
- setInternalValue(newValue);
127
- }
128
-
129
- setShowErrorIcon(false);
130
-
131
- if (onChange) {
132
- onChange(event);
133
- }
134
- };
135
-
136
- // Date Picker Logic
137
- const isDateInput = type === 'date';
138
- const [showDatePicker, setShowDatePicker] = useState(false);
139
- const [tempDate, setTempDate] = useState<Date | null>(null);
140
-
141
- const initialDateValue = useMemo(() => {
142
- const val = String(value);
143
- if (!val) return null;
144
- const [y, m, d] = val.split('-').map(Number);
145
- if (y && m && d) return new Date(y, m - 1, d);
146
- return null;
147
- }, [value]);
148
-
149
- const handleDatePickerToggle = () => {
150
- if (disabled) return;
151
- if (showDatePicker) {
152
- setShowDatePicker(false);
153
- } else {
154
- setTempDate(initialDateValue);
155
- setShowDatePicker(true);
156
- }
157
- };
158
-
159
- useEffect(() => {
160
- if (showDatePicker) {
161
- setIsFocused(true);
162
- } else if (!isSelectInput || !showMenu) {
163
- setIsFocused(false);
164
- }
165
- }, [showDatePicker]);
166
-
167
- useEffect(() => {
168
- if (!showDatePicker) return;
169
-
170
- const isInside = (target: Node | null) => {
171
- if (!target) return false;
172
- return (
173
- textFieldRef.current?.contains(target) ||
174
- datePickerRef.current?.contains(target)
175
- );
176
- };
177
-
178
- const handlePointerDown = (e: PointerEvent) => {
179
- const target = e.target as Node;
180
- const inDatePicker = datePickerRef.current?.contains(target);
181
- const inCalendarTrigger = calendarTriggerRef.current?.contains(target);
182
- if (!inDatePicker && !inCalendarTrigger) {
183
- setShowDatePicker(false);
184
- }
185
- };
186
-
187
- const handleFocusIn = (e: FocusEvent) => {
188
- if (!isInside(e.target as Node)) {
189
- setShowDatePicker(false);
190
- }
191
- };
192
-
193
- const handleKeyDown = (e: KeyboardEvent) => {
194
- if (e.key === 'Escape') {
195
- setShowDatePicker(false);
196
- }
197
- };
198
-
199
- document.addEventListener('pointerdown', handlePointerDown);
200
- document.addEventListener('focusin', handleFocusIn);
201
- document.addEventListener('keydown', handleKeyDown);
202
-
203
- return () => {
204
- document.removeEventListener('pointerdown', handlePointerDown);
205
- document.removeEventListener('focusin', handleFocusIn);
206
- document.removeEventListener('keydown', handleKeyDown);
207
- };
208
- }, [showDatePicker]);
209
-
210
- const handleDateConfirm = () => {
211
- const newValue = tempDate ? tempDate.toLocaleDateString('en-CA') : '';
212
-
213
- if (!isControlled) {
214
- setInternalValue(newValue);
215
- }
216
-
217
- if (onChange) {
218
- const event = {
219
- target: {
220
- value: newValue,
221
- name,
222
- type,
223
- },
224
- } as React.ChangeEvent<HTMLInputElement>;
225
- onChange(event);
226
- }
227
- setShowDatePicker(false);
228
- };
229
-
230
- // Select Logic
231
- const isSelectInput = type === 'select';
232
- const [showMenu, setShowMenu] = useState(false);
233
- const menuRef = useRef<HTMLDivElement>(null);
234
-
235
- const displayValue = useMemo(() => {
236
- if (isSelectInput && options) {
237
- const selectedOption = options.find(
238
- (o) => String(o.value) === String(value),
239
- );
240
- return selectedOption ? selectedOption.label : value;
241
- }
242
- return value;
243
- }, [value, isSelectInput, options]);
244
-
245
- const handleSelectToggle = () => {
246
- if (disabled) return;
247
- setShowMenu(!showMenu);
248
- setIsFocused(!showMenu);
249
- };
250
-
251
- const handleSelectOption = (optionValue: string | number) => {
252
- if (!isControlled) {
253
- setInternalValue(String(optionValue));
254
- }
255
-
256
- if (onChange) {
257
- const event = {
258
- target: {
259
- value: String(optionValue),
260
- name,
261
- type,
262
- },
263
- } as React.ChangeEvent<HTMLInputElement>;
264
- onChange(event);
265
- }
266
- setShowMenu(false);
267
- setIsFocused(false);
268
- };
269
-
270
- // Close menu on outside click
271
- useEffect(() => {
272
- if (!showMenu) return;
273
- const handleClickOutside = (event: MouseEvent) => {
274
- if (
275
- textFieldRef.current &&
276
- !textFieldRef.current.contains(event.target as Node) &&
277
- menuRef.current &&
278
- !menuRef.current.contains(event.target as Node)
279
- ) {
280
- setShowMenu(false);
281
- setIsFocused(false);
282
- }
283
- };
284
- document.addEventListener('mousedown', handleClickOutside);
285
- return () => {
286
- document.removeEventListener('mousedown', handleClickOutside);
287
- };
288
- }, [showMenu]);
289
-
290
- const effectiveTrailingIcon = useMemo(() => {
291
- if (trailingIcon) return trailingIcon;
292
- if (isDateInput) return faCalendarDays;
293
- if (isSelectInput) return showMenu ? faChevronUp : faChevronDown;
294
- return undefined;
295
- }, [trailingIcon, isDateInput, isSelectInput, showMenu]);
296
-
297
- // Enhance styles for date input or select
298
- const inputSpecialClass =
299
- isDateInput || isSelectInput
300
- ? '[&::-webkit-calendar-picker-indicator]:hidden cursor-pointer selection:bg-transparent'
301
- : '';
302
-
303
- const styles = useTextFieldStyle({
304
- showSupportingText: hasSupportingText,
305
- isFocused,
306
- showErrorIcon,
307
- disabled,
308
- name,
309
- label,
310
- autoComplete,
311
- className,
312
- onChange,
313
- placeholder,
314
- supportingText,
315
- type,
316
- leadingIcon,
317
- trailingIcon: effectiveTrailingIcon,
318
- variant,
319
- errorText,
320
- value: String(displayValue),
321
- suffix,
322
- multiline,
323
- });
324
-
325
- const TextComponent = multiline ? TextareaAutosize : 'input';
326
- // For select, we want the input to be readOnly but still focusable?
327
- // Actually, for better UX, standard select inputs are often readOnly text fields.
328
- const textComponentProps = multiline
329
- ? {}
330
- : {
331
- type: isSelectInput ? 'text' : type,
332
- readOnly: isSelectInput,
333
- };
334
-
335
- const isFloating =
336
- isFocused ||
337
- (typeof value === 'string' && value.length > 0) ||
338
- type == 'date' ||
339
- (isSelectInput && showMenu);
340
-
341
- const showLegend = isFloating && variant === 'outlined';
342
- const showLabel = !showLegend;
343
-
344
- return (
345
- <div ref={textFieldRef} className={styles.textField} style={style}>
346
- <fieldset
347
- onClick={() => {
348
- if (isSelectInput) handleSelectToggle();
349
- else focusInput();
350
- }}
351
- className={styles.content}
352
- role="presentation"
353
- >
354
- <div className={styles.stateLayer}></div>
355
- {leadingIcon && (
356
- <div className={styles.leadingIcon}>
357
- {React.isValidElement(leadingIcon) ? (
358
- leadingIcon
359
- ) : (
360
- <Icon className={'w-5 h-5'} icon={leadingIcon}></Icon>
361
- )}
362
- </div>
363
- )}
364
-
365
- <motion.legend
366
- aria-hidden="true"
367
- variants={{
368
- hidden: { width: 0, padding: 0 },
369
- visible: { width: 'auto', padding: '0 8px' },
370
- }}
371
- initial={showLegend ? 'visible' : 'hidden'}
372
- animate={showLegend ? 'visible' : 'hidden'}
373
- className={
374
- 'max-w-full ml-2 px-2 text-body-small h-0 overflow-hidden whitespace-nowrap'
375
- }
376
- transition={{ duration: 0.2 }}
377
- >
378
- <span className={'transform inline-flex -translate-y-1/2 opacity-0'}>
379
- {label}
380
- </span>
381
- </motion.legend>
382
-
383
- <div className={'flex-1 relative'}>
384
- {showLabel && (
385
- <motion.label
386
- htmlFor={id}
387
- className={classNames(
388
- 'absolute left-4 transition-all duration-300 pointer-events-none',
389
- {
390
- 'text-body-small top-2': variant == 'filled' && isFloating,
391
- 'text-body-large top-1/2 transform -translate-y-1/2': !(
392
- variant == 'filled' && isFloating
393
- ),
394
- },
395
- )}
396
- transition={{ duration: 0.3 }}
397
- layoutId={variant === 'outlined' ? `${id}-label` : undefined}
398
- >
399
- <span className={styles.label}>{label}</span>
400
- </motion.label>
401
- )}
402
-
403
- {showLegend && (
404
- <motion.label
405
- htmlFor={id}
406
- className={classNames(
407
- 'absolute left-2 -top-3 px-1 text-body-small z-10',
408
- styles.label,
409
- )}
410
- layoutId={`${id}-label`}
411
- transition={{ duration: 0.3 }}
412
- >
413
- {label}
414
- </motion.label>
415
- )}
416
-
417
- <TextComponent
418
- {...(restProps as any)}
419
- ref={inputRef as any}
420
- value={displayValue} // Use displayValue for select
421
- onChange={handleChange}
422
- className={classNames(styles.input, inputSpecialClass)}
423
- id={id}
424
- name={name}
425
- placeholder={isFocused ? (placeholder ?? undefined) : ''}
426
- onFocus={() => {
427
- if (!isSelectInput) setIsFocused(true);
428
- }}
429
- onBlur={() => {
430
- // For select, we manage focus manually with menu state usually
431
- if (!isSelectInput) setIsFocused(false);
432
- }}
433
- disabled={disabled}
434
- autoComplete={autoComplete}
435
- aria-invalid={!!errorText?.length}
436
- aria-describedby={hasSupportingText ? helperTextId : undefined}
437
- {...textComponentProps}
438
- />
439
- </div>
440
-
441
- <div className={styles.activeIndicator}></div>
442
-
443
- {!showErrorIcon && (
444
- <>
445
- {effectiveTrailingIcon && (
446
- <div
447
- ref={isDateInput ? calendarTriggerRef : undefined}
448
- onClick={(event) => {
449
- event.stopPropagation();
450
- if (isDateInput) handleDatePickerToggle();
451
- if (isSelectInput) handleSelectToggle();
452
- }}
453
- className={classNames(
454
- styles.trailingIcon,
455
- (isDateInput || isSelectInput) && 'cursor-pointer',
456
- )}
457
- >
458
- <div className="flex items-center justify-center w-full h-full">
459
- {React.isValidElement(effectiveTrailingIcon) ? (
460
- effectiveTrailingIcon
461
- ) : (
462
- <Icon
463
- className={'h-5'}
464
- icon={effectiveTrailingIcon as any}
465
- />
466
- )}
467
- </div>
468
- </div>
469
- )}
470
- {!effectiveTrailingIcon && suffix && (
471
- <span className={styles.suffix}>{suffix}</span>
472
- )}
473
- </>
474
- )}
475
-
476
- {showErrorIcon && (
477
- <div
478
- className={classNames(styles.trailingIcon, {
479
- ' absolute right-0': !effectiveTrailingIcon,
480
- })}
481
- >
482
- <Icon
483
- className={'h-5 text-error'}
484
- icon={faCircleExclamation}
485
- ></Icon>
486
- </div>
487
- )}
488
- </fieldset>
489
-
490
- {hasSupportingText && (
491
- <p className={styles.supportingText} id={helperTextId}>
492
- {errorText?.length
493
- ? errorText
494
- : supportingText?.length
495
- ? supportingText
496
- : '\u00A0'}
497
- </p>
498
- )}
499
-
500
- {isDateInput && showDatePicker && (
501
- <>
502
- <AnchorPositioner anchorRef={textFieldRef} position="bottom">
503
- <div
504
- ref={datePickerRef}
505
- className="z-50 shadow-xl rounded-[28px] bg-surface-container-high overflow-hidden"
506
- >
507
- <DatePicker
508
- className={''}
509
- value={tempDate}
510
- onChange={setTempDate}
511
- />
512
- <div className="flex justify-end gap-2 p-4 pt-0">
513
- <Button
514
- variant="text"
515
- size="small"
516
- onClick={() => setShowDatePicker(false)}
517
- >
518
- Cancel
519
- </Button>
520
- <Button
521
- variant="filled"
522
- size="small"
523
- onClick={handleDateConfirm}
524
- >
525
- OK
526
- </Button>
527
- </div>
528
- </div>
529
- </AnchorPositioner>
530
- </>
531
- )}
532
-
533
- {isSelectInput && showMenu && (
534
- <AnchorPositioner
535
- anchorRef={textFieldRef}
536
- position="bottom"
537
- style={{ width: textFieldRef.current?.offsetWidth }}
538
- >
539
- <div ref={menuRef}>
540
- <Menu className={'max-w-full'} selected={value}>
541
- {children
542
- ? React.Children.map(children, (child) => {
543
- if (
544
- React.isValidElement(child) &&
545
- child.type === MenuItem
546
- ) {
547
- return React.cloneElement(child, {
548
- onClick: (e: React.MouseEvent) => {
549
- if (child.props.onClick) {
550
- child.props.onClick(e);
551
- }
552
- handleSelectOption(child.props.value ?? '');
553
- },
554
- } as any);
555
- }
556
- return child;
557
- })
558
- : options?.map((opt, i) => {
559
- if (opt.type === 'divider') {
560
- return <Divider key={i} className="my-1" />;
561
- }
562
- if (opt.type === 'headline') {
563
- return <MenuHeadline key={i} label={opt.label} />;
564
- }
565
- return (
566
- <MenuItem
567
- key={opt.value ?? i}
568
- onClick={(e) => {
569
- if (opt.onClick) {
570
- opt.onClick(e);
571
- }
572
- handleSelectOption(opt.value ?? '');
573
- }}
574
- {...opt}
575
- >
576
- {opt.label}
577
- </MenuItem>
578
- );
579
- })}
580
- </Menu>
581
- </div>
582
- </AnchorPositioner>
583
- )}
584
- </div>
585
- );
586
- };