@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/README.md +14 -3
- package/dist/chunk-3TCR34LS.mjs +169 -0
- package/dist/icons.d.mts +32 -0
- package/dist/icons.d.ts +32 -0
- package/dist/icons.js +215 -0
- package/dist/icons.mjs +46 -0
- package/dist/index.d.mts +85 -50
- package/dist/index.d.ts +85 -50
- package/dist/index.js +1371 -399
- package/dist/index.mjs +1254 -421
- package/dist/styles.css +417 -97
- package/package.json +8 -3
- package/dist/styles.d.mts +0 -2
- package/dist/styles.d.ts +0 -2
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
|
|
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__ */
|
|
151
|
-
/* @__PURE__ */
|
|
152
|
-
items.map((item, index) => item === "start-ellipsis" || item === "end-ellipsis" ? /* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
272
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
275
|
-
/* @__PURE__ */
|
|
276
|
-
/* @__PURE__ */
|
|
277
|
-
/* @__PURE__ */
|
|
278
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
321
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
322
|
+
return /* @__PURE__ */ jsx3("thead", { ...props });
|
|
325
323
|
}
|
|
326
324
|
function TableBody(props) {
|
|
327
|
-
return /* @__PURE__ */
|
|
325
|
+
return /* @__PURE__ */ jsx3("tbody", { ...props });
|
|
328
326
|
}
|
|
329
327
|
function TableRow({ children, ...props }) {
|
|
330
328
|
const { striped } = useContext(TableContext);
|
|
331
|
-
return /* @__PURE__ */
|
|
329
|
+
return /* @__PURE__ */ jsx3("tr", { "data-striped": striped || void 0, ...props, children });
|
|
332
330
|
}
|
|
333
331
|
function TableCell({ children, ...props }) {
|
|
334
|
-
return /* @__PURE__ */
|
|
332
|
+
return /* @__PURE__ */ jsx3("td", { ...props, children });
|
|
335
333
|
}
|
|
336
334
|
function TableHeader({ children, ...props }) {
|
|
337
|
-
return /* @__PURE__ */
|
|
335
|
+
return /* @__PURE__ */ jsx3("th", { scope: "col", ...props, children });
|
|
338
336
|
}
|
|
339
337
|
function TableCaption(props) {
|
|
340
|
-
return /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
353
|
-
/* @__PURE__ */
|
|
354
|
-
/* @__PURE__ */
|
|
355
|
-
label && /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
378
|
-
/* @__PURE__ */
|
|
379
|
-
title && /* @__PURE__ */
|
|
380
|
-
/* @__PURE__ */
|
|
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__ */
|
|
383
|
-
footer && /* @__PURE__ */
|
|
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/
|
|
388
|
-
import {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
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
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
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
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
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
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
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
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
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
|
-
|
|
506
|
-
|
|
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
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
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(/[
|
|
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(
|
|
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)
|
|
604
|
-
|
|
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)
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
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
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
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
|
-
|
|
647
|
-
|
|
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
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
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 {
|
|
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] =
|
|
682
|
-
|
|
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] =
|
|
686
|
-
const [month, setMonth] =
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
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(
|
|
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([
|
|
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 ? [
|
|
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(
|
|
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)
|
|
1447
|
+
if (isRange)
|
|
1448
|
+
setRange(editingEnd ? [rangeValue[0], next] : [next, rangeValue[1]]);
|
|
729
1449
|
else setSingle(next);
|
|
730
1450
|
};
|
|
731
|
-
return /* @__PURE__ */
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
/* @__PURE__ */
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
/* @__PURE__ */
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
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
|
|
789
|
-
import { jsx as
|
|
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] =
|
|
1607
|
+
const [internalExpanded, setInternalExpanded] = useState10(defaultExpanded);
|
|
792
1608
|
const isExpanded = expanded ?? internalExpanded;
|
|
793
|
-
const id =
|
|
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__ */
|
|
801
|
-
/* @__PURE__ */
|
|
802
|
-
/* @__PURE__ */
|
|
803
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
824
|
-
/* @__PURE__ */
|
|
825
|
-
label && /* @__PURE__ */
|
|
826
|
-
!label && /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
1670
|
+
return /* @__PURE__ */ jsx16(SkeletonBase, { variant: "circle", width: size, height: size, ...props });
|
|
855
1671
|
}
|
|
856
1672
|
function SkeletonSquare({ size = 80, ...props }) {
|
|
857
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
1676
|
+
return /* @__PURE__ */ jsx16(SkeletonBase, { variant: "box", width, height, ...props });
|
|
861
1677
|
}
|
|
862
1678
|
function SkeletonLine({ width = "100%", height = 12, ...props }) {
|
|
863
|
-
return /* @__PURE__ */
|
|
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
|
|
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
|
|
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 =
|
|
892
|
-
const panelRef =
|
|
893
|
-
|
|
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__ */
|
|
1721
|
+
/* @__PURE__ */ jsx17("div", { className: "fe-modal-backdrop", role: "presentation", onMouseDown: (event) => {
|
|
906
1722
|
if (event.target === event.currentTarget && closeOnBackdropClick) onClose();
|
|
907
|
-
}, children: /* @__PURE__ */
|
|
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__ */
|
|
920
|
-
/* @__PURE__ */
|
|
921
|
-
title && /* @__PURE__ */
|
|
922
|
-
description && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
927
|
-
hasFooter && /* @__PURE__ */
|
|
928
|
-
footer && /* @__PURE__ */
|
|
929
|
-
actions.length > 0 && /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
950
|
-
(label || !indeterminate && showValue) && /* @__PURE__ */
|
|
951
|
-
label && /* @__PURE__ */
|
|
952
|
-
!indeterminate && showValue && /* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
969
|
-
dot && /* @__PURE__ */
|
|
970
|
-
/* @__PURE__ */
|
|
971
|
-
onRemove && /* @__PURE__ */
|
|
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
|
|
977
|
-
import { jsx as
|
|
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] =
|
|
1011
|
-
|
|
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__ */
|
|
1019
|
-
/* @__PURE__ */
|
|
1020
|
-
/* @__PURE__ */
|
|
1021
|
-
entry.title && /* @__PURE__ */
|
|
1022
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1025
|
-
/* @__PURE__ */
|
|
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
|
|
1040
|
-
import { jsx as
|
|
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
|
-
|
|
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
|
-
|
|
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__ */
|
|
1069
|
-
/* @__PURE__ */
|
|
1070
|
-
action && /* @__PURE__ */
|
|
1071
|
-
onClose && /* @__PURE__ */
|
|
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
|
-
|
|
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
|
};
|