@dmsi/wedgekit-react 0.0.551 → 0.0.552

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 (137) hide show
  1. package/package.json +2 -3
  2. package/src/brand.css +0 -125
  3. package/src/classNames.ts +0 -174
  4. package/src/components/AccessChangerTabItem.tsx +0 -71
  5. package/src/components/Accordion.tsx +0 -108
  6. package/src/components/Alert.tsx +0 -81
  7. package/src/components/Breadcrumbs.tsx +0 -142
  8. package/src/components/Button.tsx +0 -216
  9. package/src/components/CalendarRange.tsx +0 -628
  10. package/src/components/Caption.tsx +0 -144
  11. package/src/components/Card.tsx +0 -88
  12. package/src/components/Checkbox.tsx +0 -206
  13. package/src/components/CompactImagesPreview.tsx +0 -135
  14. package/src/components/ContentTab.tsx +0 -84
  15. package/src/components/ContentTabs.tsx +0 -136
  16. package/src/components/DMSiLogo.tsx +0 -33
  17. package/src/components/DataGrid/ColumnSelectorHeaderCell/ColumnSelectorMenuOption.tsx +0 -35
  18. package/src/components/DataGrid/ColumnSelectorHeaderCell/index.tsx +0 -74
  19. package/src/components/DataGrid/PinnedColumns.tsx +0 -183
  20. package/src/components/DataGrid/TableBody/LoadingCell.tsx +0 -44
  21. package/src/components/DataGrid/TableBody/TableBodyRow.tsx +0 -157
  22. package/src/components/DataGrid/TableBody/index.tsx +0 -185
  23. package/src/components/DataGrid/index.tsx +0 -756
  24. package/src/components/DataGrid/types.ts +0 -98
  25. package/src/components/DataGrid/utils.tsx +0 -15
  26. package/src/components/DataGridCell.tsx +0 -526
  27. package/src/components/DataTable.tsx +0 -881
  28. package/src/components/DateInput.tsx +0 -306
  29. package/src/components/DateRangeInput.tsx +0 -758
  30. package/src/components/DebugJson.tsx +0 -28
  31. package/src/components/Display.tsx +0 -66
  32. package/src/components/EditingContext.tsx +0 -43
  33. package/src/components/EmptyCartIcon.tsx +0 -18
  34. package/src/components/FilterGroup.tsx +0 -264
  35. package/src/components/FullViewportBox.tsx +0 -19
  36. package/src/components/Grid.tsx +0 -97
  37. package/src/components/Heading.tsx +0 -72
  38. package/src/components/HorizontalDivider.tsx +0 -22
  39. package/src/components/Icon.tsx +0 -39
  40. package/src/components/ImagePlaceholder.tsx +0 -22
  41. package/src/components/Input.tsx +0 -609
  42. package/src/components/InputGroup.tsx +0 -59
  43. package/src/components/Label.tsx +0 -46
  44. package/src/components/Link.tsx +0 -117
  45. package/src/components/List.tsx +0 -18
  46. package/src/components/ListGroup.tsx +0 -82
  47. package/src/components/LiveChatComponent.tsx +0 -56
  48. package/src/components/LoadingScrim.tsx +0 -33
  49. package/src/components/LogoAgilityTopBar.tsx +0 -54
  50. package/src/components/LogoDMSiTopBar.tsx +0 -33
  51. package/src/components/LogoMillworkTopBar.tsx +0 -119
  52. package/src/components/MainBar.tsx +0 -91
  53. package/src/components/MaxViewportBox.tsx +0 -19
  54. package/src/components/Menu.tsx +0 -316
  55. package/src/components/MenuOption.tsx +0 -330
  56. package/src/components/MobileDataGrid/ColumnList.tsx +0 -66
  57. package/src/components/MobileDataGrid/ColumnSelector/index.tsx +0 -97
  58. package/src/components/MobileDataGrid/GridContextProvider/GridContext.tsx +0 -25
  59. package/src/components/MobileDataGrid/GridContextProvider/index.tsx +0 -132
  60. package/src/components/MobileDataGrid/GridContextProvider/useGridContext.ts +0 -10
  61. package/src/components/MobileDataGrid/MobileDataGridCard/MobileDataGridColumn.tsx +0 -27
  62. package/src/components/MobileDataGrid/MobileDataGridCard/index.tsx +0 -138
  63. package/src/components/MobileDataGrid/MobileDataGridHeader.tsx +0 -81
  64. package/src/components/MobileDataGrid/RowDetailModalProvider/ModalContent.tsx +0 -42
  65. package/src/components/MobileDataGrid/RowDetailModalProvider/index.tsx +0 -68
  66. package/src/components/MobileDataGrid/dataGridReducer.ts +0 -55
  67. package/src/components/MobileDataGrid/index.tsx +0 -92
  68. package/src/components/MobileDataGrid/types.ts +0 -4
  69. package/src/components/Modal.tsx +0 -312
  70. package/src/components/ModalButtons.tsx +0 -62
  71. package/src/components/ModalContent.tsx +0 -31
  72. package/src/components/ModalHeader.tsx +0 -78
  73. package/src/components/ModalScrim.tsx +0 -42
  74. package/src/components/NavigationTab.tsx +0 -95
  75. package/src/components/NavigationTabs.tsx +0 -70
  76. package/src/components/NestedMenu.tsx +0 -131
  77. package/src/components/Notification.tsx +0 -128
  78. package/src/components/OptionPill.tsx +0 -139
  79. package/src/components/OrderCheckIcon.tsx +0 -19
  80. package/src/components/PDFViewer/DownloadIcon.tsx +0 -25
  81. package/src/components/PDFViewer/PDFElement.tsx +0 -90
  82. package/src/components/PDFViewer/PDFNavigation.tsx +0 -68
  83. package/src/components/PDFViewer/PDFPage.tsx +0 -34
  84. package/src/components/PDFViewer/index.tsx +0 -128
  85. package/src/components/Pagination.tsx +0 -182
  86. package/src/components/Paragraph.tsx +0 -55
  87. package/src/components/Password.tsx +0 -62
  88. package/src/components/ProductImagePreview/CarouselPagination.tsx +0 -54
  89. package/src/components/ProductImagePreview/MobileImageCarousel.tsx +0 -226
  90. package/src/components/ProductImagePreview/ProductPrimaryImage.tsx +0 -219
  91. package/src/components/ProductImagePreview/Thumbnail.tsx +0 -55
  92. package/src/components/ProductImagePreview/ZoomWindow.tsx +0 -136
  93. package/src/components/ProductImagePreview/index.tsx +0 -182
  94. package/src/components/ProductImagePreview/useProductImagePreview.ts +0 -211
  95. package/src/components/ProjectBar.tsx +0 -82
  96. package/src/components/Radio.tsx +0 -146
  97. package/src/components/Search.tsx +0 -152
  98. package/src/components/SearchResultImage/index.tsx +0 -39
  99. package/src/components/Select.tsx +0 -114
  100. package/src/components/SideMenu.tsx +0 -30
  101. package/src/components/SideMenuGroup.tsx +0 -95
  102. package/src/components/SideMenuItem.tsx +0 -109
  103. package/src/components/SimpleTable.tsx +0 -77
  104. package/src/components/SkeletonParagraph.tsx +0 -31
  105. package/src/components/Spinner.tsx +0 -32
  106. package/src/components/Stack.tsx +0 -347
  107. package/src/components/StatusPill.tsx +0 -59
  108. package/src/components/Stepper.tsx +0 -128
  109. package/src/components/Subheader.tsx +0 -50
  110. package/src/components/Surface.tsx +0 -37
  111. package/src/components/Swatch.tsx +0 -1341
  112. package/src/components/Textarea.tsx +0 -102
  113. package/src/components/Theme.tsx +0 -27
  114. package/src/components/Time.tsx +0 -460
  115. package/src/components/Toast.tsx +0 -268
  116. package/src/components/Tooltip.tsx +0 -159
  117. package/src/components/TopBar.tsx +0 -139
  118. package/src/components/Upload.tsx +0 -107
  119. package/src/components/WorldpayIframe.tsx +0 -7
  120. package/src/components/index.ts +0 -34
  121. package/src/components/useMenuSystem.tsx +0 -456
  122. package/src/components/useMounted.tsx +0 -14
  123. package/src/darkmode.css +0 -278
  124. package/src/fonts.css +0 -23
  125. package/src/hooks/index.ts +0 -4
  126. package/src/hooks/useInfiniteScroll.tsx +0 -40
  127. package/src/hooks/useKeydown.ts +0 -42
  128. package/src/hooks/useMatchesMedia.ts +0 -18
  129. package/src/hooks/useTableLayout.ts +0 -106
  130. package/src/index.css +0 -800
  131. package/src/index.tsx +0 -5
  132. package/src/types.ts +0 -150
  133. package/src/utils/date.ts +0 -236
  134. package/src/utils/formatting.tsx +0 -81
  135. package/src/utils/index.ts +0 -4
  136. package/src/utils/mergeObjectArrays.ts +0 -18
  137. package/src/utils.ts +0 -24
@@ -1,609 +0,0 @@
1
- "use client";
2
- import {
3
- ComponentProps,
4
- ReactNode,
5
- RefObject,
6
- useEffect,
7
- useRef,
8
- useState,
9
- } from "react";
10
-
11
- import clsx from "clsx";
12
- import {
13
- baseTransition,
14
- componentGap,
15
- componentPaddingMinusBorder,
16
- componentPaddingXUsingComponentGap,
17
- componentPaddingMinusBorderDesktop,
18
- typography,
19
- } from "../classNames";
20
- import { Label } from "./Label";
21
- import { Icon } from "./Icon";
22
- import {
23
- getDecimalPlaceholder,
24
- formatDecimalValue,
25
- formatCurrencyDisplay,
26
- } from "../utils/formatting";
27
- import { TextAlign } from "../types";
28
- import { Paragraph } from "./Paragraph";
29
-
30
- export type InputVariant =
31
- | "default"
32
- | "search"
33
- | "finder"
34
- | "currency"
35
- | "percentage"
36
- | "uom";
37
-
38
- export type InputFormatting = {
39
- variant?: InputVariant;
40
- decimals?: number;
41
- uom?: string;
42
- removeSearchIcon?: boolean;
43
- };
44
-
45
- export type InputBaseProps = {
46
- id?: string;
47
- testid?: string;
48
- after?: ReactNode;
49
- before?: ReactNode;
50
- rightAdornment?: ReactNode;
51
- label?: string;
52
- error?: boolean;
53
- align?: TextAlign;
54
- caption?: ReactNode;
55
- required?: boolean;
56
- selectOnFocus?: boolean;
57
- inputContainerRef?: RefObject<HTMLLabelElement | null>;
58
- removeRoundness?: boolean;
59
- removeBorder?: boolean;
60
- wrapperClassName?: string;
61
- focus?: boolean;
62
- secondaryIconColor?: boolean;
63
- fullWidth?: boolean; // If true, input takes full width of the container
64
- autocompletePadding?: boolean; // If true, applies padding suitable for autocomplete dropdowns
65
- wrapperRef?: RefObject<HTMLDivElement | null>;
66
- } & InputFormatting &
67
- Omit<ComponentProps<"input">, "align" | "id">;
68
-
69
- export const InputBase = ({
70
- id,
71
- testid,
72
- before,
73
- after,
74
- rightAdornment,
75
- type,
76
- label,
77
- error,
78
- className,
79
- align = "left",
80
- caption,
81
- required,
82
- selectOnFocus,
83
- removeRoundness,
84
- inputContainerRef,
85
- removeBorder,
86
- wrapperClassName,
87
- focus,
88
- secondaryIconColor,
89
- fullWidth = true,
90
- width,
91
- wrapperRef,
92
- autocompletePadding = false,
93
- ...props
94
- }: InputBaseProps) => {
95
- const attributes = {
96
- "data-error": (error && !focus) || null,
97
- "data-focus": focus || null,
98
- };
99
- const inputRef = useRef<HTMLInputElement | null>(null);
100
- const inputId = id ? `${id}-input` : undefined;
101
-
102
- useEffect(() => {
103
- const input = inputRef.current;
104
- const focusHandler = () => {
105
- input?.select();
106
- };
107
- if (selectOnFocus) {
108
- inputRef.current?.addEventListener("focus", focusHandler);
109
-
110
- return () => {
111
- input?.removeEventListener("focus", focusHandler);
112
- };
113
- }
114
- }, [selectOnFocus]);
115
-
116
- const inputBaseClass = clsx(
117
- fullWidth ? "w-full" : "w-fit",
118
- "flex flex-row items-center",
119
- "bg-background-action-secondary-normal caret-icon-on-action-secondary-normal",
120
- componentGap,
121
- baseTransition,
122
- "outline-transparent outline-2 -outline-offset-2",
123
- !autocompletePadding && componentPaddingMinusBorder,
124
- autocompletePadding && componentPaddingMinusBorderDesktop,
125
- !removeRoundness && "rounded-base",
126
- !removeBorder && "border border-border-primary-normal",
127
- "relative",
128
- );
129
-
130
- const inputFocusClass = clsx(
131
- "has-[[data-focus]]:border-transparent has-[[data-focus]]:outline-border-primary-focus focus-within:border-transparent focus-within:outline-border-primary-focus",
132
- );
133
-
134
- const inputDisabledClass = clsx(
135
- "has-disabled:bg-background-action-secondary-disabled",
136
- );
137
-
138
- const inputReadOnlyClass = clsx(
139
- "has-[input:not(:disabled):read-only]:outline-none has-[input:not(:disabled):read-only]:bg-transparent has-[input:not(:disabled):read-only]:border-transparent has-[input:not(:disabled):read-only]:pl-0",
140
- );
141
-
142
- const inputInvalidClass = clsx(
143
- "has-[[data-error]]:border-transparent has-[[data-error]]:not-focus-within:outline-border-primary-error has-[[data-error]]:not-focus-within:outline-1",
144
- );
145
-
146
- return (
147
- <label
148
- id={id}
149
- data-testid={testid}
150
- htmlFor={inputId}
151
- ref={inputContainerRef}
152
- className={clsx(
153
- "w-full flex flex-col",
154
- "block",
155
- "text-text-primary-normal has-disabled:text-text-primary-disabled",
156
- componentGap,
157
- )}
158
- style={{
159
- ...props.style,
160
- }}
161
- >
162
- {label && (
163
- <div className={clsx("flex items-center", componentGap)}>
164
- <Label
165
- id={id ? `${id}-label` : undefined}
166
- color={error ? "text-primary-error" : undefined}
167
- className={clsx(
168
- props.disabled || props.readOnly
169
- ? "cursor-default"
170
- : "cursor-pointer",
171
- )}
172
- >
173
- {label}
174
- </Label>
175
-
176
- {required && (
177
- <span
178
- className={clsx(typography.label, "text-text-critical-normal")}
179
- >
180
- *
181
- </span>
182
- )}
183
- </div>
184
- )}
185
-
186
- <div
187
- className={clsx(
188
- inputBaseClass,
189
- !props.disabled && inputInvalidClass,
190
- inputFocusClass,
191
- inputDisabledClass,
192
- inputReadOnlyClass,
193
- wrapperClassName,
194
- )}
195
- ref={(el) => {
196
- if (wrapperRef) {
197
- wrapperRef.current = el;
198
- }
199
- }}
200
- >
201
- {before}
202
-
203
- <input
204
- ref={(el) => {
205
- inputRef.current = el;
206
- }}
207
- type={type}
208
- required={required}
209
- {...props}
210
- {...attributes}
211
- id={inputId}
212
- data-testid={testid ? `${testid}-input` : undefined}
213
- className={clsx(
214
- "flex-1 outline-none w-full max-w-full min-h-6 min-w-0",
215
- "[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
216
- "placeholder:text-text-secondary-normal disabled:text-text-secondary-disabled",
217
- align === "right" && "text-right",
218
- align === "center" && "text-center",
219
- componentPaddingXUsingComponentGap,
220
- typography.paragraph,
221
- className,
222
- props.readOnly && !props.disabled && "!px-0",
223
- )}
224
- style={{ ...props.style, width }}
225
- />
226
-
227
- {secondaryIconColor ? (
228
- <span className="contents text-text-secondary-normal">{after}</span>
229
- ) : (
230
- after
231
- )}
232
- {rightAdornment}
233
- </div>
234
-
235
- {caption && (
236
- <div
237
- id={id ? `${id}-caption` : undefined}
238
- data-testid={testid ? `${testid}-caption` : undefined}
239
- >
240
- {caption}
241
- </div>
242
- )}
243
- </label>
244
- );
245
- };
246
-
247
- export const Input = ({
248
- variant = "default",
249
- decimals,
250
- uom,
251
- removeSearchIcon,
252
- value: propValue,
253
- onChange,
254
- onBlur,
255
- onClear,
256
- id,
257
- testid,
258
- rightAdornment,
259
- ...props
260
- }: Omit<ComponentProps<"input">, "onChange" | "align" | "children"> &
261
- InputBaseProps & {
262
- onChange?: React.ChangeEventHandler<HTMLInputElement>;
263
- onClear?: () => void;
264
- }) => {
265
- const [internalValue, setInternalValue] = useState("");
266
- const [displayValue, setDisplayValue] = useState("");
267
- useEffect(() => {
268
- const stringValue = propValue?.toString() ?? "";
269
- setInternalValue(stringValue);
270
- setDisplayValue(stringValue);
271
- }, [propValue]);
272
-
273
- useEffect(() => {
274
- if (variant !== "currency") {
275
- return;
276
- }
277
-
278
- const stringValue = propValue?.toString() ?? "";
279
-
280
- if (!stringValue) {
281
- return;
282
- }
283
-
284
- const formatted = formatDecimalValue(stringValue, decimals ?? 2);
285
-
286
- setInternalValue(formatted);
287
- setDisplayValue(formatCurrencyDisplay(formatted));
288
- // Intentionally not adding dependencies to avoid formatting on every change
289
- // eslint-disable-next-line react-hooks/exhaustive-deps
290
- }, []);
291
-
292
- const getInputProps = () => {
293
- const baseProps = {
294
- ...props,
295
- id,
296
- ...getDecimalPlaceholder(decimals),
297
- value: propValue,
298
- };
299
-
300
- switch (variant) {
301
- case "search":
302
- return {
303
- ...baseProps,
304
- placeholder: props.placeholder ?? "Search",
305
- className: "!mr-6",
306
- value: displayValue,
307
- };
308
-
309
- case "finder":
310
- return baseProps;
311
-
312
- case "currency":
313
- return {
314
- ...baseProps,
315
- align: "right" as const,
316
- type: "text" as const,
317
- value: displayValue,
318
- };
319
-
320
- case "percentage":
321
- case "uom":
322
- return {
323
- ...baseProps,
324
- type: "number" as const,
325
- align: "right" as const,
326
- };
327
-
328
- default:
329
- return baseProps;
330
- }
331
- };
332
-
333
- const getBeforeElement = () => {
334
- if (props.before) return props.before;
335
-
336
- switch (variant) {
337
- case "search":
338
- return !removeSearchIcon ? (
339
- <span className="text-icon-primary-normal contents">
340
- <Icon name="search" />
341
- </span>
342
- ) : null;
343
-
344
- case "currency":
345
- return (
346
- <span className="text-icon-primary-normal contents">
347
- <Icon name="attach_money" />
348
- </span>
349
- );
350
-
351
- default:
352
- return null;
353
- }
354
- };
355
-
356
- const getAfterElement = () => {
357
- if (props.after) return props.after;
358
-
359
- switch (variant) {
360
- case "search": {
361
- const hasValue = displayValue.length > 0;
362
- return hasValue && !props.readOnly ? (
363
- <Icon
364
- id={id ? `${id}-clear-button` : undefined}
365
- testid={testid ? `${testid}-clear-button` : undefined}
366
- name="close"
367
- onClick={handleSearchReset}
368
- className="cursor-pointer absolute right-2 bottom-2/4 translate-y-2/4"
369
- />
370
- ) : null;
371
- }
372
-
373
- case "finder":
374
- return <Icon name="search" />;
375
-
376
- case "uom":
377
- return uom ? (
378
- <Paragraph color="text-secondary-normal">
379
- {uom.toUpperCase()}
380
- </Paragraph>
381
- ) : null;
382
-
383
- case "percentage":
384
- return (
385
- <span className="text-icon-primary-normal contents">
386
- <Icon name="percent" />
387
- </span>
388
- );
389
-
390
- default:
391
- return null;
392
- }
393
- };
394
-
395
- const handleSearchReset = () => {
396
- setInternalValue("");
397
- setDisplayValue("");
398
-
399
- if (onChange) {
400
- const syntheticEvent = {
401
- target: { value: "" },
402
- } as React.ChangeEvent<HTMLInputElement>;
403
-
404
- if (typeof onChange === "function") {
405
- onChange(syntheticEvent);
406
- }
407
- }
408
-
409
- onClear?.();
410
- };
411
-
412
- const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
413
- const rawValue = e.target.value;
414
- const maxNumber =
415
- props.max != null
416
- ? Number(String(props.max).replace(/,/g, ""))
417
- : undefined;
418
-
419
- if (variant === "currency") {
420
- const raw = rawValue.replace(/,/g, ""); // Remove commas for processing
421
-
422
- if (raw === "") {
423
- setInternalValue("");
424
- setDisplayValue("");
425
- if (onChange) {
426
- const syntheticEvent = {
427
- ...e,
428
- target: { ...e.target, value: "" },
429
- } as React.ChangeEvent<HTMLInputElement>;
430
- onChange(syntheticEvent);
431
- }
432
- return;
433
- }
434
-
435
- const regex = /^\d*\.?\d*$/;
436
- if (!regex.test(raw)) return;
437
-
438
- const parts = raw.split(".");
439
- const currentDecimals = decimals ?? 2;
440
- if (parts.length === 2 && parts[1].length > currentDecimals) return;
441
-
442
- const asNumber = Number(raw);
443
- if (!isNaN(asNumber) && maxNumber != null && asNumber > maxNumber) {
444
- // Clamp to max
445
- const clamped = maxNumber;
446
- const formattedClamped = formatDecimalValue(
447
- clamped.toString(),
448
- currentDecimals,
449
- );
450
- setInternalValue(formattedClamped);
451
- setDisplayValue(formatCurrencyDisplay(formattedClamped));
452
- if (onChange) {
453
- const syntheticEvent = {
454
- ...e,
455
- target: { ...e.target, value: clamped.toString() },
456
- } as React.ChangeEvent<HTMLInputElement>;
457
- onChange(syntheticEvent);
458
- }
459
- return;
460
- }
461
-
462
- setInternalValue(raw);
463
- setDisplayValue(formatCurrencyDisplay(raw));
464
-
465
- if (!isNaN(asNumber) && onChange) {
466
- const syntheticEvent = {
467
- ...e,
468
- target: { ...e.target, value: asNumber.toString() },
469
- } as React.ChangeEvent<HTMLInputElement>;
470
- onChange(syntheticEvent);
471
- }
472
- return;
473
- }
474
-
475
- // Handle numeric variants (percentage / uom) wrt max prop
476
- if (
477
- (variant === "percentage" || variant === "uom") &&
478
- e.target.type === "number"
479
- ) {
480
- const numeric = Number(rawValue);
481
- if (!isNaN(numeric) && maxNumber != null && numeric > maxNumber) {
482
- const clamped = maxNumber;
483
- const formattedClamped = formatDecimalValue(
484
- clamped.toString(),
485
- decimals ?? 0,
486
- );
487
- setInternalValue(formattedClamped);
488
- setDisplayValue(formattedClamped);
489
-
490
- if (typeof onChange === "function") {
491
- const syntheticEvent = {
492
- ...e,
493
- target: { ...e.target, value: clamped.toString() },
494
- } as React.ChangeEvent<HTMLInputElement>;
495
- onChange(syntheticEvent);
496
- }
497
- return;
498
- }
499
-
500
- setInternalValue(rawValue);
501
- setDisplayValue(rawValue);
502
- if (typeof onChange === "function") {
503
- onChange(e);
504
- }
505
- return;
506
- }
507
-
508
- // Default behavior for other variants
509
- setInternalValue(rawValue);
510
- setDisplayValue(rawValue);
511
- if (typeof onChange === "function") {
512
- onChange(e);
513
- }
514
- };
515
-
516
- const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {
517
- if (!internalValue) {
518
- onBlur?.(e);
519
- return;
520
- }
521
-
522
- if (variant === "currency") {
523
- const formatted = formatDecimalValue(internalValue, decimals ?? 2);
524
- setInternalValue(formatted);
525
- setDisplayValue(formatCurrencyDisplay(formatted));
526
-
527
- const asNumber = Number(formatted);
528
- if (!isNaN(asNumber) && onChange) {
529
- const syntheticEvent = {
530
- ...e,
531
- target: { ...e.target, value: asNumber.toString() },
532
- } as React.ChangeEvent<HTMLInputElement>;
533
- onChange(syntheticEvent);
534
- }
535
- } else if (variant === "uom" || variant === "percentage") {
536
- const formattedValue = formatDecimalValue(e.target.value, decimals);
537
- e.target.value = formattedValue;
538
- }
539
-
540
- onBlur?.(e);
541
- };
542
-
543
- const inputProps = getInputProps();
544
-
545
- return (
546
- <InputBase
547
- {...inputProps}
548
- before={getBeforeElement()}
549
- after={getAfterElement()}
550
- onChange={handleChange}
551
- onBlur={handleBlur}
552
- testid={testid}
553
- rightAdornment={rightAdornment}
554
- />
555
- );
556
- };
557
-
558
- Input.displayName = "Input";
559
-
560
- // Legacy component exports for backward compatibility
561
- export const Finder = (
562
- props: Omit<ComponentProps<"input">, "value" | "align" | "children" | "id"> &
563
- InputBaseProps & { value?: string | number },
564
- ) => <Input {...props} variant="finder" />;
565
-
566
- export const UOM = (
567
- props: Omit<ComponentProps<"input">, "value" | "align" | "children" | "id"> &
568
- InputBaseProps & {
569
- uom: string;
570
- value?: string | number;
571
- },
572
- ) => <Input {...props} variant="uom" />;
573
-
574
- export const Currency = (
575
- props: Omit<
576
- ComponentProps<"input">,
577
- "onChange" | "align" | "children" | "id"
578
- > &
579
- InputBaseProps & {
580
- onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
581
- },
582
- ) => {
583
- const handleCurrencyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
584
- // For currency, we want to pass the numeric value but maintain the string interface
585
- props.onChange?.(e);
586
- };
587
-
588
- return (
589
- <Input
590
- {...props}
591
- variant="currency"
592
- decimals={props.decimals ?? 2}
593
- onChange={handleCurrencyChange}
594
- />
595
- );
596
- };
597
-
598
- export const Percentage = (
599
- props: Omit<ComponentProps<"input">, "value" | "align" | "children" | "id"> &
600
- InputBaseProps & {
601
- value?: string | number;
602
- },
603
- ) => <Input {...props} variant="percentage" />;
604
-
605
- // Set display names for legacy components
606
- Finder.displayName = "Finder";
607
- UOM.displayName = "UOM";
608
- Currency.displayName = "Currency";
609
- Percentage.displayName = "Percentage";
@@ -1,59 +0,0 @@
1
- "use client";
2
- import { ComponentProps, ReactNode } from "react";
3
- import { Label } from "./Label";
4
- import clsx from "clsx";
5
- import { useId } from "react";
6
- import { componentGap, layoutGap } from "../classNames";
7
-
8
- type InputGroupProps = {
9
- id?: string;
10
- testid?: string;
11
- label: string;
12
- orientation?: "vertical" | "horizontal";
13
- error?: boolean;
14
- caption?: ReactNode;
15
- };
16
-
17
- export const InputGroup = ({
18
- id,
19
- testid,
20
- label,
21
- orientation = "horizontal",
22
- error = false,
23
- children,
24
- caption,
25
- ...props
26
- }: ComponentProps<"div"> & InputGroupProps) => {
27
- const internalId = useId();
28
- const labelId = id ? `${id}-label` : undefined;
29
- const labelTestId = testid ? `${testid}-label` : undefined;
30
-
31
- return (
32
- <div id={id} data-testid={testid} {...props} className={clsx("flex flex-col", componentGap)}>
33
- <Label
34
- id={labelId}
35
- testid={labelTestId}
36
- as="label"
37
- className={clsx({ "!text-text-primary-error": error })}
38
- htmlFor={internalId}
39
- >
40
- {label}
41
- </Label>
42
-
43
- <div
44
- className={clsx(
45
- "flex *:py-mobile-component-padding desktop:*:py-desktop-component-padding compact:*:py-desktop-compact-component-padding",
46
- orientation === "vertical"
47
- ? "flex-col"
48
- : clsx("items-center", layoutGap),
49
- )}
50
- >
51
- {children}
52
- </div>
53
-
54
- {caption && <div id={id ? `${id}-caption` : undefined} data-testid={testid ? `${testid}-caption` : undefined}>{caption}</div>}
55
- </div>
56
- );
57
- };
58
-
59
- InputGroup.displayName = "InputGroup";
@@ -1,46 +0,0 @@
1
- import clsx from "clsx";
2
- import { AsProps, TextAttributes, TypographyProps } from "../types";
3
- import { componentPaddingXUsingComponentGap, typography } from "../classNames";
4
- export type Tags = "span" | "label" | "p" | "a";
5
-
6
- type LabelProps = {
7
- as?: Tags;
8
- id?: string;
9
- testid?: string;
10
- } & AsProps<Tags> &
11
- TextAttributes &
12
- TypographyProps;
13
-
14
- export const Label = ({
15
- as = "span",
16
- padded,
17
- className,
18
- color,
19
- align,
20
- id,
21
- testid,
22
- ...props
23
- }: LabelProps) => {
24
- const Element = as;
25
- return (
26
- <Element
27
- id={id}
28
- data-testid={testid}
29
- className={clsx(
30
- typography.label,
31
- align === "left" && "text-left",
32
- align === "center" && "text-center",
33
- align === "right" && "text-right",
34
- className,
35
- padded && componentPaddingXUsingComponentGap,
36
- )}
37
- {...props}
38
- style={{
39
- ...props.style,
40
- color: color ? `var(--color-${color})` : undefined,
41
- }}
42
- />
43
- );
44
- };
45
-
46
- Label.displayName = "Label";