@dragunio/fe-libs 0.1.4 → 0.1.5

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/dist/index.mjs CHANGED
@@ -1,3 +1,27 @@
1
+ import {
2
+ ChevronDownIcon,
3
+ CloseIcon,
4
+ PlusIcon,
5
+ SearchIcon,
6
+ arrow_left,
7
+ check_square_fill,
8
+ chevron_down,
9
+ chevron_left,
10
+ chevron_right,
11
+ chevron_up,
12
+ copy,
13
+ key,
14
+ lock,
15
+ lock_unlocked,
16
+ log_out,
17
+ minus_square,
18
+ plus,
19
+ plus_square,
20
+ search,
21
+ trash,
22
+ x_close
23
+ } from "./chunk-3TCR34LS.mjs";
24
+
1
25
  // packages/button/src/index.tsx
2
26
  import { forwardRef } from "react";
3
27
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -64,32 +88,6 @@ var Button = forwardRef(
64
88
  );
65
89
  Button.displayName = "Button";
66
90
 
67
- // packages/icons/src/index.tsx
68
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
69
- var iconProps = ({ size, ...props }) => ({
70
- width: size ?? 20,
71
- height: size ?? 20,
72
- fill: "none",
73
- viewBox: "0 0 24 24",
74
- "aria-hidden": true,
75
- ...props
76
- });
77
- function PlusIcon(props) {
78
- return /* @__PURE__ */ jsx2("svg", { ...iconProps(props), children: /* @__PURE__ */ jsx2("path", { d: "M12 5v14M5 12h14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) });
79
- }
80
- function ChevronDownIcon(props) {
81
- return /* @__PURE__ */ jsx2("svg", { ...iconProps(props), children: /* @__PURE__ */ jsx2("path", { d: "m6 9 6 6 6-6", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) });
82
- }
83
- function CloseIcon(props) {
84
- return /* @__PURE__ */ jsx2("svg", { ...iconProps(props), children: /* @__PURE__ */ jsx2("path", { d: "m6 6 12 12M18 6 6 18", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) });
85
- }
86
- function SearchIcon(props) {
87
- return /* @__PURE__ */ jsxs2("svg", { ...iconProps(props), children: [
88
- /* @__PURE__ */ jsx2("circle", { cx: "11", cy: "11", r: "6.5", stroke: "currentColor", strokeWidth: "2" }),
89
- /* @__PURE__ */ jsx2("path", { d: "m16 16 4 4", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
90
- ] });
91
- }
92
-
93
91
  // packages/table/src/index.tsx
94
92
  import {
95
93
  createContext,
@@ -104,7 +102,7 @@ import {
104
102
 
105
103
  // packages/pagination/src/index.tsx
106
104
  import { useMemo, useState } from "react";
107
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
105
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
108
106
  var clamp = (value, min, max) => Math.min(Math.max(value, min), max);
109
107
  var range = (start, end) => Array.from({ length: Math.max(0, end - start + 1) }, (_, index) => start + index);
110
108
  function getItems(totalPages, page, siblingCount, boundaryCount) {
@@ -147,9 +145,9 @@ function Pagination({
147
145
  if (page === void 0) setUncontrolledPage(resolvedPage);
148
146
  if (resolvedPage !== currentPage) onPageChange?.(resolvedPage);
149
147
  };
150
- return /* @__PURE__ */ jsxs3("nav", { className: ["fe-pagination", className].filter(Boolean).join(" "), "aria-label": "Pagination", ...props, children: [
151
- /* @__PURE__ */ jsx3(Button, { className: "fe-pagination__button fe-pagination__button--control", hierarchy: "secondary-gray", size: "40", iconOnly: true, icon: "\u2039", "aria-label": previousLabel, disabled: disabled || currentPage === 1, onClick: () => selectPage(currentPage - 1) }),
152
- items.map((item, index) => item === "start-ellipsis" || item === "end-ellipsis" ? /* @__PURE__ */ jsx3("span", { className: "fe-pagination__ellipsis", "aria-hidden": "true", children: "\u2026" }, `${item}-${index}`) : /* @__PURE__ */ jsx3(
148
+ return /* @__PURE__ */ jsxs2("nav", { className: ["fe-pagination", className].filter(Boolean).join(" "), "aria-label": "Pagination", ...props, children: [
149
+ /* @__PURE__ */ jsx2(Button, { className: "fe-pagination__button fe-pagination__button--control", hierarchy: "secondary-gray", size: "40", iconOnly: true, icon: "\u2039", "aria-label": previousLabel, disabled: disabled || currentPage === 1, onClick: () => selectPage(currentPage - 1) }),
150
+ items.map((item, index) => item === "start-ellipsis" || item === "end-ellipsis" ? /* @__PURE__ */ jsx2("span", { className: "fe-pagination__ellipsis", "aria-hidden": "true", children: "\u2026" }, `${item}-${index}`) : /* @__PURE__ */ jsx2(
153
151
  Button,
154
152
  {
155
153
  className: "fe-pagination__button",
@@ -163,12 +161,12 @@ function Pagination({
163
161
  },
164
162
  item
165
163
  )),
166
- /* @__PURE__ */ jsx3(Button, { className: "fe-pagination__button fe-pagination__button--control", hierarchy: "secondary-gray", size: "40", iconOnly: true, icon: "\u203A", "aria-label": nextLabel, disabled: disabled || currentPage === safeTotalPages, onClick: () => selectPage(currentPage + 1) })
164
+ /* @__PURE__ */ jsx2(Button, { className: "fe-pagination__button fe-pagination__button--control", hierarchy: "secondary-gray", size: "40", iconOnly: true, icon: "\u203A", "aria-label": nextLabel, disabled: disabled || currentPage === safeTotalPages, onClick: () => selectPage(currentPage + 1) })
167
165
  ] });
168
166
  }
169
167
 
170
168
  // packages/table/src/index.tsx
171
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
169
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
172
170
  var TableContext = createContext({ striped: false });
173
171
  var MIN_COLUMN_WIDTH = 96;
174
172
  var MAX_COLUMN_WIDTH = 1200;
@@ -268,14 +266,14 @@ function DataTable({
268
266
  if (nextPage !== currentPage) onPageChange?.(nextPage);
269
267
  };
270
268
  const resolvedPaginationPosition = paginationPosition === "middle-bottom" ? "bottom-center" : paginationPosition;
271
- const paginationControl = shouldPaginate && totalPages > 1 ? /* @__PURE__ */ jsx4("div", { className: `fe-table__pagination fe-table__pagination--${resolvedPaginationPosition}`, children: /* @__PURE__ */ jsx4(Pagination, { page: currentPage, totalPages, onPageChange: changePage }) }) : null;
272
- return /* @__PURE__ */ jsxs4("div", { className: "fe-table", "data-resizing": isResizing || void 0, children: [
269
+ const paginationControl = shouldPaginate && totalPages > 1 ? /* @__PURE__ */ jsx3("div", { className: `fe-table__pagination fe-table__pagination--${resolvedPaginationPosition}`, children: /* @__PURE__ */ jsx3(Pagination, { page: currentPage, totalPages, onPageChange: changePage }) }) : null;
270
+ return /* @__PURE__ */ jsxs3("div", { className: "fe-table", "data-resizing": isResizing || void 0, children: [
273
271
  resolvedPaginationPosition === "top-right" && paginationControl,
274
- /* @__PURE__ */ jsxs4("table", { className: ["fe-table__table", className].filter(Boolean).join(" "), "data-fe-table": true, "data-striped": striped || void 0, ...props, children: [
275
- /* @__PURE__ */ jsx4("colgroup", { children: sizes2.map((size, index) => /* @__PURE__ */ jsx4("col", { style: { width: `${size}px` } }, index)) }),
276
- /* @__PURE__ */ jsx4("thead", { children: /* @__PURE__ */ jsx4("tr", { children: Array.from({ length: columnCount }, (_, columnIndex) => /* @__PURE__ */ jsxs4("th", { scope: "col", children: [
277
- /* @__PURE__ */ jsx4("span", { className: "fe-table__header-content", children: headers[columnIndex] ?? `Column ${columnIndex + 1}` }),
278
- /* @__PURE__ */ jsx4(
272
+ /* @__PURE__ */ jsxs3("table", { className: ["fe-table__table", className].filter(Boolean).join(" "), "data-fe-table": true, "data-striped": striped || void 0, ...props, children: [
273
+ /* @__PURE__ */ jsx3("colgroup", { children: sizes2.map((size, index) => /* @__PURE__ */ jsx3("col", { style: { width: `${size}px` } }, index)) }),
274
+ /* @__PURE__ */ jsx3("thead", { children: /* @__PURE__ */ jsx3("tr", { children: Array.from({ length: columnCount }, (_, columnIndex) => /* @__PURE__ */ jsxs3("th", { scope: "col", children: [
275
+ /* @__PURE__ */ jsx3("span", { className: "fe-table__header-content", children: headers[columnIndex] ?? `Column ${columnIndex + 1}` }),
276
+ /* @__PURE__ */ jsx3(
279
277
  "span",
280
278
  {
281
279
  className: "fe-table__resize-handle",
@@ -299,7 +297,7 @@ function DataTable({
299
297
  }
300
298
  )
301
299
  ] }, columnIndex)) }) }),
302
- /* @__PURE__ */ jsx4("tbody", { children: pagedData.map((row, rowIndex) => /* @__PURE__ */ jsx4("tr", { children: Array.from({ length: columnCount }, (_, columnIndex) => /* @__PURE__ */ jsx4("td", { children: row[columnIndex] }, columnIndex)) }, shouldPaginate ? (currentPage - 1) * safePageSize + rowIndex : rowIndex)) })
300
+ /* @__PURE__ */ jsx3("tbody", { children: pagedData.map((row, rowIndex) => /* @__PURE__ */ jsx3("tr", { children: Array.from({ length: columnCount }, (_, columnIndex) => /* @__PURE__ */ jsx3("td", { children: row[columnIndex] }, columnIndex)) }, shouldPaginate ? (currentPage - 1) * safePageSize + rowIndex : rowIndex)) })
303
301
  ] }),
304
302
  resolvedPaginationPosition !== "top-right" && paginationControl
305
303
  ] });
@@ -317,42 +315,42 @@ function Table({
317
315
  paginationPosition,
318
316
  ...props
319
317
  }) {
320
- if (headers || data) return /* @__PURE__ */ jsx4(DataTable, { headers: headers ?? [], data: data ?? [], striped: striped ?? true, pagination, pageSize, page, defaultPage, onPageChange, paginationPosition, ...props });
321
- return /* @__PURE__ */ jsx4(TableContext.Provider, { value: { striped: striped ?? false }, children: /* @__PURE__ */ jsx4("table", { "data-fe-table": true, "data-striped": striped || void 0, ...props, children }) });
318
+ if (headers || data) return /* @__PURE__ */ jsx3(DataTable, { headers: headers ?? [], data: data ?? [], striped: striped ?? true, pagination, pageSize, page, defaultPage, onPageChange, paginationPosition, ...props });
319
+ return /* @__PURE__ */ jsx3(TableContext.Provider, { value: { striped: striped ?? false }, children: /* @__PURE__ */ jsx3("table", { "data-fe-table": true, "data-striped": striped || void 0, ...props, children }) });
322
320
  }
323
321
  function TableHead(props) {
324
- return /* @__PURE__ */ jsx4("thead", { ...props });
322
+ return /* @__PURE__ */ jsx3("thead", { ...props });
325
323
  }
326
324
  function TableBody(props) {
327
- return /* @__PURE__ */ jsx4("tbody", { ...props });
325
+ return /* @__PURE__ */ jsx3("tbody", { ...props });
328
326
  }
329
327
  function TableRow({ children, ...props }) {
330
328
  const { striped } = useContext(TableContext);
331
- return /* @__PURE__ */ jsx4("tr", { "data-striped": striped || void 0, ...props, children });
329
+ return /* @__PURE__ */ jsx3("tr", { "data-striped": striped || void 0, ...props, children });
332
330
  }
333
331
  function TableCell({ children, ...props }) {
334
- return /* @__PURE__ */ jsx4("td", { ...props, children });
332
+ return /* @__PURE__ */ jsx3("td", { ...props, children });
335
333
  }
336
334
  function TableHeader({ children, ...props }) {
337
- return /* @__PURE__ */ jsx4("th", { scope: "col", ...props, children });
335
+ return /* @__PURE__ */ jsx3("th", { scope: "col", ...props, children });
338
336
  }
339
337
  function TableCaption(props) {
340
- return /* @__PURE__ */ jsx4("caption", { ...props });
338
+ return /* @__PURE__ */ jsx3("caption", { ...props });
341
339
  }
342
340
 
343
341
  // packages/toggle/src/index.tsx
344
342
  import { forwardRef as forwardRef2 } from "react";
345
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
343
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
346
344
  var Toggle = forwardRef2(function Toggle2({ color = "#16a34a", label, className, style, id, ...props }, ref) {
347
345
  const classes = ["fe-toggle", className].filter(Boolean).join(" ");
348
346
  const toggleStyle = {
349
347
  "--fe-toggle-color": color,
350
348
  ...style
351
349
  };
352
- return /* @__PURE__ */ jsxs5("label", { className: classes, style: toggleStyle, children: [
353
- /* @__PURE__ */ jsx5("input", { ref, id, className: "fe-toggle__input", type: "checkbox", role: "switch", ...props }),
354
- /* @__PURE__ */ jsx5("span", { className: "fe-toggle__control", "aria-hidden": "true" }),
355
- label && /* @__PURE__ */ jsx5("span", { className: "fe-toggle__label", children: label })
350
+ return /* @__PURE__ */ jsxs4("label", { className: classes, style: toggleStyle, children: [
351
+ /* @__PURE__ */ jsx4("input", { ref, id, className: "fe-toggle__input", type: "checkbox", role: "switch", ...props }),
352
+ /* @__PURE__ */ jsx4("span", { className: "fe-toggle__control", "aria-hidden": "true" }),
353
+ label && /* @__PURE__ */ jsx4("span", { className: "fe-toggle__label", children: label })
356
354
  ] });
357
355
  });
358
356
  Toggle.displayName = "Toggle";
@@ -360,7 +358,7 @@ Toggle.displayName = "Toggle";
360
358
  // packages/drawer/src/index.tsx
361
359
  import { useEffect as useEffect2 } from "react";
362
360
  import { createPortal } from "react-dom";
363
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
361
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
364
362
  function Drawer({ open, onClose, title, footer, side = "right", width = 400, fullScreen = false, children, closeOnBackdropClick = true, className, style, ...props }) {
365
363
  useEffect2(() => {
366
364
  if (!open) return;
@@ -372,28 +370,47 @@ function Drawer({ open, onClose, title, footer, side = "right", width = 400, ful
372
370
  }, [onClose, open]);
373
371
  if (!open || typeof document === "undefined") return null;
374
372
  const panelStyle = !fullScreen && (side === "left" || side === "right") ? { ...style, width: typeof width === "number" ? `${width}px` : width } : style;
375
- return createPortal(/* @__PURE__ */ jsx6("div", { className: "fe-drawer-backdrop", role: "presentation", onMouseDown: (event) => {
373
+ return createPortal(/* @__PURE__ */ jsx5("div", { className: "fe-drawer-backdrop", role: "presentation", onMouseDown: (event) => {
376
374
  if (event.target === event.currentTarget && closeOnBackdropClick) onClose();
377
- }, children: /* @__PURE__ */ jsxs6("aside", { className: ["fe-drawer", `fe-drawer--${side}`, fullScreen && "fe-drawer--full-screen", className].filter(Boolean).join(" "), style: panelStyle, role: "dialog", "aria-modal": "true", "aria-label": typeof title === "string" ? title : "Drawer", ...props, children: [
378
- /* @__PURE__ */ jsxs6("header", { className: "fe-drawer__header", children: [
379
- title && /* @__PURE__ */ jsx6("h2", { children: title }),
380
- /* @__PURE__ */ jsx6("button", { type: "button", "aria-label": "Close drawer", onClick: onClose, children: "\xD7" })
375
+ }, children: /* @__PURE__ */ jsxs5("aside", { className: ["fe-drawer", `fe-drawer--${side}`, fullScreen && "fe-drawer--full-screen", className].filter(Boolean).join(" "), style: panelStyle, role: "dialog", "aria-modal": "true", "aria-label": typeof title === "string" ? title : "Drawer", ...props, children: [
376
+ /* @__PURE__ */ jsxs5("header", { className: "fe-drawer__header", children: [
377
+ title && /* @__PURE__ */ jsx5("h2", { children: title }),
378
+ /* @__PURE__ */ jsx5("button", { type: "button", "aria-label": "Close drawer", onClick: onClose, children: "\xD7" })
381
379
  ] }),
382
- /* @__PURE__ */ jsx6("div", { className: "fe-drawer__body", children }),
383
- footer && /* @__PURE__ */ jsx6("footer", { className: "fe-drawer__footer", children: footer })
380
+ /* @__PURE__ */ jsx5("div", { className: "fe-drawer__body", children }),
381
+ footer && /* @__PURE__ */ jsx5("footer", { className: "fe-drawer__footer", children: footer })
384
382
  ] }) }), document.body);
385
383
  }
386
384
 
387
- // packages/form-controls/src/index.tsx
388
- import {
389
- forwardRef as forwardRef3,
390
- useEffect as useEffect3,
391
- useId,
392
- useLayoutEffect,
393
- useRef as useRef2,
394
- useState as useState3
395
- } from "react";
396
- import { createPortal as createPortal2 } from "react-dom";
385
+ // packages/form-controls/src/controls/TextInput/text-input.tsx
386
+ import { forwardRef as forwardRef3, useId as useId2, useState as useState4 } from "react";
387
+
388
+ // packages/tooltip/src/index.tsx
389
+ import { cloneElement, useId, useState as useState3 } from "react";
390
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
391
+ function Tooltip({ content, children, placement = "top", disabled, className, ...props }) {
392
+ const [visible, setVisible] = useState3(false);
393
+ const id = useId();
394
+ const trigger = cloneElement(children, { "aria-describedby": visible ? id : void 0, onMouseEnter: (event) => {
395
+ children.props.onMouseEnter?.(event);
396
+ setVisible(true);
397
+ }, onMouseLeave: (event) => {
398
+ children.props.onMouseLeave?.(event);
399
+ setVisible(false);
400
+ }, onFocus: (event) => {
401
+ children.props.onFocus?.(event);
402
+ setVisible(true);
403
+ }, onBlur: (event) => {
404
+ children.props.onBlur?.(event);
405
+ setVisible(false);
406
+ } });
407
+ return /* @__PURE__ */ jsxs6("span", { className: ["fe-tooltip", `fe-tooltip--${placement}`, className].filter(Boolean).join(" "), ...props, children: [
408
+ trigger,
409
+ visible && !disabled && /* @__PURE__ */ jsx6("span", { id, role: "tooltip", className: "fe-tooltip__content", children: content })
410
+ ] });
411
+ }
412
+
413
+ // packages/form-controls/src/controls/Field/field.tsx
397
414
  import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
398
415
  function getFieldError(error, errorMessage) {
399
416
  if (errorMessage !== void 0 && errorMessage !== null) return errorMessage;
@@ -403,178 +420,655 @@ function getFieldError(error, errorMessage) {
403
420
  function getDescribedBy(existing, messageId2) {
404
421
  return [existing, messageId2].filter(Boolean).join(" ") || void 0;
405
422
  }
406
- var TextInput = forwardRef3(function TextInput2({ value, defaultValue = "", onChange, onValueChange, label, helperText, error, errorMessage, clearable = false, onClear, clearLabel = "Clear input", className, disabled, readOnly, id, "aria-describedby": ariaDescribedBy, "aria-labelledby": ariaLabelledBy, ...props }, ref) {
407
- const generatedId = useId();
408
- const inputId = id ?? `${generatedId}-input`;
409
- const labelId = `${generatedId}-label`;
410
- const messageId2 = `${generatedId}-message`;
411
- const controlled = value !== void 0;
412
- const [internalValue, setInternalValue] = useState3(defaultValue);
413
- const currentValue = controlled ? value : internalValue;
414
- const fieldError = getFieldError(error, errorMessage);
415
- const hasError = fieldError !== void 0 && fieldError !== false && fieldError !== null;
416
- const displayedMessage = hasError ? fieldError : helperText;
417
- const describedBy = getDescribedBy(ariaDescribedBy, displayedMessage ? messageId2 : void 0);
418
- const clear = () => {
419
- if (!controlled) setInternalValue("");
420
- onValueChange?.("");
421
- onClear?.();
422
- };
423
- const labelledBy = getDescribedBy(ariaLabelledBy, label ? labelId : void 0);
424
- return /* @__PURE__ */ jsxs7("label", { className: ["fe-text-input", hasError && "fe-text-input--error", className].filter(Boolean).join(" "), children: [
425
- label && /* @__PURE__ */ jsx7("span", { id: labelId, className: "fe-text-input__label", children: label }),
426
- /* @__PURE__ */ jsxs7("span", { className: "fe-text-input__control", children: [
427
- /* @__PURE__ */ jsx7("input", { ref, id: inputId, value: currentValue, disabled, readOnly, "aria-invalid": hasError || void 0, "aria-labelledby": labelledBy, "aria-describedby": describedBy, onChange: (event) => {
428
- if (!controlled) setInternalValue(event.target.value);
429
- onValueChange?.(event.target.value);
430
- onChange?.(event);
431
- }, ...props }),
432
- clearable && currentValue && !disabled && !readOnly && /* @__PURE__ */ jsx7(Button, { hierarchy: "tertiary-gray", size: "24", iconOnly: true, icon: /* @__PURE__ */ jsx7(CloseIcon, { size: 14 }), "aria-label": clearLabel, onClick: clear, className: "fe-text-input__clear" })
433
- ] }),
434
- displayedMessage && /* @__PURE__ */ jsx7("span", { id: messageId2, className: hasError ? "fe-text-input__error" : "fe-text-input__helper", children: displayedMessage })
423
+ function FieldLabel({
424
+ id,
425
+ label,
426
+ description,
427
+ descriptionDisplay,
428
+ isRequired = false
429
+ }) {
430
+ if (!label) return null;
431
+ return /* @__PURE__ */ jsxs7("span", { className: "fe-field__label", children: [
432
+ /* @__PURE__ */ jsx7("span", { id, children: label }),
433
+ isRequired && /* @__PURE__ */ jsx7("span", { className: "fe-field__required", "aria-hidden": "true", children: "*" }),
434
+ description && descriptionDisplay === "tooltip" && /* @__PURE__ */ jsx7(Tooltip, { content: description, children: /* @__PURE__ */ jsx7(
435
+ "span",
436
+ {
437
+ className: "fe-field__info",
438
+ tabIndex: 0,
439
+ role: "img",
440
+ "aria-label": "More information",
441
+ children: "i"
442
+ }
443
+ ) })
435
444
  ] });
436
- });
445
+ }
446
+ function FieldMessage({
447
+ id,
448
+ error,
449
+ description,
450
+ descriptionDisplay
451
+ }) {
452
+ if (error !== void 0 && error !== false && error !== null)
453
+ return /* @__PURE__ */ jsx7(
454
+ "span",
455
+ {
456
+ id,
457
+ className: "fe-field__message fe-field__message--error",
458
+ role: "alert",
459
+ children: error
460
+ }
461
+ );
462
+ if (description && descriptionDisplay === "inline")
463
+ return /* @__PURE__ */ jsx7("span", { id, className: "fe-field__message", children: description });
464
+ return null;
465
+ }
466
+
467
+ // packages/form-controls/src/controls/TextInput/text-input.tsx
468
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
469
+ var TextInput = forwardRef3(
470
+ function TextInput2({
471
+ value,
472
+ defaultValue = "",
473
+ onChange,
474
+ onValueChange,
475
+ label,
476
+ description,
477
+ descriptionDisplay = "inline",
478
+ helperText,
479
+ error,
480
+ errorMessage,
481
+ clearable = false,
482
+ onClear,
483
+ clearLabel = "Clear input",
484
+ className,
485
+ disabled,
486
+ readOnly,
487
+ id,
488
+ prefix,
489
+ suffix,
490
+ Prefix,
491
+ Suffix,
492
+ isRequired = false,
493
+ placeholder,
494
+ required,
495
+ "aria-describedby": ariaDescribedBy,
496
+ "aria-labelledby": ariaLabelledBy,
497
+ ...props
498
+ }, ref) {
499
+ const generatedId = useId2();
500
+ const inputId = id ?? generatedId + "-input";
501
+ const labelId = generatedId + "-label";
502
+ const messageId2 = generatedId + "-message";
503
+ const controlled = value !== void 0;
504
+ const [internalValue, setInternalValue] = useState4(defaultValue);
505
+ const currentValue = controlled ? value : internalValue;
506
+ const fieldError = getFieldError(error, errorMessage);
507
+ const hasError = fieldError !== void 0 && fieldError !== false && fieldError !== null;
508
+ const resolvedDescription = description ?? helperText;
509
+ const hasMessage = hasError || resolvedDescription && descriptionDisplay === "inline";
510
+ const describedBy = getDescribedBy(
511
+ ariaDescribedBy,
512
+ hasMessage ? messageId2 : void 0
513
+ );
514
+ const resolvedPrefix = prefix ?? Prefix;
515
+ const resolvedSuffix = suffix ?? Suffix;
516
+ const labelledBy = getDescribedBy(
517
+ ariaLabelledBy,
518
+ label ? labelId : void 0
519
+ );
520
+ const clear = () => {
521
+ if (!controlled) setInternalValue("");
522
+ onValueChange?.("");
523
+ onClear?.();
524
+ };
525
+ return /* @__PURE__ */ jsxs8(
526
+ "div",
527
+ {
528
+ className: [
529
+ "fe-text-input",
530
+ hasError && "fe-text-input--error",
531
+ className
532
+ ].filter(Boolean).join(" "),
533
+ children: [
534
+ /* @__PURE__ */ jsx8(
535
+ FieldLabel,
536
+ {
537
+ id: labelId,
538
+ label,
539
+ description: resolvedDescription,
540
+ descriptionDisplay,
541
+ isRequired
542
+ }
543
+ ),
544
+ /* @__PURE__ */ jsxs8("span", { className: "fe-text-input__control", children: [
545
+ resolvedPrefix && /* @__PURE__ */ jsx8("span", { className: "fe-text-input__prefix", children: resolvedPrefix }),
546
+ /* @__PURE__ */ jsxs8("span", { className: "fe-text-input__input-wrap", children: [
547
+ /* @__PURE__ */ jsx8(
548
+ "input",
549
+ {
550
+ ref,
551
+ id: inputId,
552
+ value: currentValue,
553
+ placeholder,
554
+ required: isRequired || required,
555
+ disabled,
556
+ readOnly,
557
+ "aria-invalid": hasError || void 0,
558
+ "aria-required": isRequired || void 0,
559
+ "aria-labelledby": labelledBy,
560
+ "aria-describedby": describedBy,
561
+ onChange: (event) => {
562
+ if (!controlled) setInternalValue(event.target.value);
563
+ onValueChange?.(event.target.value);
564
+ onChange?.(event);
565
+ },
566
+ ...props
567
+ }
568
+ ),
569
+ isRequired && placeholder && !currentValue && /* @__PURE__ */ jsxs8("span", { className: "fe-text-input__placeholder", "aria-hidden": "true", children: [
570
+ /* @__PURE__ */ jsx8("span", { children: placeholder }),
571
+ /* @__PURE__ */ jsx8("span", { className: "fe-field__required", children: "*" })
572
+ ] })
573
+ ] }),
574
+ resolvedSuffix && /* @__PURE__ */ jsx8("span", { className: "fe-text-input__suffix", children: resolvedSuffix }),
575
+ clearable && currentValue && !disabled && !readOnly && /* @__PURE__ */ jsx8(
576
+ Button,
577
+ {
578
+ hierarchy: "tertiary-gray",
579
+ size: "24",
580
+ iconOnly: true,
581
+ icon: /* @__PURE__ */ jsx8(CloseIcon, { size: 14 }),
582
+ "aria-label": clearLabel,
583
+ onClick: clear,
584
+ className: "fe-text-input__clear"
585
+ }
586
+ )
587
+ ] }),
588
+ /* @__PURE__ */ jsx8(
589
+ FieldMessage,
590
+ {
591
+ id: messageId2,
592
+ error: fieldError,
593
+ description: resolvedDescription,
594
+ descriptionDisplay
595
+ }
596
+ )
597
+ ]
598
+ }
599
+ );
600
+ }
601
+ );
437
602
  TextInput.displayName = "TextInput";
438
- var TextArea = forwardRef3(function TextArea2({ value, defaultValue = "", onChange, onValueChange, label, helperText, error, errorMessage, clearable = false, onClear, clearLabel = "Clear text area", className, disabled, readOnly, id, "aria-describedby": ariaDescribedBy, "aria-labelledby": ariaLabelledBy, ...props }, ref) {
439
- const generatedId = useId();
440
- const inputId = id ?? `${generatedId}-input`;
441
- const labelId = `${generatedId}-label`;
442
- const messageId2 = `${generatedId}-message`;
443
- const controlled = value !== void 0;
444
- const [internalValue, setInternalValue] = useState3(defaultValue);
445
- const currentValue = controlled ? value : internalValue;
446
- const fieldError = getFieldError(error, errorMessage);
447
- const hasError = fieldError !== void 0 && fieldError !== false && fieldError !== null;
448
- const displayedMessage = hasError ? fieldError : helperText;
449
- const describedBy = getDescribedBy(ariaDescribedBy, displayedMessage ? messageId2 : void 0);
450
- const clear = () => {
451
- if (!controlled) setInternalValue("");
452
- onValueChange?.("");
453
- onClear?.();
454
- };
455
- const labelledBy = getDescribedBy(ariaLabelledBy, label ? labelId : void 0);
456
- return /* @__PURE__ */ jsxs7("label", { className: ["fe-text-area", hasError && "fe-text-area--error", className].filter(Boolean).join(" "), children: [
457
- label && /* @__PURE__ */ jsx7("span", { id: labelId, className: "fe-text-area__label", children: label }),
458
- /* @__PURE__ */ jsxs7("span", { className: "fe-text-area__control", children: [
459
- /* @__PURE__ */ jsx7("textarea", { ref, id: inputId, value: currentValue, disabled, readOnly, "aria-invalid": hasError || void 0, "aria-labelledby": labelledBy, "aria-describedby": describedBy, onChange: (event) => {
460
- if (!controlled) setInternalValue(event.target.value);
461
- onValueChange?.(event.target.value);
462
- onChange?.(event);
463
- }, ...props }),
464
- clearable && currentValue && !disabled && !readOnly && /* @__PURE__ */ jsx7(Button, { hierarchy: "tertiary-gray", size: "24", iconOnly: true, icon: /* @__PURE__ */ jsx7(CloseIcon, { size: 14 }), "aria-label": clearLabel, onClick: clear, className: "fe-text-area__clear" })
465
- ] }),
466
- displayedMessage && /* @__PURE__ */ jsx7("span", { id: messageId2, className: hasError ? "fe-text-area__error" : "fe-text-area__helper", children: displayedMessage })
467
- ] });
468
- });
469
- TextArea.displayName = "TextArea";
470
- var Selection = forwardRef3(function Selection2({ className, label, helperText, error, options, placeholder = "Select an option", size = "medium", id, value, defaultValue, onChange, multiple = false, searchable = false, tag = false, clearable = false, disabled = false, name, onKeyDown, ...props }, ref) {
471
- const generatedId = useId();
472
- const listboxId = id ?? generatedId;
473
- const isControlled = value !== void 0;
474
- const [internalValue, setInternalValue] = useState3(defaultValue ?? (multiple ? [] : ""));
475
- const selectedValue = isControlled ? value : internalValue;
476
- const selectedValues = Array.isArray(selectedValue) ? selectedValue : selectedValue === "" || selectedValue === null || selectedValue === void 0 ? [] : [selectedValue];
477
- const selectedOptions = options.filter((option) => selectedValues.some((item) => String(item) === String(option.value)));
478
- const [open, setOpen] = useState3(false);
479
- const [query, setQuery] = useState3("");
480
- const [activeIndex, setActiveIndex] = useState3(0);
481
- const rootRef = useRef2(null);
482
- const menuRef = useRef2(null);
483
- const [menuPosition, setMenuPosition] = useState3(null);
484
- useEffect3(() => {
485
- const close = (event) => {
486
- const target = event.target;
487
- if (!rootRef.current?.contains(target) && !menuRef.current?.contains(target)) setOpen(false);
603
+
604
+ // packages/form-controls/src/controls/TextArea/text-area.tsx
605
+ import { forwardRef as forwardRef4, useId as useId3, useState as useState5 } from "react";
606
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
607
+ var TextArea = forwardRef4(
608
+ function TextArea2({
609
+ value,
610
+ defaultValue = "",
611
+ onChange,
612
+ onValueChange,
613
+ label,
614
+ description,
615
+ descriptionDisplay = "inline",
616
+ helperText,
617
+ error,
618
+ errorMessage,
619
+ clearable = false,
620
+ onClear,
621
+ clearLabel = "Clear text area",
622
+ className,
623
+ disabled,
624
+ readOnly,
625
+ id,
626
+ isRequired = false,
627
+ placeholder,
628
+ required,
629
+ "aria-describedby": ariaDescribedBy,
630
+ "aria-labelledby": ariaLabelledBy,
631
+ ...props
632
+ }, ref) {
633
+ const generatedId = useId3();
634
+ const inputId = id ?? generatedId + "-input";
635
+ const labelId = generatedId + "-label";
636
+ const messageId2 = generatedId + "-message";
637
+ const controlled = value !== void 0;
638
+ const [internalValue, setInternalValue] = useState5(defaultValue);
639
+ const currentValue = controlled ? value : internalValue;
640
+ const fieldError = getFieldError(error, errorMessage);
641
+ const hasError = fieldError !== void 0 && fieldError !== false && fieldError !== null;
642
+ const resolvedDescription = description ?? helperText;
643
+ const hasMessage = hasError || resolvedDescription && descriptionDisplay === "inline";
644
+ const describedBy = getDescribedBy(
645
+ ariaDescribedBy,
646
+ hasMessage ? messageId2 : void 0
647
+ );
648
+ const labelledBy = getDescribedBy(
649
+ ariaLabelledBy,
650
+ label ? labelId : void 0
651
+ );
652
+ const clear = () => {
653
+ if (!controlled) setInternalValue("");
654
+ onValueChange?.("");
655
+ onClear?.();
488
656
  };
489
- document.addEventListener("mousedown", close);
490
- return () => document.removeEventListener("mousedown", close);
491
- }, []);
492
- useLayoutEffect(() => {
493
- if (!open) return;
494
- const updateMenuPosition = () => {
495
- const rect = rootRef.current?.getBoundingClientRect();
496
- if (rect) setMenuPosition({ top: rect.bottom + 7, left: rect.left, width: rect.width });
657
+ return /* @__PURE__ */ jsxs9(
658
+ "div",
659
+ {
660
+ className: [
661
+ "fe-text-area",
662
+ hasError && "fe-text-area--error",
663
+ className
664
+ ].filter(Boolean).join(" "),
665
+ children: [
666
+ /* @__PURE__ */ jsx9(
667
+ FieldLabel,
668
+ {
669
+ id: labelId,
670
+ label,
671
+ description: resolvedDescription,
672
+ descriptionDisplay,
673
+ isRequired
674
+ }
675
+ ),
676
+ /* @__PURE__ */ jsxs9("span", { className: "fe-text-area__control", children: [
677
+ /* @__PURE__ */ jsx9(
678
+ "textarea",
679
+ {
680
+ ref,
681
+ id: inputId,
682
+ value: currentValue,
683
+ placeholder,
684
+ required: isRequired || required,
685
+ disabled,
686
+ readOnly,
687
+ "aria-invalid": hasError || void 0,
688
+ "aria-required": isRequired || void 0,
689
+ "aria-labelledby": labelledBy,
690
+ "aria-describedby": describedBy,
691
+ onChange: (event) => {
692
+ if (!controlled) setInternalValue(event.target.value);
693
+ onValueChange?.(event.target.value);
694
+ onChange?.(event);
695
+ },
696
+ ...props
697
+ }
698
+ ),
699
+ isRequired && placeholder && !currentValue && /* @__PURE__ */ jsxs9("span", { className: "fe-text-area__placeholder", "aria-hidden": "true", children: [
700
+ /* @__PURE__ */ jsx9("span", { children: placeholder }),
701
+ /* @__PURE__ */ jsx9("span", { className: "fe-field__required", children: "*" })
702
+ ] }),
703
+ clearable && currentValue && !disabled && !readOnly && /* @__PURE__ */ jsx9(
704
+ Button,
705
+ {
706
+ hierarchy: "tertiary-gray",
707
+ size: "24",
708
+ iconOnly: true,
709
+ icon: /* @__PURE__ */ jsx9(CloseIcon, { size: 14 }),
710
+ "aria-label": clearLabel,
711
+ onClick: clear,
712
+ className: "fe-text-area__clear"
713
+ }
714
+ )
715
+ ] }),
716
+ /* @__PURE__ */ jsx9(
717
+ FieldMessage,
718
+ {
719
+ id: messageId2,
720
+ error: fieldError,
721
+ description: resolvedDescription,
722
+ descriptionDisplay
723
+ }
724
+ )
725
+ ]
726
+ }
727
+ );
728
+ }
729
+ );
730
+ TextArea.displayName = "TextArea";
731
+
732
+ // packages/form-controls/src/controls/Selection/selection.tsx
733
+ import {
734
+ forwardRef as forwardRef5,
735
+ useEffect as useEffect3,
736
+ useId as useId4,
737
+ useLayoutEffect,
738
+ useRef as useRef2,
739
+ useState as useState6
740
+ } from "react";
741
+ import { createPortal as createPortal2 } from "react-dom";
742
+ import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
743
+ var Selection = forwardRef5(
744
+ function Selection2({
745
+ className,
746
+ label,
747
+ isRequired = false,
748
+ description,
749
+ descriptionDisplay = "inline",
750
+ helperText,
751
+ error,
752
+ errorMessage,
753
+ options,
754
+ placeholder = "Select an option",
755
+ size = "medium",
756
+ id,
757
+ value,
758
+ defaultValue,
759
+ onChange,
760
+ multiple = false,
761
+ searchable = false,
762
+ tag = false,
763
+ clearable = false,
764
+ disabled = false,
765
+ name,
766
+ onKeyDown,
767
+ "aria-label": ariaLabel,
768
+ "aria-describedby": ariaDescribedBy,
769
+ "aria-labelledby": ariaLabelledBy,
770
+ ...props
771
+ }, ref) {
772
+ const generatedId = useId4();
773
+ const triggerId = id ?? generatedId + "-trigger";
774
+ const listboxId = triggerId + "-listbox";
775
+ const labelId = generatedId + "-label";
776
+ const messageId2 = generatedId + "-message";
777
+ const fieldError = getFieldError(error, errorMessage);
778
+ const hasError = fieldError !== void 0 && fieldError !== false && fieldError !== null;
779
+ const resolvedDescription = description ?? helperText;
780
+ const hasMessage = hasError || resolvedDescription && descriptionDisplay === "inline";
781
+ const describedBy = getDescribedBy(
782
+ ariaDescribedBy,
783
+ hasMessage ? messageId2 : void 0
784
+ );
785
+ const labelledBy = getDescribedBy(
786
+ ariaLabelledBy,
787
+ label ? labelId : void 0
788
+ );
789
+ const isControlled = value !== void 0;
790
+ const [internalValue, setInternalValue] = useState6(
791
+ defaultValue ?? (multiple ? [] : "")
792
+ );
793
+ const selectedValue = isControlled ? value : internalValue;
794
+ const selectedValues = Array.isArray(selectedValue) ? selectedValue : selectedValue === "" || selectedValue === null || selectedValue === void 0 ? [] : [selectedValue];
795
+ const selectedOptions = options.filter(
796
+ (option) => selectedValues.some((item) => String(item) === String(option.value))
797
+ );
798
+ const [open, setOpen] = useState6(false);
799
+ const [query, setQuery] = useState6("");
800
+ const [activeIndex, setActiveIndex] = useState6(0);
801
+ const rootRef = useRef2(null);
802
+ const menuRef = useRef2(null);
803
+ const [menuPosition, setMenuPosition] = useState6(null);
804
+ useEffect3(() => {
805
+ const close = (event) => {
806
+ const target = event.target;
807
+ if (!rootRef.current?.contains(target) && !menuRef.current?.contains(target))
808
+ setOpen(false);
809
+ };
810
+ document.addEventListener("mousedown", close);
811
+ return () => document.removeEventListener("mousedown", close);
812
+ }, []);
813
+ useLayoutEffect(() => {
814
+ if (!open) return;
815
+ const updateMenuPosition = () => {
816
+ const rect = rootRef.current?.getBoundingClientRect();
817
+ if (rect)
818
+ setMenuPosition({
819
+ top: rect.bottom + 7,
820
+ left: rect.left,
821
+ width: rect.width
822
+ });
823
+ };
824
+ updateMenuPosition();
825
+ window.addEventListener("resize", updateMenuPosition);
826
+ document.addEventListener("scroll", updateMenuPosition, true);
827
+ return () => {
828
+ window.removeEventListener("resize", updateMenuPosition);
829
+ document.removeEventListener("scroll", updateMenuPosition, true);
830
+ };
831
+ }, [open]);
832
+ const filteredOptions = options.filter(
833
+ (option) => !query || (option.searchText ?? (typeof option.label === "string" ? option.label : String(option.value))).toLowerCase().includes(query.toLowerCase())
834
+ );
835
+ const commit = (next) => {
836
+ if (!isControlled) setInternalValue(next);
837
+ const selected = options.filter(
838
+ (option) => (Array.isArray(next) ? next : [next]).some(
839
+ (item) => String(item) === String(option.value)
840
+ )
841
+ );
842
+ onChange?.(next, multiple ? selected : selected[0]);
497
843
  };
498
- updateMenuPosition();
499
- window.addEventListener("resize", updateMenuPosition);
500
- document.addEventListener("scroll", updateMenuPosition, true);
501
- return () => {
502
- window.removeEventListener("resize", updateMenuPosition);
503
- document.removeEventListener("scroll", updateMenuPosition, true);
844
+ const choose = (option) => {
845
+ if (option.disabled) return;
846
+ const isSelected = selectedValues.some(
847
+ (item) => String(item) === String(option.value)
848
+ );
849
+ if (multiple)
850
+ commit(
851
+ isSelected ? selectedValues.filter(
852
+ (item) => String(item) !== String(option.value)
853
+ ) : [...selectedValues, option.value]
854
+ );
855
+ else {
856
+ commit(option.value);
857
+ setOpen(false);
858
+ setQuery("");
859
+ }
504
860
  };
505
- }, [open]);
506
- const filteredOptions = options.filter((option) => !query || (option.searchText ?? (typeof option.label === "string" ? option.label : String(option.value))).toLowerCase().includes(query.toLowerCase()));
507
- const commit = (next) => {
508
- if (!isControlled) setInternalValue(next);
509
- const selected = options.filter((option) => (Array.isArray(next) ? next : [next]).some((item) => String(item) === String(option.value)));
510
- onChange?.(next, multiple ? selected : selected[0]);
511
- };
512
- const choose = (option) => {
513
- if (option.disabled) return;
514
- const isSelected = selectedValues.some((item) => String(item) === String(option.value));
515
- if (multiple) commit(isSelected ? selectedValues.filter((item) => String(item) !== String(option.value)) : [...selectedValues, option.value]);
516
- else {
517
- commit(option.value);
518
- setOpen(false);
861
+ const clear = () => {
862
+ commit(multiple ? [] : "");
519
863
  setQuery("");
520
- }
521
- };
522
- const clear = () => {
523
- commit(multiple ? [] : "");
524
- setQuery("");
525
- };
526
- const displayLabel = selectedOptions.length ? selectedOptions.map((option) => option.label) : null;
527
- const onTriggerKeyDown = (event) => {
528
- onKeyDown?.(event);
529
- if (disabled) return;
530
- if (event.key === "ArrowDown" || event.key === "ArrowUp") {
531
- event.preventDefault();
532
- setOpen(true);
533
- setActiveIndex((current) => Math.max(0, Math.min(filteredOptions.length - 1, current + (event.key === "ArrowDown" ? 1 : -1))));
534
- }
535
- if (event.key === "Enter" || event.key === " ") {
536
- event.preventDefault();
537
- if (!open) setOpen(true);
538
- else if (filteredOptions[activeIndex]) choose(filteredOptions[activeIndex]);
539
- }
540
- if (event.key === "Escape") setOpen(false);
541
- };
542
- return /* @__PURE__ */ jsxs7("div", { ref, className: ["fe-selection", `fe-selection--${size}`, open && "fe-selection--open", clearable && selectedOptions.length > 0 && "fe-selection--clearable", error && "fe-selection--error", disabled && "fe-selection--disabled", className].filter(Boolean).join(" "), ...props, children: [
543
- label && /* @__PURE__ */ jsx7("span", { className: "fe-selection__label", children: label }),
544
- /* @__PURE__ */ jsxs7("div", { ref: rootRef, className: "fe-selection__control", children: [
545
- name && selectedValues.map((item) => /* @__PURE__ */ jsx7("input", { type: "hidden", name: multiple ? `${name}[]` : name, value: item }, String(item))),
546
- /* @__PURE__ */ jsxs7("button", { type: "button", className: "fe-selection__trigger", disabled, "aria-invalid": error || void 0, "aria-haspopup": "listbox", "aria-expanded": open, "aria-controls": listboxId, onClick: () => setOpen((current) => !current), onKeyDown: onTriggerKeyDown, children: [
547
- /* @__PURE__ */ jsx7("span", { className: ["fe-selection__value", !selectedOptions.length && "is-placeholder", tag && selectedOptions.length > 1 && "is-tags"].filter(Boolean).join(" "), children: displayLabel ? tag && multiple ? selectedOptions.map((option) => /* @__PURE__ */ jsxs7("span", { className: "fe-selection__tag", children: [
548
- option.label,
549
- /* @__PURE__ */ jsx7("span", { "aria-hidden": "true", children: "\xD7" })
550
- ] }, String(option.value))) : displayLabel.map((item, index) => /* @__PURE__ */ jsxs7("span", { children: [
551
- item,
552
- index < displayLabel.length - 1 ? ", " : ""
553
- ] }, index)) : placeholder }),
554
- /* @__PURE__ */ jsx7("span", { className: "fe-selection__actions", children: /* @__PURE__ */ jsx7("span", { className: "fe-selection__chevron", "aria-hidden": "true" }) })
555
- ] }),
556
- clearable && selectedOptions.length > 0 && /* @__PURE__ */ jsx7("button", { type: "button", className: "fe-selection__clear", "aria-label": "Clear selection", onClick: clear }),
557
- open && menuPosition && createPortal2(/* @__PURE__ */ jsxs7("div", { ref: menuRef, id: listboxId, className: "fe-selection__menu", style: { position: "fixed", top: menuPosition.top, left: menuPosition.left, width: menuPosition.width }, role: "listbox", "aria-multiselectable": multiple || void 0, children: [
558
- searchable && /* @__PURE__ */ jsxs7("div", { className: "fe-selection__search", children: [
559
- /* @__PURE__ */ jsx7("span", { "aria-hidden": "true", children: "\u2315" }),
560
- /* @__PURE__ */ jsx7("input", { autoFocus: true, value: query, onChange: (event) => {
561
- setQuery(event.target.value);
562
- setActiveIndex(0);
563
- }, placeholder: "Search\u2026", "aria-label": "Search options" })
564
- ] }),
565
- /* @__PURE__ */ jsx7("div", { className: "fe-selection__options", children: filteredOptions.length ? filteredOptions.map((option, index) => {
566
- const isSelected = selectedValues.some((item) => String(item) === String(option.value));
567
- return /* @__PURE__ */ jsxs7("button", { type: "button", className: [isSelected && "is-selected", index === activeIndex && "is-active"].filter(Boolean).join(" "), role: "option", "aria-selected": isSelected, disabled: option.disabled, onMouseMove: () => setActiveIndex(index), onClick: () => choose(option), children: [
568
- /* @__PURE__ */ jsx7("span", { children: option.label }),
569
- isSelected && /* @__PURE__ */ jsx7("span", { className: "fe-selection__check", "aria-hidden": "true", children: "\u2713" })
570
- ] }, String(option.value));
571
- }) : /* @__PURE__ */ jsx7("p", { className: "fe-selection__empty", children: "No matching options" }) })
572
- ] }), document.body)
573
- ] }),
574
- helperText && /* @__PURE__ */ jsx7("span", { className: "fe-selection__helper", children: helperText })
575
- ] });
576
- });
864
+ };
865
+ const displayLabel = selectedOptions.length ? selectedOptions.map((option) => option.label) : null;
866
+ const onTriggerKeyDown = (event) => {
867
+ onKeyDown?.(event);
868
+ if (disabled) return;
869
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
870
+ event.preventDefault();
871
+ setOpen(true);
872
+ setActiveIndex(
873
+ (current) => Math.max(
874
+ 0,
875
+ Math.min(
876
+ filteredOptions.length - 1,
877
+ current + (event.key === "ArrowDown" ? 1 : -1)
878
+ )
879
+ )
880
+ );
881
+ }
882
+ if (event.key === "Enter" || event.key === " ") {
883
+ event.preventDefault();
884
+ if (!open) setOpen(true);
885
+ else if (filteredOptions[activeIndex])
886
+ choose(filteredOptions[activeIndex]);
887
+ }
888
+ if (event.key === "Escape") setOpen(false);
889
+ };
890
+ return /* @__PURE__ */ jsxs10(
891
+ "div",
892
+ {
893
+ ref,
894
+ className: [
895
+ "fe-selection",
896
+ "fe-selection--" + size,
897
+ open && "fe-selection--open",
898
+ clearable && selectedOptions.length > 0 && "fe-selection--clearable",
899
+ hasError && "fe-selection--error",
900
+ disabled && "fe-selection--disabled",
901
+ className
902
+ ].filter(Boolean).join(" "),
903
+ ...props,
904
+ children: [
905
+ /* @__PURE__ */ jsx10(
906
+ FieldLabel,
907
+ {
908
+ id: labelId,
909
+ label,
910
+ description: resolvedDescription,
911
+ descriptionDisplay,
912
+ isRequired
913
+ }
914
+ ),
915
+ /* @__PURE__ */ jsxs10("div", { ref: rootRef, className: "fe-selection__control", children: [
916
+ name && selectedValues.map((item) => /* @__PURE__ */ jsx10(
917
+ "input",
918
+ {
919
+ type: "hidden",
920
+ name: multiple ? name + "[]" : name,
921
+ value: item
922
+ },
923
+ String(item)
924
+ )),
925
+ /* @__PURE__ */ jsxs10(
926
+ "button",
927
+ {
928
+ id: triggerId,
929
+ type: "button",
930
+ className: "fe-selection__trigger",
931
+ disabled,
932
+ "aria-label": ariaLabel,
933
+ "aria-invalid": hasError || void 0,
934
+ "aria-required": isRequired || void 0,
935
+ "aria-labelledby": labelledBy,
936
+ "aria-describedby": describedBy,
937
+ "aria-haspopup": "listbox",
938
+ "aria-expanded": open,
939
+ "aria-controls": listboxId,
940
+ onClick: () => setOpen((current) => !current),
941
+ onKeyDown: onTriggerKeyDown,
942
+ children: [
943
+ /* @__PURE__ */ jsx10(
944
+ "span",
945
+ {
946
+ className: [
947
+ "fe-selection__value",
948
+ !selectedOptions.length && "is-placeholder",
949
+ tag && selectedOptions.length > 1 && "is-tags"
950
+ ].filter(Boolean).join(" "),
951
+ children: displayLabel ? tag && multiple ? selectedOptions.map((option) => /* @__PURE__ */ jsxs10(
952
+ "span",
953
+ {
954
+ className: "fe-selection__tag",
955
+ children: [
956
+ option.label,
957
+ /* @__PURE__ */ jsx10("span", { "aria-hidden": "true", children: "\xD7" })
958
+ ]
959
+ },
960
+ String(option.value)
961
+ )) : displayLabel.map((item, index) => /* @__PURE__ */ jsxs10("span", { children: [
962
+ item,
963
+ index < displayLabel.length - 1 ? ", " : ""
964
+ ] }, index)) : /* @__PURE__ */ jsxs10(Fragment2, { children: [
965
+ /* @__PURE__ */ jsx10("span", { children: placeholder }),
966
+ isRequired && /* @__PURE__ */ jsx10("span", { className: "fe-field__required", "aria-hidden": "true", children: "*" })
967
+ ] })
968
+ }
969
+ ),
970
+ /* @__PURE__ */ jsx10("span", { className: "fe-selection__actions", children: /* @__PURE__ */ jsx10("span", { className: "fe-selection__chevron", "aria-hidden": "true" }) })
971
+ ]
972
+ }
973
+ ),
974
+ clearable && selectedOptions.length > 0 && !disabled && /* @__PURE__ */ jsx10(
975
+ "button",
976
+ {
977
+ type: "button",
978
+ className: "fe-selection__clear",
979
+ "aria-label": "Clear selection",
980
+ onClick: clear
981
+ }
982
+ ),
983
+ open && menuPosition && createPortal2(
984
+ /* @__PURE__ */ jsxs10(
985
+ "div",
986
+ {
987
+ ref: menuRef,
988
+ id: listboxId,
989
+ className: "fe-selection__menu",
990
+ style: {
991
+ position: "fixed",
992
+ top: menuPosition.top,
993
+ left: menuPosition.left,
994
+ width: menuPosition.width
995
+ },
996
+ role: "listbox",
997
+ "aria-multiselectable": multiple || void 0,
998
+ children: [
999
+ searchable && /* @__PURE__ */ jsxs10("div", { className: "fe-selection__search", children: [
1000
+ /* @__PURE__ */ jsx10("span", { "aria-hidden": "true", children: "\u2315" }),
1001
+ /* @__PURE__ */ jsx10(
1002
+ "input",
1003
+ {
1004
+ autoFocus: true,
1005
+ value: query,
1006
+ onChange: (event) => {
1007
+ setQuery(event.target.value);
1008
+ setActiveIndex(0);
1009
+ },
1010
+ placeholder: "Search\u2026",
1011
+ "aria-label": "Search options"
1012
+ }
1013
+ )
1014
+ ] }),
1015
+ /* @__PURE__ */ jsx10("div", { className: "fe-selection__options", children: filteredOptions.length ? filteredOptions.map((option, index) => {
1016
+ const isSelected = selectedValues.some(
1017
+ (item) => String(item) === String(option.value)
1018
+ );
1019
+ return /* @__PURE__ */ jsxs10(
1020
+ "button",
1021
+ {
1022
+ type: "button",
1023
+ className: [
1024
+ isSelected && "is-selected",
1025
+ index === activeIndex && "is-active"
1026
+ ].filter(Boolean).join(" "),
1027
+ role: "option",
1028
+ "aria-selected": isSelected,
1029
+ disabled: option.disabled,
1030
+ onMouseMove: () => setActiveIndex(index),
1031
+ onClick: () => choose(option),
1032
+ children: [
1033
+ /* @__PURE__ */ jsx10("span", { children: option.label }),
1034
+ isSelected && /* @__PURE__ */ jsx10(
1035
+ "span",
1036
+ {
1037
+ className: "fe-selection__check",
1038
+ "aria-hidden": "true",
1039
+ children: "\u2713"
1040
+ }
1041
+ )
1042
+ ]
1043
+ },
1044
+ String(option.value)
1045
+ );
1046
+ }) : /* @__PURE__ */ jsx10("p", { className: "fe-selection__empty", children: "No matching options" }) })
1047
+ ]
1048
+ }
1049
+ ),
1050
+ document.body
1051
+ )
1052
+ ] }),
1053
+ /* @__PURE__ */ jsx10(
1054
+ FieldMessage,
1055
+ {
1056
+ id: messageId2,
1057
+ error: fieldError,
1058
+ description: resolvedDescription,
1059
+ descriptionDisplay
1060
+ }
1061
+ )
1062
+ ]
1063
+ }
1064
+ );
1065
+ }
1066
+ );
577
1067
  Selection.displayName = "Selection";
1068
+
1069
+ // packages/form-controls/src/controls/NumberInput/number-input.tsx
1070
+ import { forwardRef as forwardRef6, useEffect as useEffect4, useId as useId5, useState as useState7 } from "react";
1071
+ import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
578
1072
  function formatNumber(value, decimals = 2, thousandSeparator = ",", decimalSeparator = ".") {
579
1073
  return new Intl.NumberFormat("en-US", {
580
1074
  minimumFractionDigits: 0,
@@ -583,7 +1077,7 @@ function formatNumber(value, decimals = 2, thousandSeparator = ",", decimalSepar
583
1077
  }).format(value).replace(/,/g, thousandSeparator).replace(/\./g, decimalSeparator);
584
1078
  }
585
1079
  function escapeRegExp(value) {
586
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1080
+ return value.replace(/[.*+?^$\x7B\x7D()|[\]\\]/g, "\\$&");
587
1081
  }
588
1082
  function groupInteger(value, separator) {
589
1083
  return value.replace(/\B(?=(\d{3})+(?!\d))/g, separator);
@@ -592,7 +1086,10 @@ function normalizeNumberInput(raw, options) {
592
1086
  const { allowDecimal, decimalSeparator, thousandSeparator, min, max } = options;
593
1087
  const decimals = Math.max(0, options.decimals);
594
1088
  const negative = raw.trimStart().startsWith("-") && (min === void 0 || min < 0);
595
- const decimalExpression = new RegExp(`[^0-9${allowDecimal ? escapeRegExp(decimalSeparator) : ""}]`, "g");
1089
+ const decimalExpression = new RegExp(
1090
+ "[^0-9" + (allowDecimal ? escapeRegExp(decimalSeparator) : "") + "]",
1091
+ "g"
1092
+ );
596
1093
  const cleaned = raw.replace(decimalExpression, "");
597
1094
  const decimalIndex = allowDecimal ? cleaned.indexOf(decimalSeparator) : -1;
598
1095
  const hasDecimal = decimalIndex >= 0;
@@ -600,64 +1097,227 @@ function normalizeNumberInput(raw, options) {
600
1097
  const rawFraction = hasDecimal ? cleaned.slice(decimalIndex + decimalSeparator.length).replace(new RegExp(escapeRegExp(decimalSeparator), "g"), "") : "";
601
1098
  const integer = rawInteger.replace(/^0+(?=\d)/, "") || (rawInteger ? "0" : "");
602
1099
  const fraction = rawFraction.slice(0, decimals);
603
- if (!integer && !fraction) return { display: negative ? "-" : "", value: null };
604
- const numericValue = Number(`${negative ? "-" : ""}${integer || "0"}${hasDecimal ? `.${fraction || "0"}` : ""}`);
1100
+ if (!integer && !fraction)
1101
+ return { display: negative ? "-" : "", value: null };
1102
+ const numericValue = Number(
1103
+ (negative ? "-" : "") + (integer || "0") + (hasDecimal ? "." + (fraction || "0") : "")
1104
+ );
605
1105
  if (!Number.isFinite(numericValue)) return { display: "", value: null };
606
1106
  const lowerBound = min === void 0 ? numericValue : Math.max(numericValue, min);
607
1107
  const value = max === void 0 ? lowerBound : Math.min(lowerBound, max);
608
- if (value !== numericValue) return { display: formatNumber(value, decimals, thousandSeparator, decimalSeparator), value };
609
- return { display: `${negative ? "-" : ""}${groupInteger(integer || "0", thousandSeparator)}${hasDecimal ? `${decimalSeparator}${fraction}` : ""}`, value };
610
- }
611
- var NumberInput = forwardRef3(function NumberInput2({ value, defaultValue = null, onValueChange, allowDecimal = true, decimals = 2, min, max, decimalSeparator = ".", thousandSeparator = ",", label, helperText, error, errorMessage, className, onBlur, onFocus, "aria-describedby": ariaDescribedBy, ...props }, ref) {
612
- const generatedId = useId();
613
- const messageId2 = `${generatedId}-message`;
614
- const isControlled = value !== void 0;
615
- const [internalValue, setInternalValue] = useState3(defaultValue);
616
- const [focused, setFocused] = useState3(false);
617
- const actualValue = isControlled ? value ?? null : internalValue;
618
- const [text, setText] = useState3(actualValue === null ? "" : formatNumber(actualValue, decimals, thousandSeparator, decimalSeparator));
619
- const fieldError = getFieldError(error, errorMessage);
620
- const hasError = fieldError !== void 0 && fieldError !== false && fieldError !== null;
621
- const displayedMessage = hasError ? fieldError : helperText;
622
- const describedBy = getDescribedBy(ariaDescribedBy, displayedMessage ? messageId2 : void 0);
623
- useEffect3(() => {
624
- if (!focused) setText(actualValue === null ? "" : formatNumber(actualValue, decimals, thousandSeparator, decimalSeparator));
625
- }, [actualValue, decimalSeparator, decimals, focused, thousandSeparator]);
626
- const updateValue = (nextText) => {
627
- const next = normalizeNumberInput(nextText, { allowDecimal, decimals, decimalSeparator, thousandSeparator, min, max });
628
- setText(next.display);
629
- const nextValue = next.value;
630
- if (!isControlled) setInternalValue(nextValue);
631
- onValueChange?.(nextValue);
1108
+ if (value !== numericValue)
1109
+ return {
1110
+ display: formatNumber(
1111
+ value,
1112
+ decimals,
1113
+ thousandSeparator,
1114
+ decimalSeparator
1115
+ ),
1116
+ value
1117
+ };
1118
+ return {
1119
+ display: (negative ? "-" : "") + groupInteger(integer || "0", thousandSeparator) + (hasDecimal ? decimalSeparator + fraction : ""),
1120
+ value
632
1121
  };
633
- return /* @__PURE__ */ jsxs7("label", { className: ["fe-number-input", hasError && "fe-number-input--error", className].filter(Boolean).join(" "), children: [
634
- label && /* @__PURE__ */ jsx7("span", { className: "fe-number-input__label", children: label }),
635
- /* @__PURE__ */ jsx7("input", { ref, inputMode: allowDecimal ? "decimal" : "numeric", value: text, onFocus: (event) => {
636
- setFocused(true);
637
- onFocus?.(event);
638
- }, onChange: (event) => updateValue(event.target.value), onBlur: (event) => {
639
- setFocused(false);
640
- onBlur?.(event);
641
- }, ...props, "aria-invalid": hasError || void 0, "aria-describedby": describedBy }),
642
- displayedMessage && /* @__PURE__ */ jsx7("span", { id: messageId2, className: hasError ? "fe-number-input__error" : "fe-number-input__helper", children: displayedMessage })
643
- ] });
644
- });
1122
+ }
1123
+ var NumberInput = forwardRef6(
1124
+ function NumberInput2({
1125
+ value,
1126
+ defaultValue = null,
1127
+ onValueChange,
1128
+ allowDecimal = true,
1129
+ decimals = 2,
1130
+ min,
1131
+ max,
1132
+ decimalSeparator = ".",
1133
+ thousandSeparator = ",",
1134
+ label,
1135
+ description,
1136
+ descriptionDisplay = "inline",
1137
+ helperText,
1138
+ error,
1139
+ errorMessage,
1140
+ isRequired = false,
1141
+ className,
1142
+ onBlur,
1143
+ onFocus,
1144
+ placeholder,
1145
+ required,
1146
+ endAdornment,
1147
+ "aria-describedby": ariaDescribedBy,
1148
+ "aria-labelledby": ariaLabelledBy,
1149
+ ...props
1150
+ }, ref) {
1151
+ const generatedId = useId5();
1152
+ const messageId2 = generatedId + "-message";
1153
+ const isControlled = value !== void 0;
1154
+ const [internalValue, setInternalValue] = useState7(defaultValue);
1155
+ const [focused, setFocused] = useState7(false);
1156
+ const actualValue = isControlled ? value ?? null : internalValue;
1157
+ const [text, setText] = useState7(
1158
+ actualValue === null ? "" : formatNumber(
1159
+ actualValue,
1160
+ decimals,
1161
+ thousandSeparator,
1162
+ decimalSeparator
1163
+ )
1164
+ );
1165
+ const fieldError = getFieldError(error, errorMessage);
1166
+ const hasError = fieldError !== void 0 && fieldError !== false && fieldError !== null;
1167
+ const labelId = generatedId + "-label";
1168
+ const resolvedDescription = description ?? helperText;
1169
+ const hasMessage = hasError || resolvedDescription && descriptionDisplay === "inline";
1170
+ const describedBy = getDescribedBy(
1171
+ ariaDescribedBy,
1172
+ hasMessage ? messageId2 : void 0
1173
+ );
1174
+ const labelledBy = getDescribedBy(
1175
+ ariaLabelledBy,
1176
+ label ? labelId : void 0
1177
+ );
1178
+ useEffect4(() => {
1179
+ if (!focused)
1180
+ setText(
1181
+ actualValue === null ? "" : formatNumber(
1182
+ actualValue,
1183
+ decimals,
1184
+ thousandSeparator,
1185
+ decimalSeparator
1186
+ )
1187
+ );
1188
+ }, [actualValue, decimalSeparator, decimals, focused, thousandSeparator]);
1189
+ const updateValue = (nextText) => {
1190
+ const next = normalizeNumberInput(nextText, {
1191
+ allowDecimal,
1192
+ decimals,
1193
+ decimalSeparator,
1194
+ thousandSeparator,
1195
+ min,
1196
+ max
1197
+ });
1198
+ setText(next.display);
1199
+ if (!isControlled) setInternalValue(next.value);
1200
+ onValueChange?.(next.value);
1201
+ };
1202
+ return /* @__PURE__ */ jsxs11(
1203
+ "label",
1204
+ {
1205
+ className: [
1206
+ "fe-number-input",
1207
+ hasError && "fe-number-input--error",
1208
+ className
1209
+ ].filter(Boolean).join(" "),
1210
+ children: [
1211
+ /* @__PURE__ */ jsx11(
1212
+ FieldLabel,
1213
+ {
1214
+ id: labelId,
1215
+ label,
1216
+ description: resolvedDescription,
1217
+ descriptionDisplay,
1218
+ isRequired
1219
+ }
1220
+ ),
1221
+ /* @__PURE__ */ jsxs11("span", { className: "fe-number-input__control", children: [
1222
+ /* @__PURE__ */ jsx11(
1223
+ "input",
1224
+ {
1225
+ ref,
1226
+ inputMode: allowDecimal ? "decimal" : "numeric",
1227
+ value: text,
1228
+ placeholder,
1229
+ required: isRequired || required,
1230
+ onFocus: (event) => {
1231
+ setFocused(true);
1232
+ onFocus?.(event);
1233
+ },
1234
+ onChange: (event) => updateValue(event.target.value),
1235
+ onBlur: (event) => {
1236
+ setFocused(false);
1237
+ onBlur?.(event);
1238
+ },
1239
+ ...props,
1240
+ "aria-invalid": hasError || void 0,
1241
+ "aria-required": isRequired || void 0,
1242
+ "aria-labelledby": labelledBy,
1243
+ "aria-describedby": describedBy
1244
+ }
1245
+ ),
1246
+ isRequired && placeholder && !text && /* @__PURE__ */ jsxs11("span", { className: "fe-number-input__placeholder", "aria-hidden": "true", children: [
1247
+ /* @__PURE__ */ jsx11("span", { children: placeholder }),
1248
+ /* @__PURE__ */ jsx11("span", { className: "fe-field__required", children: "*" })
1249
+ ] }),
1250
+ endAdornment
1251
+ ] }),
1252
+ /* @__PURE__ */ jsx11(
1253
+ FieldMessage,
1254
+ {
1255
+ id: messageId2,
1256
+ error: fieldError,
1257
+ description: resolvedDescription,
1258
+ descriptionDisplay
1259
+ }
1260
+ )
1261
+ ]
1262
+ }
1263
+ );
1264
+ }
1265
+ );
645
1266
  NumberInput.displayName = "NumberInput";
646
- function CurrencyInput({ suffix = "VND", currencies, currency, defaultCurrency, onCurrencyChange, className, ...props }) {
647
- const [internalCurrency, setInternalCurrency] = useState3(defaultCurrency ?? currencies?.[0]?.code ?? "");
1267
+
1268
+ // packages/form-controls/src/controls/CurrencyInput/currency-input.tsx
1269
+ import { useState as useState8 } from "react";
1270
+ import { jsx as jsx12 } from "react/jsx-runtime";
1271
+ function CurrencyInput({
1272
+ suffix = "VND",
1273
+ currencies,
1274
+ currency,
1275
+ defaultCurrency,
1276
+ onCurrencyChange,
1277
+ className,
1278
+ disabled,
1279
+ ...props
1280
+ }) {
1281
+ const [internalCurrency, setInternalCurrency] = useState8(
1282
+ defaultCurrency ?? currencies?.[0]?.code ?? ""
1283
+ );
648
1284
  const selectedCurrency = currency ?? internalCurrency;
649
1285
  const current = currencies?.find((item) => item.code === selectedCurrency);
650
1286
  const currencySuffix = current?.suffix ?? current?.code ?? suffix;
651
- return /* @__PURE__ */ jsxs7("div", { className: ["fe-currency-input", className].filter(Boolean).join(" "), children: [
652
- /* @__PURE__ */ jsx7(NumberInput, { ...props, className: "fe-currency-input__number" }),
653
- currencies?.length ? /* @__PURE__ */ jsx7("select", { className: "fe-currency-input__currency", "aria-label": "Currency", value: selectedCurrency, onChange: (event) => {
654
- const next = currencies.find((item) => item.code === event.target.value);
655
- if (!next) return;
656
- if (currency === void 0) setInternalCurrency(next.code);
657
- onCurrencyChange?.(next);
658
- }, children: currencies.map((item) => /* @__PURE__ */ jsx7("option", { value: item.code, children: item.label ?? item.code }, item.code)) }) : /* @__PURE__ */ jsx7("span", { className: "fe-currency-input__suffix", children: currencySuffix })
659
- ] });
1287
+ const endAdornment = currencies?.length ? /* @__PURE__ */ jsx12(
1288
+ Selection,
1289
+ {
1290
+ className: "fe-currency-input__currency",
1291
+ "aria-label": "Currency",
1292
+ options: currencies.map((item) => ({
1293
+ label: item.label ?? item.code,
1294
+ value: item.code
1295
+ })),
1296
+ disabled,
1297
+ value: selectedCurrency,
1298
+ size: "small",
1299
+ onChange: (value) => {
1300
+ const next = currencies.find((item) => item.code === String(value));
1301
+ if (!next) return;
1302
+ if (currency === void 0) setInternalCurrency(next.code);
1303
+ onCurrencyChange?.(next);
1304
+ }
1305
+ }
1306
+ ) : /* @__PURE__ */ jsx12("span", { className: "fe-currency-input__suffix", children: currencySuffix });
1307
+ return /* @__PURE__ */ jsx12(
1308
+ NumberInput,
1309
+ {
1310
+ ...props,
1311
+ disabled,
1312
+ className: ["fe-currency-input", className].filter(Boolean).join(" "),
1313
+ endAdornment
1314
+ }
1315
+ );
660
1316
  }
1317
+
1318
+ // packages/form-controls/src/controls/DateTimePicker/date-time-picker.tsx
1319
+ import { useEffect as useEffect5, useId as useId6, useRef as useRef3, useState as useState9 } from "react";
1320
+ import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
661
1321
  var pad = (value) => String(value).padStart(2, "0");
662
1322
  function formatDate(date, format) {
663
1323
  return format.replace(/yyyy/g, String(date.getFullYear())).replace(/MM/g, pad(date.getMonth() + 1)).replace(/dd/g, pad(date.getDate())).replace(/HH/g, pad(date.getHours())).replace(/mm/g, pad(date.getMinutes()));
@@ -675,24 +1335,66 @@ function mergeDateTime(day, time) {
675
1335
  return next;
676
1336
  }
677
1337
  function DateTimePicker(props) {
678
- const { label, format = "dd/MM/yyyy HH:mm", disabled, placeholder, locale = "en-US", className, mode = "single" } = props;
1338
+ const {
1339
+ label,
1340
+ description,
1341
+ descriptionDisplay = "inline",
1342
+ helperText,
1343
+ error,
1344
+ errorMessage,
1345
+ isRequired = false,
1346
+ format = "dd/MM/yyyy HH:mm",
1347
+ disabled,
1348
+ placeholder,
1349
+ locale = "en-US",
1350
+ className,
1351
+ mode = "single",
1352
+ id,
1353
+ "aria-describedby": ariaDescribedBy,
1354
+ "aria-labelledby": ariaLabelledBy
1355
+ } = props;
1356
+ const generatedId = useId6();
1357
+ const triggerId = id ?? generatedId + "-trigger";
1358
+ const labelId = generatedId + "-label";
1359
+ const messageId2 = generatedId + "-message";
1360
+ const fieldError = getFieldError(error, errorMessage);
1361
+ const hasError = fieldError !== void 0 && fieldError !== false && fieldError !== null;
1362
+ const resolvedDescription = description ?? helperText;
1363
+ const hasMessage = hasError || resolvedDescription && descriptionDisplay === "inline";
1364
+ const describedBy = getDescribedBy(
1365
+ ariaDescribedBy,
1366
+ hasMessage ? messageId2 : void 0
1367
+ );
1368
+ const labelledBy = getDescribedBy(
1369
+ ariaLabelledBy,
1370
+ label ? labelId : void 0
1371
+ );
679
1372
  const isRange = mode === "range";
680
1373
  const controlled = props.value !== void 0;
681
- const [singleInternal, setSingleInternal] = useState3((!isRange ? props.defaultValue : null) ?? null);
682
- const [rangeInternal, setRangeInternal] = useState3((isRange ? props.defaultValue : void 0) ?? [null, null]);
1374
+ const [singleInternal, setSingleInternal] = useState9(
1375
+ (!isRange ? props.defaultValue : null) ?? null
1376
+ );
1377
+ const [rangeInternal, setRangeInternal] = useState9(
1378
+ (isRange ? props.defaultValue : void 0) ?? [null, null]
1379
+ );
683
1380
  const singleValue = !isRange ? props.value ?? singleInternal : null;
684
1381
  const rangeValue = isRange ? props.value ?? rangeInternal : [null, null];
685
- const [open, setOpen] = useState3(false);
686
- const [month, setMonth] = useState3(() => new Date((isRange ? rangeValue[0] : singleValue) ?? /* @__PURE__ */ new Date()));
687
- const [editingEnd, setEditingEnd] = useState3(false);
688
- const rootRef = useRef2(null);
689
- useEffect3(() => {
1382
+ const [open, setOpen] = useState9(false);
1383
+ const [month, setMonth] = useState9(
1384
+ () => new Date((isRange ? rangeValue[0] : singleValue) ?? /* @__PURE__ */ new Date())
1385
+ );
1386
+ const [editingEnd, setEditingEnd] = useState9(false);
1387
+ const rootRef = useRef3(null);
1388
+ useEffect5(() => {
690
1389
  const onPointerDown = (event) => {
691
1390
  if (!rootRef.current?.contains(event.target)) setOpen(false);
692
1391
  };
693
1392
  document.addEventListener("mousedown", onPointerDown);
694
1393
  return () => document.removeEventListener("mousedown", onPointerDown);
695
1394
  }, []);
1395
+ useEffect5(() => {
1396
+ if (disabled) setOpen(false);
1397
+ }, [disabled]);
696
1398
  const setSingle = (next) => {
697
1399
  if (!controlled) setSingleInternal(next);
698
1400
  props.onChange?.(next);
@@ -703,13 +1405,24 @@ function DateTimePicker(props) {
703
1405
  };
704
1406
  const selectDay = (day) => {
705
1407
  if (!isRange) {
706
- setSingle(mergeDateTime(day, singleValue ? `${pad(singleValue.getHours())}:${pad(singleValue.getMinutes())}` : "00:00"));
1408
+ setSingle(
1409
+ mergeDateTime(
1410
+ day,
1411
+ singleValue ? pad(singleValue.getHours()) + ":" + pad(singleValue.getMinutes()) : "00:00"
1412
+ )
1413
+ );
707
1414
  setOpen(false);
708
1415
  return;
709
1416
  }
710
1417
  const [start, end] = rangeValue;
711
1418
  if (!start || end || editingEnd) {
712
- setRange([mergeDateTime(day, start ? `${pad(start.getHours())}:${pad(start.getMinutes())}` : "00:00"), null]);
1419
+ setRange([
1420
+ mergeDateTime(
1421
+ day,
1422
+ start ? pad(start.getHours()) + ":" + pad(start.getMinutes()) : "00:00"
1423
+ ),
1424
+ null
1425
+ ]);
713
1426
  setEditingEnd(false);
714
1427
  return;
715
1428
  }
@@ -717,97 +1430,200 @@ function DateTimePicker(props) {
717
1430
  setRange(nextEnd < start ? [nextEnd, start] : [start, nextEnd]);
718
1431
  setEditingEnd(false);
719
1432
  };
720
- const shownValue = isRange ? [rangeValue[0] && formatDate(rangeValue[0], format), rangeValue[1] && formatDate(rangeValue[1], format)].filter(Boolean).join(" \u2014 ") : singleValue && formatDate(singleValue, format);
1433
+ const shownValue = isRange ? [
1434
+ rangeValue[0] && formatDate(rangeValue[0], format),
1435
+ rangeValue[1] && formatDate(rangeValue[1], format)
1436
+ ].filter(Boolean).join(" \u2014 ") : singleValue && formatDate(singleValue, format);
721
1437
  const firstDay = new Date(month.getFullYear(), month.getMonth(), 1);
722
1438
  const offset = (firstDay.getDay() + 6) % 7;
723
- const days = Array.from({ length: 42 }, (_, index) => new Date(month.getFullYear(), month.getMonth(), index - offset + 1));
1439
+ const days = Array.from(
1440
+ { length: 42 },
1441
+ (_, index) => new Date(month.getFullYear(), month.getMonth(), index - offset + 1)
1442
+ );
724
1443
  const selectedForTime = isRange ? editingEnd ? rangeValue[1] : rangeValue[0] : singleValue;
725
1444
  const setTime = (time) => {
726
1445
  if (!selectedForTime) return;
727
1446
  const next = mergeDateTime(selectedForTime, time);
728
- if (isRange) setRange(editingEnd ? [rangeValue[0], next] : [next, rangeValue[1]]);
1447
+ if (isRange)
1448
+ setRange(editingEnd ? [rangeValue[0], next] : [next, rangeValue[1]]);
729
1449
  else setSingle(next);
730
1450
  };
731
- return /* @__PURE__ */ jsxs7("div", { ref: rootRef, className: ["fe-datetime-picker", className].filter(Boolean).join(" "), children: [
732
- label && /* @__PURE__ */ jsx7("span", { className: "fe-datetime-picker__label", children: label }),
733
- /* @__PURE__ */ jsxs7("button", { type: "button", className: "fe-datetime-picker__trigger", disabled, "aria-expanded": open, onClick: () => setOpen((current) => !current), children: [
734
- /* @__PURE__ */ jsx7("span", { "aria-hidden": "true", children: "\u25F7" }),
735
- /* @__PURE__ */ jsx7("span", { children: shownValue || placeholder || (isRange ? "Select date range" : "Select date and time") })
736
- ] }),
737
- open && /* @__PURE__ */ jsxs7("div", { className: "fe-datetime-picker__popper", role: "dialog", "aria-label": "Date and time picker", children: [
738
- /* @__PURE__ */ jsxs7("div", { className: "fe-datetime-picker__month", children: [
739
- /* @__PURE__ */ jsx7("button", { type: "button", "aria-label": "Previous month", onClick: () => setMonth((current) => new Date(current.getFullYear(), current.getMonth() - 1, 1)), children: "\u2039" }),
740
- /* @__PURE__ */ jsx7("strong", { children: month.toLocaleDateString(locale, { month: "long", year: "numeric" }) }),
741
- /* @__PURE__ */ jsx7("button", { type: "button", "aria-label": "Next month", onClick: () => setMonth((current) => new Date(current.getFullYear(), current.getMonth() + 1, 1)), children: "\u203A" })
742
- ] }),
743
- /* @__PURE__ */ jsx7("div", { className: "fe-datetime-picker__weekdays", children: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"].map((day) => /* @__PURE__ */ jsx7("span", { children: day }, day)) }),
744
- /* @__PURE__ */ jsx7("div", { className: "fe-datetime-picker__days", children: days.map((day) => {
745
- const inMonth = day.getMonth() === month.getMonth();
746
- const selected = isRange ? sameDay(day, rangeValue[0]) || sameDay(day, rangeValue[1]) : sameDay(day, singleValue);
747
- const inRange = isRange && rangeValue[0] && rangeValue[1] && day > startOfDay(rangeValue[0]) && day < startOfDay(rangeValue[1]);
748
- return /* @__PURE__ */ jsx7("button", { type: "button", className: [!inMonth && "is-other-month", selected && "is-selected", inRange && "is-in-range"].filter(Boolean).join(" "), onClick: () => selectDay(day), children: day.getDate() }, day.toISOString());
749
- }) }),
750
- isRange && /* @__PURE__ */ jsxs7("div", { className: "fe-datetime-picker__range-tabs", children: [
751
- /* @__PURE__ */ jsx7("button", { type: "button", className: !editingEnd ? "is-active" : "", onClick: () => setEditingEnd(false), children: "Start" }),
752
- /* @__PURE__ */ jsx7("button", { type: "button", className: editingEnd ? "is-active" : "", onClick: () => setEditingEnd(true), children: "End" })
753
- ] }),
754
- /* @__PURE__ */ jsxs7("label", { className: "fe-datetime-picker__time", children: [
755
- "Time",
756
- /* @__PURE__ */ jsx7("input", { type: "time", value: selectedForTime ? `${pad(selectedForTime.getHours())}:${pad(selectedForTime.getMinutes())}` : "00:00", onChange: (event) => setTime(event.target.value), disabled: !selectedForTime })
757
- ] })
758
- ] })
759
- ] });
760
- }
761
-
762
- // packages/tooltip/src/index.tsx
763
- import { cloneElement, useId as useId2, useState as useState4 } from "react";
764
- import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
765
- function Tooltip({ content, children, placement = "top", disabled, className, ...props }) {
766
- const [visible, setVisible] = useState4(false);
767
- const id = useId2();
768
- const trigger = cloneElement(children, { "aria-describedby": visible ? id : void 0, onMouseEnter: (event) => {
769
- children.props.onMouseEnter?.(event);
770
- setVisible(true);
771
- }, onMouseLeave: (event) => {
772
- children.props.onMouseLeave?.(event);
773
- setVisible(false);
774
- }, onFocus: (event) => {
775
- children.props.onFocus?.(event);
776
- setVisible(true);
777
- }, onBlur: (event) => {
778
- children.props.onBlur?.(event);
779
- setVisible(false);
780
- } });
781
- return /* @__PURE__ */ jsxs8("span", { className: ["fe-tooltip", `fe-tooltip--${placement}`, className].filter(Boolean).join(" "), ...props, children: [
782
- trigger,
783
- visible && !disabled && /* @__PURE__ */ jsx8("span", { id, role: "tooltip", className: "fe-tooltip__content", children: content })
784
- ] });
1451
+ return /* @__PURE__ */ jsxs12(
1452
+ "div",
1453
+ {
1454
+ ref: rootRef,
1455
+ className: [
1456
+ "fe-datetime-picker",
1457
+ hasError && "fe-datetime-picker--error",
1458
+ className
1459
+ ].filter(Boolean).join(" "),
1460
+ children: [
1461
+ /* @__PURE__ */ jsx13(
1462
+ FieldLabel,
1463
+ {
1464
+ id: labelId,
1465
+ label,
1466
+ description: resolvedDescription,
1467
+ descriptionDisplay,
1468
+ isRequired
1469
+ }
1470
+ ),
1471
+ /* @__PURE__ */ jsxs12(
1472
+ "button",
1473
+ {
1474
+ id: triggerId,
1475
+ type: "button",
1476
+ className: "fe-datetime-picker__trigger",
1477
+ disabled,
1478
+ "aria-invalid": hasError || void 0,
1479
+ "aria-required": isRequired || void 0,
1480
+ "aria-labelledby": labelledBy,
1481
+ "aria-describedby": describedBy,
1482
+ "aria-expanded": open,
1483
+ onClick: () => setOpen((current) => !current),
1484
+ children: [
1485
+ /* @__PURE__ */ jsx13("span", { "aria-hidden": "true", children: "\u25F7" }),
1486
+ /* @__PURE__ */ jsxs12(
1487
+ "span",
1488
+ {
1489
+ className: !shownValue && placeholder ? "fe-datetime-picker__value is-placeholder" : "fe-datetime-picker__value",
1490
+ children: [
1491
+ shownValue || placeholder || (isRange ? "Select date range" : "Select date and time"),
1492
+ isRequired && placeholder && !shownValue && /* @__PURE__ */ jsx13("span", { className: "fe-field__required", "aria-hidden": "true", children: "*" })
1493
+ ]
1494
+ }
1495
+ )
1496
+ ]
1497
+ }
1498
+ ),
1499
+ open && /* @__PURE__ */ jsxs12(
1500
+ "div",
1501
+ {
1502
+ className: "fe-datetime-picker__popper",
1503
+ role: "dialog",
1504
+ "aria-label": "Date and time picker",
1505
+ children: [
1506
+ /* @__PURE__ */ jsxs12("div", { className: "fe-datetime-picker__month", children: [
1507
+ /* @__PURE__ */ jsx13(
1508
+ "button",
1509
+ {
1510
+ type: "button",
1511
+ "aria-label": "Previous month",
1512
+ onClick: () => setMonth(
1513
+ (current) => new Date(current.getFullYear(), current.getMonth() - 1, 1)
1514
+ ),
1515
+ children: "\u2039"
1516
+ }
1517
+ ),
1518
+ /* @__PURE__ */ jsx13("strong", { children: month.toLocaleDateString(locale, {
1519
+ month: "long",
1520
+ year: "numeric"
1521
+ }) }),
1522
+ /* @__PURE__ */ jsx13(
1523
+ "button",
1524
+ {
1525
+ type: "button",
1526
+ "aria-label": "Next month",
1527
+ onClick: () => setMonth(
1528
+ (current) => new Date(current.getFullYear(), current.getMonth() + 1, 1)
1529
+ ),
1530
+ children: "\u203A"
1531
+ }
1532
+ )
1533
+ ] }),
1534
+ /* @__PURE__ */ jsx13("div", { className: "fe-datetime-picker__weekdays", children: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"].map((day) => /* @__PURE__ */ jsx13("span", { children: day }, day)) }),
1535
+ /* @__PURE__ */ jsx13("div", { className: "fe-datetime-picker__days", children: days.map((day) => {
1536
+ const inMonth = day.getMonth() === month.getMonth();
1537
+ const selected = isRange ? sameDay(day, rangeValue[0]) || sameDay(day, rangeValue[1]) : sameDay(day, singleValue);
1538
+ const inRange = isRange && rangeValue[0] && rangeValue[1] && day > startOfDay(rangeValue[0]) && day < startOfDay(rangeValue[1]);
1539
+ return /* @__PURE__ */ jsx13(
1540
+ "button",
1541
+ {
1542
+ type: "button",
1543
+ className: [
1544
+ !inMonth && "is-other-month",
1545
+ selected && "is-selected",
1546
+ inRange && "is-in-range"
1547
+ ].filter(Boolean).join(" "),
1548
+ onClick: () => selectDay(day),
1549
+ children: day.getDate()
1550
+ },
1551
+ day.toISOString()
1552
+ );
1553
+ }) }),
1554
+ isRange && /* @__PURE__ */ jsxs12("div", { className: "fe-datetime-picker__range-tabs", children: [
1555
+ /* @__PURE__ */ jsx13(
1556
+ "button",
1557
+ {
1558
+ type: "button",
1559
+ className: !editingEnd ? "is-active" : "",
1560
+ onClick: () => setEditingEnd(false),
1561
+ children: "Start"
1562
+ }
1563
+ ),
1564
+ /* @__PURE__ */ jsx13(
1565
+ "button",
1566
+ {
1567
+ type: "button",
1568
+ className: editingEnd ? "is-active" : "",
1569
+ onClick: () => setEditingEnd(true),
1570
+ children: "End"
1571
+ }
1572
+ )
1573
+ ] }),
1574
+ /* @__PURE__ */ jsxs12("label", { className: "fe-datetime-picker__time", children: [
1575
+ "Time",
1576
+ /* @__PURE__ */ jsx13(
1577
+ "input",
1578
+ {
1579
+ type: "time",
1580
+ value: selectedForTime ? pad(selectedForTime.getHours()) + ":" + pad(selectedForTime.getMinutes()) : "00:00",
1581
+ onChange: (event) => setTime(event.target.value),
1582
+ disabled: !selectedForTime
1583
+ }
1584
+ )
1585
+ ] })
1586
+ ]
1587
+ }
1588
+ ),
1589
+ /* @__PURE__ */ jsx13(
1590
+ FieldMessage,
1591
+ {
1592
+ id: messageId2,
1593
+ error: fieldError,
1594
+ description: resolvedDescription,
1595
+ descriptionDisplay
1596
+ }
1597
+ )
1598
+ ]
1599
+ }
1600
+ );
785
1601
  }
786
1602
 
787
1603
  // packages/expandable-section/src/index.tsx
788
- import { useId as useId3, useState as useState5 } from "react";
789
- import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
1604
+ import { useId as useId7, useState as useState10 } from "react";
1605
+ import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
790
1606
  function ExpandableSection({ title, children, expanded, defaultExpanded = false, onExpandedChange, disabled, className, ...props }) {
791
- const [internalExpanded, setInternalExpanded] = useState5(defaultExpanded);
1607
+ const [internalExpanded, setInternalExpanded] = useState10(defaultExpanded);
792
1608
  const isExpanded = expanded ?? internalExpanded;
793
- const id = useId3();
1609
+ const id = useId7();
794
1610
  const toggle = () => {
795
1611
  if (disabled) return;
796
1612
  const next = !isExpanded;
797
1613
  if (expanded === void 0) setInternalExpanded(next);
798
1614
  onExpandedChange?.(next);
799
1615
  };
800
- return /* @__PURE__ */ jsxs9("section", { className: ["fe-expandable-section", isExpanded && "fe-expandable-section--expanded", disabled && "fe-expandable-section--disabled", className].filter(Boolean).join(" "), ...props, children: [
801
- /* @__PURE__ */ jsxs9("button", { className: "fe-expandable-section__trigger", type: "button", "aria-expanded": isExpanded, "aria-controls": id, disabled, onClick: toggle, children: [
802
- /* @__PURE__ */ jsx9("span", { children: title }),
803
- /* @__PURE__ */ jsx9("span", { className: "fe-expandable-section__chevron", "aria-hidden": "true" })
1616
+ return /* @__PURE__ */ jsxs13("section", { className: ["fe-expandable-section", isExpanded && "fe-expandable-section--expanded", disabled && "fe-expandable-section--disabled", className].filter(Boolean).join(" "), ...props, children: [
1617
+ /* @__PURE__ */ jsxs13("button", { className: "fe-expandable-section__trigger", type: "button", "aria-expanded": isExpanded, "aria-controls": id, disabled, onClick: toggle, children: [
1618
+ /* @__PURE__ */ jsx14("span", { children: title }),
1619
+ /* @__PURE__ */ jsx14("span", { className: "fe-expandable-section__chevron", "aria-hidden": "true" })
804
1620
  ] }),
805
- /* @__PURE__ */ jsx9("div", { id, className: "fe-expandable-section__content", "aria-hidden": !isExpanded, children: /* @__PURE__ */ jsx9("div", { className: "fe-expandable-section__content-inner", children }) })
1621
+ /* @__PURE__ */ jsx14("div", { id, className: "fe-expandable-section__content", "aria-hidden": !isExpanded, children: /* @__PURE__ */ jsx14("div", { className: "fe-expandable-section__content-inner", children }) })
806
1622
  ] });
807
1623
  }
808
1624
 
809
1625
  // packages/loading/src/index.tsx
810
- import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
1626
+ import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
811
1627
  var sizes = {
812
1628
  small: "16px",
813
1629
  medium: "24px",
@@ -820,15 +1636,15 @@ function Loading({ size = "medium", color = "#2878f0", label, className, style,
820
1636
  "--fe-loading-color": color,
821
1637
  ...style
822
1638
  };
823
- return /* @__PURE__ */ jsxs10("span", { className: ["fe-loading", className].filter(Boolean).join(" "), style: loadingStyle, role: "status", ...props, children: [
824
- /* @__PURE__ */ jsx10("span", { className: "fe-loading__spinner", "aria-hidden": "true" }),
825
- label && /* @__PURE__ */ jsx10("span", { className: "fe-loading__label", children: label }),
826
- !label && /* @__PURE__ */ jsx10("span", { className: "fe-loading__sr-only", children: "Loading" })
1639
+ return /* @__PURE__ */ jsxs14("span", { className: ["fe-loading", className].filter(Boolean).join(" "), style: loadingStyle, role: "status", ...props, children: [
1640
+ /* @__PURE__ */ jsx15("span", { className: "fe-loading__spinner", "aria-hidden": "true" }),
1641
+ label && /* @__PURE__ */ jsx15("span", { className: "fe-loading__label", children: label }),
1642
+ !label && /* @__PURE__ */ jsx15("span", { className: "fe-loading__sr-only", children: "Loading" })
827
1643
  ] });
828
1644
  }
829
1645
 
830
1646
  // packages/skeleton/src/index.tsx
831
- import { Fragment as Fragment2, jsx as jsx11 } from "react/jsx-runtime";
1647
+ import { Fragment as Fragment3, jsx as jsx16 } from "react/jsx-runtime";
832
1648
  var pixels = (value) => typeof value === "number" ? `${value}px` : value;
833
1649
  function SkeletonBase({ variant = "box", shape, width, height, count = 1, animated = true, className, style, ...props }) {
834
1650
  const resolvedVariant = shape ?? variant;
@@ -839,7 +1655,7 @@ function SkeletonBase({ variant = "box", shape, width, height, count = 1, animat
839
1655
  "--fe-skeleton-height": resolvedHeight,
840
1656
  ...style
841
1657
  };
842
- return /* @__PURE__ */ jsx11(Fragment2, { children: Array.from({ length: Math.max(1, count) }, (_, index) => /* @__PURE__ */ jsx11(
1658
+ return /* @__PURE__ */ jsx16(Fragment3, { children: Array.from({ length: Math.max(1, count) }, (_, index) => /* @__PURE__ */ jsx16(
843
1659
  "div",
844
1660
  {
845
1661
  className: ["fe-skeleton", `fe-skeleton--${resolvedVariant}`, animated && "fe-skeleton--animated", className].filter(Boolean).join(" "),
@@ -851,16 +1667,16 @@ function SkeletonBase({ variant = "box", shape, width, height, count = 1, animat
851
1667
  )) });
852
1668
  }
853
1669
  function SkeletonCircle({ size = 40, ...props }) {
854
- return /* @__PURE__ */ jsx11(SkeletonBase, { variant: "circle", width: size, height: size, ...props });
1670
+ return /* @__PURE__ */ jsx16(SkeletonBase, { variant: "circle", width: size, height: size, ...props });
855
1671
  }
856
1672
  function SkeletonSquare({ size = 80, ...props }) {
857
- return /* @__PURE__ */ jsx11(SkeletonBase, { variant: "box", width: size, height: size, ...props });
1673
+ return /* @__PURE__ */ jsx16(SkeletonBase, { variant: "box", width: size, height: size, ...props });
858
1674
  }
859
1675
  function SkeletonBox({ width = "100%", height = 80, ...props }) {
860
- return /* @__PURE__ */ jsx11(SkeletonBase, { variant: "box", width, height, ...props });
1676
+ return /* @__PURE__ */ jsx16(SkeletonBase, { variant: "box", width, height, ...props });
861
1677
  }
862
1678
  function SkeletonLine({ width = "100%", height = 12, ...props }) {
863
- return /* @__PURE__ */ jsx11(SkeletonBase, { variant: "line", width, height, ...props });
1679
+ return /* @__PURE__ */ jsx16(SkeletonBase, { variant: "line", width, height, ...props });
864
1680
  }
865
1681
  var Skeleton = Object.assign(SkeletonBase, {
866
1682
  Circle: SkeletonCircle,
@@ -870,9 +1686,9 @@ var Skeleton = Object.assign(SkeletonBase, {
870
1686
  });
871
1687
 
872
1688
  // packages/modal/src/index.tsx
873
- import { useEffect as useEffect4, useId as useId4, useRef as useRef3 } from "react";
1689
+ import { useEffect as useEffect6, useId as useId8, useRef as useRef4 } from "react";
874
1690
  import { createPortal as createPortal3 } from "react-dom";
875
- import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
1691
+ import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
876
1692
  function Modal({
877
1693
  open,
878
1694
  onClose,
@@ -888,9 +1704,9 @@ function Modal({
888
1704
  className,
889
1705
  ...props
890
1706
  }) {
891
- const titleId = useId4();
892
- const panelRef = useRef3(null);
893
- useEffect4(() => {
1707
+ const titleId = useId8();
1708
+ const panelRef = useRef4(null);
1709
+ useEffect6(() => {
894
1710
  if (!open) return;
895
1711
  const onKeyDown = (event) => {
896
1712
  if (event.key === "Escape") onClose();
@@ -902,9 +1718,9 @@ function Modal({
902
1718
  if (!open || typeof document === "undefined") return null;
903
1719
  const hasFooter = footer || actions.length > 0;
904
1720
  return createPortal3(
905
- /* @__PURE__ */ jsx12("div", { className: "fe-modal-backdrop", role: "presentation", onMouseDown: (event) => {
1721
+ /* @__PURE__ */ jsx17("div", { className: "fe-modal-backdrop", role: "presentation", onMouseDown: (event) => {
906
1722
  if (event.target === event.currentTarget && closeOnBackdropClick) onClose();
907
- }, children: /* @__PURE__ */ jsxs11(
1723
+ }, children: /* @__PURE__ */ jsxs15(
908
1724
  "div",
909
1725
  {
910
1726
  ref: panelRef,
@@ -916,17 +1732,17 @@ function Modal({
916
1732
  tabIndex: -1,
917
1733
  ...props,
918
1734
  children: [
919
- (title || description || closeButton) && /* @__PURE__ */ jsxs11("header", { className: "fe-modal__header", children: [
920
- /* @__PURE__ */ jsxs11("div", { className: "fe-modal__heading", children: [
921
- title && /* @__PURE__ */ jsx12("h2", { id: titleId, children: title }),
922
- description && /* @__PURE__ */ jsx12("p", { children: description })
1735
+ (title || description || closeButton) && /* @__PURE__ */ jsxs15("header", { className: "fe-modal__header", children: [
1736
+ /* @__PURE__ */ jsxs15("div", { className: "fe-modal__heading", children: [
1737
+ title && /* @__PURE__ */ jsx17("h2", { id: titleId, children: title }),
1738
+ description && /* @__PURE__ */ jsx17("p", { children: description })
923
1739
  ] }),
924
- closeButton && /* @__PURE__ */ jsx12(Button, { hierarchy: "tertiary-gray", size: "32", iconOnly: true, icon: /* @__PURE__ */ jsx12(CloseIcon, {}), "aria-label": closeLabel, onClick: onClose })
1740
+ closeButton && /* @__PURE__ */ jsx17(Button, { hierarchy: "tertiary-gray", size: "32", iconOnly: true, icon: /* @__PURE__ */ jsx17(CloseIcon, {}), "aria-label": closeLabel, onClick: onClose })
925
1741
  ] }),
926
- /* @__PURE__ */ jsx12("div", { className: "fe-modal__body", children }),
927
- hasFooter && /* @__PURE__ */ jsxs11("footer", { className: "fe-modal__footer", children: [
928
- footer && /* @__PURE__ */ jsx12("div", { className: "fe-modal__footer-content", children: footer }),
929
- actions.length > 0 && /* @__PURE__ */ jsx12("div", { className: "fe-modal__actions", children: actions.map(({ label, ...action }, index) => /* @__PURE__ */ jsx12(Button, { ...action, children: label }, index)) })
1742
+ /* @__PURE__ */ jsx17("div", { className: "fe-modal__body", children }),
1743
+ hasFooter && /* @__PURE__ */ jsxs15("footer", { className: "fe-modal__footer", children: [
1744
+ footer && /* @__PURE__ */ jsx17("div", { className: "fe-modal__footer-content", children: footer }),
1745
+ actions.length > 0 && /* @__PURE__ */ jsx17("div", { className: "fe-modal__actions", children: actions.map(({ label, ...action }, index) => /* @__PURE__ */ jsx17(Button, { ...action, children: label }, index)) })
930
1746
  ] })
931
1747
  ]
932
1748
  }
@@ -936,7 +1752,7 @@ function Modal({
936
1752
  }
937
1753
 
938
1754
  // packages/progress/src/index.tsx
939
- import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
1755
+ import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
940
1756
  function ProgressBar({ value, max = 100, label, showValue = true, size = "medium", color = "#2878f0", className, style, "aria-label": ariaLabel, ...props }) {
941
1757
  const indeterminate = value === null || value === void 0;
942
1758
  const percentage = indeterminate ? 0 : Math.min(100, Math.max(0, Number(value) / Math.max(1, max) * 100));
@@ -946,17 +1762,17 @@ function ProgressBar({ value, max = 100, label, showValue = true, size = "medium
946
1762
  ...style
947
1763
  };
948
1764
  const visibleValue = `${Math.round(percentage)}%`;
949
- return /* @__PURE__ */ jsxs12("div", { className: ["fe-progress", `fe-progress--${size}`, indeterminate && "fe-progress--indeterminate", className].filter(Boolean).join(" "), style: progressStyle, ...props, children: [
950
- (label || !indeterminate && showValue) && /* @__PURE__ */ jsxs12("div", { className: "fe-progress__meta", children: [
951
- label && /* @__PURE__ */ jsx13("span", { className: "fe-progress__label", children: label }),
952
- !indeterminate && showValue && /* @__PURE__ */ jsx13("output", { className: "fe-progress__value", children: visibleValue })
1765
+ return /* @__PURE__ */ jsxs16("div", { className: ["fe-progress", `fe-progress--${size}`, indeterminate && "fe-progress--indeterminate", className].filter(Boolean).join(" "), style: progressStyle, ...props, children: [
1766
+ (label || !indeterminate && showValue) && /* @__PURE__ */ jsxs16("div", { className: "fe-progress__meta", children: [
1767
+ label && /* @__PURE__ */ jsx18("span", { className: "fe-progress__label", children: label }),
1768
+ !indeterminate && showValue && /* @__PURE__ */ jsx18("output", { className: "fe-progress__value", children: visibleValue })
953
1769
  ] }),
954
- /* @__PURE__ */ jsx13("div", { className: "fe-progress__track", role: "progressbar", "aria-label": ariaLabel ?? (typeof label === "string" ? label : "Progress"), "aria-valuemin": indeterminate ? void 0 : 0, "aria-valuemax": indeterminate ? void 0 : max, "aria-valuenow": indeterminate ? void 0 : Number(value), "aria-valuetext": indeterminate ? "Loading" : visibleValue, children: /* @__PURE__ */ jsx13("span", { className: "fe-progress__indicator" }) })
1770
+ /* @__PURE__ */ jsx18("div", { className: "fe-progress__track", role: "progressbar", "aria-label": ariaLabel ?? (typeof label === "string" ? label : "Progress"), "aria-valuemin": indeterminate ? void 0 : 0, "aria-valuemax": indeterminate ? void 0 : max, "aria-valuenow": indeterminate ? void 0 : Number(value), "aria-valuetext": indeterminate ? "Loading" : visibleValue, children: /* @__PURE__ */ jsx18("span", { className: "fe-progress__indicator" }) })
955
1771
  ] });
956
1772
  }
957
1773
 
958
1774
  // packages/chip/src/index.tsx
959
- import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
1775
+ import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
960
1776
  var statuses = ["default", "info", "success", "warning", "error", "neutral", "pending", "processing"];
961
1777
  function Chip({ children, status = "default", color, variant = "subtle", dot = false, onRemove, removeLabel = "Remove", className, style, ...props }) {
962
1778
  const usesCustomColor = Boolean(color);
@@ -965,16 +1781,16 @@ function Chip({ children, status = "default", color, variant = "subtle", dot = f
965
1781
  ...style
966
1782
  };
967
1783
  const resolvedStatus = statuses.includes(status) ? status : "default";
968
- return /* @__PURE__ */ jsxs13("span", { className: ["fe-chip", `fe-chip--${variant}`, `fe-chip--${usesCustomColor ? "custom" : resolvedStatus}`, className].filter(Boolean).join(" "), style: chipStyle, ...props, children: [
969
- dot && /* @__PURE__ */ jsx14("span", { className: "fe-chip__dot", "aria-hidden": "true" }),
970
- /* @__PURE__ */ jsx14("span", { className: "fe-chip__content", children }),
971
- onRemove && /* @__PURE__ */ jsx14(Button, { hierarchy: "tertiary-gray", size: "24", iconOnly: true, icon: /* @__PURE__ */ jsx14(CloseIcon, { size: 14 }), "aria-label": removeLabel, onClick: onRemove, className: "fe-chip__remove" })
1784
+ return /* @__PURE__ */ jsxs17("span", { className: ["fe-chip", `fe-chip--${variant}`, `fe-chip--${usesCustomColor ? "custom" : resolvedStatus}`, className].filter(Boolean).join(" "), style: chipStyle, ...props, children: [
1785
+ dot && /* @__PURE__ */ jsx19("span", { className: "fe-chip__dot", "aria-hidden": "true" }),
1786
+ /* @__PURE__ */ jsx19("span", { className: "fe-chip__content", children }),
1787
+ onRemove && /* @__PURE__ */ jsx19(Button, { hierarchy: "tertiary-gray", size: "24", iconOnly: true, icon: /* @__PURE__ */ jsx19(CloseIcon, { size: 14 }), "aria-label": removeLabel, onClick: onRemove, className: "fe-chip__remove" })
972
1788
  ] });
973
1789
  }
974
1790
 
975
1791
  // packages/message/src/index.tsx
976
- import { useEffect as useEffect5, useState as useState6 } from "react";
977
- import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
1792
+ import { useEffect as useEffect7, useState as useState11 } from "react";
1793
+ import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
978
1794
  var messageId = 0;
979
1795
  var entries = [];
980
1796
  var listeners = /* @__PURE__ */ new Set();
@@ -1007,22 +1823,22 @@ var message = {
1007
1823
  };
1008
1824
  var icons = { success: "\u2713", info: "i", warning: "!", error: "\xD7" };
1009
1825
  function Message({ maxCount = 4, closeLabel = "Close notification", className, ...props }) {
1010
- const [visibleEntries, setVisibleEntries] = useState6(entries);
1011
- useEffect5(() => {
1826
+ const [visibleEntries, setVisibleEntries] = useState11(entries);
1827
+ useEffect7(() => {
1012
1828
  const listener = (nextEntries) => setVisibleEntries(nextEntries);
1013
1829
  listeners.add(listener);
1014
1830
  return () => {
1015
1831
  listeners.delete(listener);
1016
1832
  };
1017
1833
  }, []);
1018
- return /* @__PURE__ */ jsx15("div", { className: ["fe-message-viewport", className].filter(Boolean).join(" "), "aria-live": "polite", ...props, children: visibleEntries.slice(-Math.max(1, maxCount)).map((entry) => /* @__PURE__ */ jsxs14("div", { className: `fe-message fe-message--${entry.severity ?? "info"}`, role: entry.severity === "error" ? "alert" : "status", children: [
1019
- /* @__PURE__ */ jsx15("span", { className: "fe-message__icon", "aria-hidden": "true", children: icons[entry.severity ?? "info"] }),
1020
- /* @__PURE__ */ jsxs14("div", { className: "fe-message__body", children: [
1021
- entry.title && /* @__PURE__ */ jsx15("strong", { className: "fe-message__title", children: entry.title }),
1022
- /* @__PURE__ */ jsx15("div", { className: "fe-message__content", children: entry.content })
1834
+ return /* @__PURE__ */ jsx20("div", { className: ["fe-message-viewport", className].filter(Boolean).join(" "), "aria-live": "polite", ...props, children: visibleEntries.slice(-Math.max(1, maxCount)).map((entry) => /* @__PURE__ */ jsxs18("div", { className: `fe-message fe-message--${entry.severity ?? "info"}`, role: entry.severity === "error" ? "alert" : "status", children: [
1835
+ /* @__PURE__ */ jsx20("span", { className: "fe-message__icon", "aria-hidden": "true", children: icons[entry.severity ?? "info"] }),
1836
+ /* @__PURE__ */ jsxs18("div", { className: "fe-message__body", children: [
1837
+ entry.title && /* @__PURE__ */ jsx20("strong", { className: "fe-message__title", children: entry.title }),
1838
+ /* @__PURE__ */ jsx20("div", { className: "fe-message__content", children: entry.content })
1023
1839
  ] }),
1024
- entry.action && /* @__PURE__ */ jsx15("span", { className: "fe-message__action", children: entry.action }),
1025
- /* @__PURE__ */ jsx15(Button, { className: "fe-message__close", hierarchy: "tertiary-gray", size: "24", iconOnly: true, icon: "\xD7", "aria-label": closeLabel, onClick: () => dismiss(entry.id) })
1840
+ entry.action && /* @__PURE__ */ jsx20("span", { className: "fe-message__action", children: entry.action }),
1841
+ /* @__PURE__ */ jsx20(Button, { className: "fe-message__close", hierarchy: "tertiary-gray", size: "24", iconOnly: true, icon: "\xD7", "aria-label": closeLabel, onClick: () => dismiss(entry.id) })
1026
1842
  ] }, entry.id)) });
1027
1843
  }
1028
1844
  ((Message2) => {
@@ -1036,8 +1852,8 @@ function Message({ maxCount = 4, closeLabel = "Close notification", className, .
1036
1852
  })(Message || (Message = {}));
1037
1853
 
1038
1854
  // packages/snackbar/src/index.tsx
1039
- import { useEffect as useEffect6 } from "react";
1040
- import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
1855
+ import { useEffect as useEffect8 } from "react";
1856
+ import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
1041
1857
  function Snackbar({
1042
1858
  open,
1043
1859
  message: message2,
@@ -1051,12 +1867,12 @@ function Snackbar({
1051
1867
  }) {
1052
1868
  const vertical = anchorOrigin.vertical ?? "bottom";
1053
1869
  const horizontal = anchorOrigin.horizontal ?? "center";
1054
- useEffect6(() => {
1870
+ useEffect8(() => {
1055
1871
  if (!open || autoHideDuration === null) return void 0;
1056
1872
  const timer = window.setTimeout(() => onClose?.("timeout"), autoHideDuration);
1057
1873
  return () => window.clearTimeout(timer);
1058
1874
  }, [open, autoHideDuration, onClose]);
1059
- useEffect6(() => {
1875
+ useEffect8(() => {
1060
1876
  if (!open) return void 0;
1061
1877
  const onKeyDown = (event) => {
1062
1878
  if (event.key === "Escape") onClose?.("escapeKeyDown");
@@ -1065,10 +1881,10 @@ function Snackbar({
1065
1881
  return () => window.removeEventListener("keydown", onKeyDown);
1066
1882
  }, [open, onClose]);
1067
1883
  if (!open) return null;
1068
- return /* @__PURE__ */ jsx16("div", { className: ["fe-snackbar", `fe-snackbar--${vertical}`, `fe-snackbar--${horizontal}`, className].filter(Boolean).join(" "), ...props, children: /* @__PURE__ */ jsxs15("div", { className: "fe-snackbar__content", role: "status", "aria-live": "polite", children: [
1069
- /* @__PURE__ */ jsx16("span", { className: "fe-snackbar__message", children: message2 }),
1070
- action && /* @__PURE__ */ jsx16("span", { className: "fe-snackbar__action", children: action }),
1071
- onClose && /* @__PURE__ */ jsx16(Button, { className: "fe-snackbar__close", hierarchy: "tertiary-gray", size: "24", iconOnly: true, icon: "\xD7", "aria-label": closeLabel, onClick: () => onClose("closeButton") })
1884
+ return /* @__PURE__ */ jsx21("div", { className: ["fe-snackbar", `fe-snackbar--${vertical}`, `fe-snackbar--${horizontal}`, className].filter(Boolean).join(" "), ...props, children: /* @__PURE__ */ jsxs19("div", { className: "fe-snackbar__content", role: "status", "aria-live": "polite", children: [
1885
+ /* @__PURE__ */ jsx21("span", { className: "fe-snackbar__message", children: message2 }),
1886
+ action && /* @__PURE__ */ jsx21("span", { className: "fe-snackbar__action", children: action }),
1887
+ onClose && /* @__PURE__ */ jsx21(Button, { className: "fe-snackbar__close", hierarchy: "tertiary-gray", size: "24", iconOnly: true, icon: "\xD7", "aria-label": closeLabel, onClick: () => onClose("closeButton") })
1072
1888
  ] }) });
1073
1889
  }
1074
1890
  export {
@@ -1106,7 +1922,24 @@ export {
1106
1922
  TextInput,
1107
1923
  Toggle,
1108
1924
  Tooltip,
1925
+ arrow_left,
1926
+ check_square_fill,
1927
+ chevron_down,
1928
+ chevron_left,
1929
+ chevron_right,
1930
+ chevron_up,
1931
+ copy,
1109
1932
  formatNumber,
1110
1933
  getIconSize,
1111
- message
1934
+ key,
1935
+ lock,
1936
+ lock_unlocked,
1937
+ log_out,
1938
+ message,
1939
+ minus_square,
1940
+ plus,
1941
+ plus_square,
1942
+ search,
1943
+ trash,
1944
+ x_close
1112
1945
  };