@dragunio/fe-libs 0.1.2 → 0.1.3

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
@@ -97,11 +97,78 @@ import {
97
97
  useCallback,
98
98
  useContext,
99
99
  useEffect,
100
- useMemo,
100
+ useMemo as useMemo2,
101
101
  useRef,
102
- useState
102
+ useState as useState2
103
103
  } from "react";
104
+
105
+ // packages/pagination/src/index.tsx
106
+ import { useMemo, useState } from "react";
104
107
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
108
+ var clamp = (value, min, max) => Math.min(Math.max(value, min), max);
109
+ var range = (start, end) => Array.from({ length: Math.max(0, end - start + 1) }, (_, index) => start + index);
110
+ function getItems(totalPages, page, siblingCount, boundaryCount) {
111
+ const visibleCount = boundaryCount * 2 + siblingCount * 2 + 3;
112
+ if (totalPages <= visibleCount) return range(1, totalPages);
113
+ const startPages = range(1, boundaryCount);
114
+ const endPages = range(totalPages - boundaryCount + 1, totalPages);
115
+ const siblingsStart = Math.max(Math.min(page - siblingCount, totalPages - boundaryCount - siblingCount * 2 - 1), boundaryCount + 2);
116
+ const siblingsEnd = Math.min(Math.max(page + siblingCount, boundaryCount + siblingCount * 2 + 2), totalPages - boundaryCount - 1);
117
+ return [
118
+ ...startPages,
119
+ ...siblingsStart > boundaryCount + 2 ? ["start-ellipsis"] : siblingsStart === boundaryCount + 2 ? [boundaryCount + 1] : [],
120
+ ...range(siblingsStart, siblingsEnd),
121
+ ...siblingsEnd < totalPages - boundaryCount - 1 ? ["end-ellipsis"] : siblingsEnd === totalPages - boundaryCount - 1 ? [totalPages - boundaryCount] : [],
122
+ ...endPages
123
+ ];
124
+ }
125
+ function Pagination({
126
+ page,
127
+ defaultPage = 1,
128
+ totalPages,
129
+ onPageChange,
130
+ siblingCount = 1,
131
+ boundaryCount = 1,
132
+ disabled = false,
133
+ previousLabel = "Previous page",
134
+ nextLabel = "Next page",
135
+ className,
136
+ ...props
137
+ }) {
138
+ const safeTotalPages = Math.max(1, Math.floor(totalPages));
139
+ const [uncontrolledPage, setUncontrolledPage] = useState(() => clamp(defaultPage, 1, safeTotalPages));
140
+ const currentPage = clamp(page ?? uncontrolledPage, 1, safeTotalPages);
141
+ const items = useMemo(
142
+ () => getItems(safeTotalPages, currentPage, Math.max(0, siblingCount), Math.max(0, boundaryCount)),
143
+ [safeTotalPages, currentPage, siblingCount, boundaryCount]
144
+ );
145
+ const selectPage = (nextPage) => {
146
+ const resolvedPage = clamp(nextPage, 1, safeTotalPages);
147
+ if (page === void 0) setUncontrolledPage(resolvedPage);
148
+ if (resolvedPage !== currentPage) onPageChange?.(resolvedPage);
149
+ };
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(
153
+ Button,
154
+ {
155
+ className: "fe-pagination__button",
156
+ hierarchy: item === currentPage ? "primary" : "secondary-gray",
157
+ size: "40",
158
+ "aria-label": `Page ${item}`,
159
+ "aria-current": item === currentPage ? "page" : void 0,
160
+ disabled,
161
+ onClick: () => selectPage(item),
162
+ children: item
163
+ },
164
+ item
165
+ )),
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) })
167
+ ] });
168
+ }
169
+
170
+ // packages/table/src/index.tsx
171
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
105
172
  var TableContext = createContext({ striped: false });
106
173
  var MIN_COLUMN_WIDTH = 96;
107
174
  var MAX_COLUMN_WIDTH = 1200;
@@ -119,9 +186,9 @@ function autoColumnSize(columnIndex, headers, data) {
119
186
  const longestText = values.reduce((longest, value) => Math.max(longest, getText(value).length), 0);
120
187
  return Math.min(MAX_COLUMN_WIDTH, Math.max(MIN_COLUMN_WIDTH, longestText * 8 + 40));
121
188
  }
122
- function getInitialColumnSizes(headers, data, sizes, minColumnWidth = MIN_COLUMN_WIDTH) {
189
+ function getInitialColumnSizes(headers, data, sizes2, minColumnWidth = MIN_COLUMN_WIDTH) {
123
190
  return Array.from({ length: getColumnCount(headers, data) }, (_, columnIndex) => {
124
- const suppliedSize = sizes?.[columnIndex];
191
+ const suppliedSize = sizes2?.[columnIndex];
125
192
  return typeof suppliedSize === "number" && Number.isFinite(suppliedSize) ? Math.min(MAX_COLUMN_WIDTH, Math.max(minColumnWidth, suppliedSize)) : autoColumnSize(columnIndex, headers, data);
126
193
  });
127
194
  }
@@ -136,19 +203,31 @@ function DataTable({
136
203
  columnSizes,
137
204
  onColumnResize,
138
205
  minColumnWidth = MIN_COLUMN_WIDTH,
206
+ pagination,
207
+ pageSize,
208
+ page,
209
+ defaultPage = 1,
210
+ onPageChange,
211
+ paginationPosition = "bottom-right",
139
212
  className,
140
213
  ...props
141
214
  }) {
142
215
  const columnCount = getColumnCount(headers, data);
143
216
  const safeMinWidth = Math.max(1, minColumnWidth);
144
- const generatedSizes = useMemo(
217
+ const generatedSizes = useMemo2(
145
218
  () => getInitialColumnSizes(headers, data, defaultColumnSizes, safeMinWidth),
146
219
  [headers, data, defaultColumnSizes, safeMinWidth]
147
220
  );
148
- const [uncontrolledSizes, setUncontrolledSizes] = useState(generatedSizes);
221
+ const [uncontrolledSizes, setUncontrolledSizes] = useState2(generatedSizes);
222
+ const shouldPaginate = pagination ?? pageSize !== void 0;
223
+ const safePageSize = Math.max(1, Math.floor(pageSize ?? 10));
224
+ const totalPages = Math.max(1, Math.ceil(data.length / safePageSize));
225
+ const [uncontrolledPage, setUncontrolledPage] = useState2(() => Math.min(Math.max(1, defaultPage), totalPages));
226
+ const currentPage = Math.min(Math.max(1, page ?? uncontrolledPage), totalPages);
227
+ const pagedData = shouldPaginate ? data.slice((currentPage - 1) * safePageSize, currentPage * safePageSize) : data;
149
228
  const resizeState = useRef();
150
- const [isResizing, setIsResizing] = useState(false);
151
- const sizes = columnSizes ? getInitialColumnSizes(headers, data, columnSizes, safeMinWidth).map((size) => Math.max(safeMinWidth, size)) : uncontrolledSizes.map((size) => Math.max(safeMinWidth, size));
229
+ const [isResizing, setIsResizing] = useState2(false);
230
+ const sizes2 = columnSizes ? getInitialColumnSizes(headers, data, columnSizes, safeMinWidth).map((size) => Math.max(safeMinWidth, size)) : uncontrolledSizes.map((size) => Math.max(safeMinWidth, size));
152
231
  useEffect(() => {
153
232
  if (columnSizes) return;
154
233
  setUncontrolledSizes((currentSizes) => {
@@ -156,12 +235,15 @@ function DataTable({
156
235
  return sameSizes(currentSizes, nextSizes) ? currentSizes : nextSizes;
157
236
  });
158
237
  }, [columnSizes, generatedSizes]);
238
+ useEffect(() => {
239
+ if (page === void 0 && uncontrolledPage > totalPages) setUncontrolledPage(totalPages);
240
+ }, [page, totalPages, uncontrolledPage]);
159
241
  const updateColumnSize = useCallback((columnIndex, nextSize) => {
160
242
  const clampedSize = Math.min(MAX_COLUMN_WIDTH, Math.max(safeMinWidth, Math.round(nextSize)));
161
- const nextSizes = sizes.map((size, index) => index === columnIndex ? clampedSize : size);
243
+ const nextSizes = sizes2.map((size, index) => index === columnIndex ? clampedSize : size);
162
244
  if (!columnSizes) setUncontrolledSizes(nextSizes);
163
245
  onColumnResize?.(nextSizes, columnIndex);
164
- }, [columnSizes, onColumnResize, safeMinWidth, sizes]);
246
+ }, [columnSizes, onColumnResize, safeMinWidth, sizes2]);
165
247
  useEffect(() => {
166
248
  const onPointerMove = (event) => {
167
249
  const activeResize = resizeState.current;
@@ -181,74 +263,96 @@ function DataTable({
181
263
  window.removeEventListener("pointercancel", stopResizing);
182
264
  };
183
265
  }, [updateColumnSize]);
184
- return /* @__PURE__ */ jsx3("div", { className: "fe-table", "data-resizing": isResizing || void 0, children: /* @__PURE__ */ jsxs3("table", { className: ["fe-table__table", className].filter(Boolean).join(" "), "data-fe-table": true, "data-striped": striped || void 0, ...props, children: [
185
- /* @__PURE__ */ jsx3("colgroup", { children: sizes.map((size, index) => /* @__PURE__ */ jsx3("col", { style: { width: `${size}px` } }, index)) }),
186
- /* @__PURE__ */ jsx3("thead", { children: /* @__PURE__ */ jsx3("tr", { children: Array.from({ length: columnCount }, (_, columnIndex) => /* @__PURE__ */ jsxs3("th", { scope: "col", children: [
187
- /* @__PURE__ */ jsx3("span", { className: "fe-table__header-content", children: headers[columnIndex] ?? `Column ${columnIndex + 1}` }),
188
- /* @__PURE__ */ jsx3(
189
- "span",
190
- {
191
- className: "fe-table__resize-handle",
192
- role: "separator",
193
- "aria-label": `Resize ${getText(headers[columnIndex]) || `column ${columnIndex + 1}`}`,
194
- "aria-orientation": "vertical",
195
- "aria-valuemin": safeMinWidth,
196
- "aria-valuemax": MAX_COLUMN_WIDTH,
197
- "aria-valuenow": sizes[columnIndex] ?? safeMinWidth,
198
- tabIndex: 0,
199
- onPointerDown: (event) => {
200
- event.preventDefault();
201
- resizeState.current = { columnIndex, startX: event.clientX, startWidth: sizes[columnIndex] ?? safeMinWidth };
202
- setIsResizing(true);
203
- event.currentTarget.setPointerCapture(event.pointerId);
204
- },
205
- onKeyDown: (event) => {
206
- if (event.key === "ArrowLeft") updateColumnSize(columnIndex, (sizes[columnIndex] ?? safeMinWidth) - 16);
207
- if (event.key === "ArrowRight") updateColumnSize(columnIndex, (sizes[columnIndex] ?? safeMinWidth) + 16);
266
+ const changePage = (nextPage) => {
267
+ if (page === void 0) setUncontrolledPage(nextPage);
268
+ if (nextPage !== currentPage) onPageChange?.(nextPage);
269
+ };
270
+ 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: [
273
+ 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(
279
+ "span",
280
+ {
281
+ className: "fe-table__resize-handle",
282
+ role: "separator",
283
+ "aria-label": `Resize ${getText(headers[columnIndex]) || `column ${columnIndex + 1}`}`,
284
+ "aria-orientation": "vertical",
285
+ "aria-valuemin": safeMinWidth,
286
+ "aria-valuemax": MAX_COLUMN_WIDTH,
287
+ "aria-valuenow": sizes2[columnIndex] ?? safeMinWidth,
288
+ tabIndex: 0,
289
+ onPointerDown: (event) => {
290
+ event.preventDefault();
291
+ resizeState.current = { columnIndex, startX: event.clientX, startWidth: sizes2[columnIndex] ?? safeMinWidth };
292
+ setIsResizing(true);
293
+ event.currentTarget.setPointerCapture(event.pointerId);
294
+ },
295
+ onKeyDown: (event) => {
296
+ if (event.key === "ArrowLeft") updateColumnSize(columnIndex, (sizes2[columnIndex] ?? safeMinWidth) - 16);
297
+ if (event.key === "ArrowRight") updateColumnSize(columnIndex, (sizes2[columnIndex] ?? safeMinWidth) + 16);
298
+ }
208
299
  }
209
- }
210
- )
211
- ] }, columnIndex)) }) }),
212
- /* @__PURE__ */ jsx3("tbody", { children: data.map((row, rowIndex) => /* @__PURE__ */ jsx3("tr", { children: Array.from({ length: columnCount }, (_, columnIndex) => /* @__PURE__ */ jsx3("td", { children: row[columnIndex] }, columnIndex)) }, rowIndex)) })
213
- ] }) });
300
+ )
301
+ ] }, 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)) })
303
+ ] }),
304
+ resolvedPaginationPosition !== "top-right" && paginationControl
305
+ ] });
214
306
  }
215
- function Table({ headers, data, striped, children, ...props }) {
216
- if (headers || data) return /* @__PURE__ */ jsx3(DataTable, { headers: headers ?? [], data: data ?? [], striped: striped ?? true, ...props });
217
- return /* @__PURE__ */ jsx3(TableContext.Provider, { value: { striped: striped ?? false }, children: /* @__PURE__ */ jsx3("table", { "data-fe-table": true, "data-striped": striped || void 0, ...props, children }) });
307
+ function Table({
308
+ headers,
309
+ data,
310
+ striped,
311
+ children,
312
+ pagination,
313
+ pageSize,
314
+ page,
315
+ defaultPage,
316
+ onPageChange,
317
+ paginationPosition,
318
+ ...props
319
+ }) {
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 }) });
218
322
  }
219
323
  function TableHead(props) {
220
- return /* @__PURE__ */ jsx3("thead", { ...props });
324
+ return /* @__PURE__ */ jsx4("thead", { ...props });
221
325
  }
222
326
  function TableBody(props) {
223
- return /* @__PURE__ */ jsx3("tbody", { ...props });
327
+ return /* @__PURE__ */ jsx4("tbody", { ...props });
224
328
  }
225
329
  function TableRow({ children, ...props }) {
226
330
  const { striped } = useContext(TableContext);
227
- return /* @__PURE__ */ jsx3("tr", { "data-striped": striped || void 0, ...props, children });
331
+ return /* @__PURE__ */ jsx4("tr", { "data-striped": striped || void 0, ...props, children });
228
332
  }
229
333
  function TableCell({ children, ...props }) {
230
- return /* @__PURE__ */ jsx3("td", { ...props, children });
334
+ return /* @__PURE__ */ jsx4("td", { ...props, children });
231
335
  }
232
336
  function TableHeader({ children, ...props }) {
233
- return /* @__PURE__ */ jsx3("th", { scope: "col", ...props, children });
337
+ return /* @__PURE__ */ jsx4("th", { scope: "col", ...props, children });
234
338
  }
235
339
  function TableCaption(props) {
236
- return /* @__PURE__ */ jsx3("caption", { ...props });
340
+ return /* @__PURE__ */ jsx4("caption", { ...props });
237
341
  }
238
342
 
239
343
  // packages/toggle/src/index.tsx
240
344
  import { forwardRef as forwardRef2 } from "react";
241
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
345
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
242
346
  var Toggle = forwardRef2(function Toggle2({ color = "#16a34a", label, className, style, id, ...props }, ref) {
243
347
  const classes = ["fe-toggle", className].filter(Boolean).join(" ");
244
348
  const toggleStyle = {
245
349
  "--fe-toggle-color": color,
246
350
  ...style
247
351
  };
248
- return /* @__PURE__ */ jsxs4("label", { className: classes, style: toggleStyle, children: [
249
- /* @__PURE__ */ jsx4("input", { ref, id, className: "fe-toggle__input", type: "checkbox", role: "switch", ...props }),
250
- /* @__PURE__ */ jsx4("span", { className: "fe-toggle__control", "aria-hidden": "true" }),
251
- label && /* @__PURE__ */ jsx4("span", { className: "fe-toggle__label", children: label })
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 })
252
356
  ] });
253
357
  });
254
358
  Toggle.displayName = "Toggle";
@@ -256,7 +360,7 @@ Toggle.displayName = "Toggle";
256
360
  // packages/drawer/src/index.tsx
257
361
  import { useEffect as useEffect2 } from "react";
258
362
  import { createPortal } from "react-dom";
259
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
363
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
260
364
  function Drawer({ open, onClose, title, footer, side = "right", width = 400, fullScreen = false, children, closeOnBackdropClick = true, className, style, ...props }) {
261
365
  useEffect2(() => {
262
366
  if (!open) return;
@@ -268,15 +372,15 @@ function Drawer({ open, onClose, title, footer, side = "right", width = 400, ful
268
372
  }, [onClose, open]);
269
373
  if (!open || typeof document === "undefined") return null;
270
374
  const panelStyle = !fullScreen && (side === "left" || side === "right") ? { ...style, width: typeof width === "number" ? `${width}px` : width } : style;
271
- return createPortal(/* @__PURE__ */ jsx5("div", { className: "fe-drawer-backdrop", role: "presentation", onMouseDown: (event) => {
375
+ return createPortal(/* @__PURE__ */ jsx6("div", { className: "fe-drawer-backdrop", role: "presentation", onMouseDown: (event) => {
272
376
  if (event.target === event.currentTarget && closeOnBackdropClick) onClose();
273
- }, 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: [
274
- /* @__PURE__ */ jsxs5("header", { className: "fe-drawer__header", children: [
275
- title && /* @__PURE__ */ jsx5("h2", { children: title }),
276
- /* @__PURE__ */ jsx5("button", { type: "button", "aria-label": "Close drawer", onClick: onClose, children: "\xD7" })
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" })
277
381
  ] }),
278
- /* @__PURE__ */ jsx5("div", { className: "fe-drawer__body", children }),
279
- footer && /* @__PURE__ */ jsx5("footer", { className: "fe-drawer__footer", children: footer })
382
+ /* @__PURE__ */ jsx6("div", { className: "fe-drawer__body", children }),
383
+ footer && /* @__PURE__ */ jsx6("footer", { className: "fe-drawer__footer", children: footer })
280
384
  ] }) }), document.body);
281
385
  }
282
386
 
@@ -286,20 +390,92 @@ import {
286
390
  useEffect as useEffect3,
287
391
  useId,
288
392
  useRef as useRef2,
289
- useState as useState2
393
+ useState as useState3
290
394
  } from "react";
291
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
395
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
396
+ function getFieldError(error, errorMessage) {
397
+ if (errorMessage !== void 0 && errorMessage !== null) return errorMessage;
398
+ if (typeof error !== "boolean") return error;
399
+ return error ? "Invalid value" : void 0;
400
+ }
401
+ function getDescribedBy(existing, messageId2) {
402
+ return [existing, messageId2].filter(Boolean).join(" ") || void 0;
403
+ }
404
+ 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) {
405
+ const generatedId = useId();
406
+ const inputId = id ?? `${generatedId}-input`;
407
+ const labelId = `${generatedId}-label`;
408
+ const messageId2 = `${generatedId}-message`;
409
+ const controlled = value !== void 0;
410
+ const [internalValue, setInternalValue] = useState3(defaultValue);
411
+ const currentValue = controlled ? value : internalValue;
412
+ const fieldError = getFieldError(error, errorMessage);
413
+ const hasError = fieldError !== void 0 && fieldError !== false && fieldError !== null;
414
+ const displayedMessage = hasError ? fieldError : helperText;
415
+ const describedBy = getDescribedBy(ariaDescribedBy, displayedMessage ? messageId2 : void 0);
416
+ const clear = () => {
417
+ if (!controlled) setInternalValue("");
418
+ onValueChange?.("");
419
+ onClear?.();
420
+ };
421
+ const labelledBy = getDescribedBy(ariaLabelledBy, label ? labelId : void 0);
422
+ return /* @__PURE__ */ jsxs7("label", { className: ["fe-text-input", hasError && "fe-text-input--error", className].filter(Boolean).join(" "), children: [
423
+ label && /* @__PURE__ */ jsx7("span", { id: labelId, className: "fe-text-input__label", children: label }),
424
+ /* @__PURE__ */ jsxs7("span", { className: "fe-text-input__control", children: [
425
+ /* @__PURE__ */ jsx7("input", { ref, id: inputId, value: currentValue, disabled, readOnly, "aria-invalid": hasError || void 0, "aria-labelledby": labelledBy, "aria-describedby": describedBy, onChange: (event) => {
426
+ if (!controlled) setInternalValue(event.target.value);
427
+ onValueChange?.(event.target.value);
428
+ onChange?.(event);
429
+ }, ...props }),
430
+ 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" })
431
+ ] }),
432
+ displayedMessage && /* @__PURE__ */ jsx7("span", { id: messageId2, className: hasError ? "fe-text-input__error" : "fe-text-input__helper", children: displayedMessage })
433
+ ] });
434
+ });
435
+ TextInput.displayName = "TextInput";
436
+ 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) {
437
+ const generatedId = useId();
438
+ const inputId = id ?? `${generatedId}-input`;
439
+ const labelId = `${generatedId}-label`;
440
+ const messageId2 = `${generatedId}-message`;
441
+ const controlled = value !== void 0;
442
+ const [internalValue, setInternalValue] = useState3(defaultValue);
443
+ const currentValue = controlled ? value : internalValue;
444
+ const fieldError = getFieldError(error, errorMessage);
445
+ const hasError = fieldError !== void 0 && fieldError !== false && fieldError !== null;
446
+ const displayedMessage = hasError ? fieldError : helperText;
447
+ const describedBy = getDescribedBy(ariaDescribedBy, displayedMessage ? messageId2 : void 0);
448
+ const clear = () => {
449
+ if (!controlled) setInternalValue("");
450
+ onValueChange?.("");
451
+ onClear?.();
452
+ };
453
+ const labelledBy = getDescribedBy(ariaLabelledBy, label ? labelId : void 0);
454
+ return /* @__PURE__ */ jsxs7("label", { className: ["fe-text-area", hasError && "fe-text-area--error", className].filter(Boolean).join(" "), children: [
455
+ label && /* @__PURE__ */ jsx7("span", { id: labelId, className: "fe-text-area__label", children: label }),
456
+ /* @__PURE__ */ jsxs7("span", { className: "fe-text-area__control", children: [
457
+ /* @__PURE__ */ jsx7("textarea", { ref, id: inputId, value: currentValue, disabled, readOnly, "aria-invalid": hasError || void 0, "aria-labelledby": labelledBy, "aria-describedby": describedBy, onChange: (event) => {
458
+ if (!controlled) setInternalValue(event.target.value);
459
+ onValueChange?.(event.target.value);
460
+ onChange?.(event);
461
+ }, ...props }),
462
+ 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" })
463
+ ] }),
464
+ displayedMessage && /* @__PURE__ */ jsx7("span", { id: messageId2, className: hasError ? "fe-text-area__error" : "fe-text-area__helper", children: displayedMessage })
465
+ ] });
466
+ });
467
+ TextArea.displayName = "TextArea";
292
468
  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) {
293
469
  const generatedId = useId();
294
470
  const listboxId = id ?? generatedId;
295
471
  const isControlled = value !== void 0;
296
- const [internalValue, setInternalValue] = useState2(defaultValue ?? (multiple ? [] : ""));
472
+ const [internalValue, setInternalValue] = useState3(defaultValue ?? (multiple ? [] : ""));
297
473
  const selectedValue = isControlled ? value : internalValue;
298
474
  const selectedValues = Array.isArray(selectedValue) ? selectedValue : selectedValue === "" || selectedValue === null || selectedValue === void 0 ? [] : [selectedValue];
299
475
  const selectedOptions = options.filter((option) => selectedValues.some((item) => String(item) === String(option.value)));
300
- const [open, setOpen] = useState2(false);
301
- const [query, setQuery] = useState2("");
302
- const [activeIndex, setActiveIndex] = useState2(0);
476
+ const [open, setOpen] = useState3(false);
477
+ const [query, setQuery] = useState3("");
478
+ const [activeIndex, setActiveIndex] = useState3(0);
303
479
  const rootRef = useRef2(null);
304
480
  useEffect3(() => {
305
481
  const close = (event) => {
@@ -344,39 +520,39 @@ var Selection = forwardRef3(function Selection2({ className, label, helperText,
344
520
  }
345
521
  if (event.key === "Escape") setOpen(false);
346
522
  };
347
- return /* @__PURE__ */ jsxs6("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: [
348
- label && /* @__PURE__ */ jsx6("span", { className: "fe-selection__label", children: label }),
349
- /* @__PURE__ */ jsxs6("div", { ref: rootRef, className: "fe-selection__control", children: [
350
- name && selectedValues.map((item) => /* @__PURE__ */ jsx6("input", { type: "hidden", name: multiple ? `${name}[]` : name, value: item }, String(item))),
351
- /* @__PURE__ */ jsxs6("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: [
352
- /* @__PURE__ */ jsx6("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__ */ jsxs6("span", { className: "fe-selection__tag", children: [
523
+ 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: [
524
+ label && /* @__PURE__ */ jsx7("span", { className: "fe-selection__label", children: label }),
525
+ /* @__PURE__ */ jsxs7("div", { ref: rootRef, className: "fe-selection__control", children: [
526
+ name && selectedValues.map((item) => /* @__PURE__ */ jsx7("input", { type: "hidden", name: multiple ? `${name}[]` : name, value: item }, String(item))),
527
+ /* @__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: [
528
+ /* @__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: [
353
529
  option.label,
354
- /* @__PURE__ */ jsx6("span", { "aria-hidden": "true", children: "\xD7" })
355
- ] }, String(option.value))) : displayLabel.map((item, index) => /* @__PURE__ */ jsxs6("span", { children: [
530
+ /* @__PURE__ */ jsx7("span", { "aria-hidden": "true", children: "\xD7" })
531
+ ] }, String(option.value))) : displayLabel.map((item, index) => /* @__PURE__ */ jsxs7("span", { children: [
356
532
  item,
357
533
  index < displayLabel.length - 1 ? ", " : ""
358
534
  ] }, index)) : placeholder }),
359
- /* @__PURE__ */ jsx6("span", { className: "fe-selection__actions", children: /* @__PURE__ */ jsx6("span", { className: "fe-selection__chevron", "aria-hidden": "true" }) })
535
+ /* @__PURE__ */ jsx7("span", { className: "fe-selection__actions", children: /* @__PURE__ */ jsx7("span", { className: "fe-selection__chevron", "aria-hidden": "true" }) })
360
536
  ] }),
361
- clearable && selectedOptions.length > 0 && /* @__PURE__ */ jsx6("button", { type: "button", className: "fe-selection__clear", "aria-label": "Clear selection", onClick: clear }),
362
- open && /* @__PURE__ */ jsxs6("div", { id: listboxId, className: "fe-selection__menu", role: "listbox", "aria-multiselectable": multiple || void 0, children: [
363
- searchable && /* @__PURE__ */ jsxs6("div", { className: "fe-selection__search", children: [
364
- /* @__PURE__ */ jsx6("span", { "aria-hidden": "true", children: "\u2315" }),
365
- /* @__PURE__ */ jsx6("input", { autoFocus: true, value: query, onChange: (event) => {
537
+ clearable && selectedOptions.length > 0 && /* @__PURE__ */ jsx7("button", { type: "button", className: "fe-selection__clear", "aria-label": "Clear selection", onClick: clear }),
538
+ open && /* @__PURE__ */ jsxs7("div", { id: listboxId, className: "fe-selection__menu", role: "listbox", "aria-multiselectable": multiple || void 0, children: [
539
+ searchable && /* @__PURE__ */ jsxs7("div", { className: "fe-selection__search", children: [
540
+ /* @__PURE__ */ jsx7("span", { "aria-hidden": "true", children: "\u2315" }),
541
+ /* @__PURE__ */ jsx7("input", { autoFocus: true, value: query, onChange: (event) => {
366
542
  setQuery(event.target.value);
367
543
  setActiveIndex(0);
368
544
  }, placeholder: "Search\u2026", "aria-label": "Search options" })
369
545
  ] }),
370
- /* @__PURE__ */ jsx6("div", { className: "fe-selection__options", children: filteredOptions.length ? filteredOptions.map((option, index) => {
546
+ /* @__PURE__ */ jsx7("div", { className: "fe-selection__options", children: filteredOptions.length ? filteredOptions.map((option, index) => {
371
547
  const isSelected = selectedValues.some((item) => String(item) === String(option.value));
372
- return /* @__PURE__ */ jsxs6("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: [
373
- /* @__PURE__ */ jsx6("span", { children: option.label }),
374
- isSelected && /* @__PURE__ */ jsx6("span", { className: "fe-selection__check", "aria-hidden": "true", children: "\u2713" })
548
+ 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: [
549
+ /* @__PURE__ */ jsx7("span", { children: option.label }),
550
+ isSelected && /* @__PURE__ */ jsx7("span", { className: "fe-selection__check", "aria-hidden": "true", children: "\u2713" })
375
551
  ] }, String(option.value));
376
- }) : /* @__PURE__ */ jsx6("p", { className: "fe-selection__empty", children: "No matching options" }) })
552
+ }) : /* @__PURE__ */ jsx7("p", { className: "fe-selection__empty", children: "No matching options" }) })
377
553
  ] })
378
554
  ] }),
379
- helperText && /* @__PURE__ */ jsx6("span", { className: "fe-selection__helper", children: helperText })
555
+ helperText && /* @__PURE__ */ jsx7("span", { className: "fe-selection__helper", children: helperText })
380
556
  ] });
381
557
  });
382
558
  Selection.displayName = "Selection";
@@ -413,12 +589,18 @@ function normalizeNumberInput(raw, options) {
413
589
  if (value !== numericValue) return { display: formatNumber(value, decimals, thousandSeparator, decimalSeparator), value };
414
590
  return { display: `${negative ? "-" : ""}${groupInteger(integer || "0", thousandSeparator)}${hasDecimal ? `${decimalSeparator}${fraction}` : ""}`, value };
415
591
  }
416
- var NumberInput = forwardRef3(function NumberInput2({ value, defaultValue = null, onValueChange, allowDecimal = true, decimals = 2, min, max, decimalSeparator = ".", thousandSeparator = ",", label, helperText, error, className, onBlur, onFocus, ...props }, ref) {
592
+ 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) {
593
+ const generatedId = useId();
594
+ const messageId2 = `${generatedId}-message`;
417
595
  const isControlled = value !== void 0;
418
- const [internalValue, setInternalValue] = useState2(defaultValue);
419
- const [focused, setFocused] = useState2(false);
596
+ const [internalValue, setInternalValue] = useState3(defaultValue);
597
+ const [focused, setFocused] = useState3(false);
420
598
  const actualValue = isControlled ? value ?? null : internalValue;
421
- const [text, setText] = useState2(actualValue === null ? "" : formatNumber(actualValue, decimals, thousandSeparator, decimalSeparator));
599
+ const [text, setText] = useState3(actualValue === null ? "" : formatNumber(actualValue, decimals, thousandSeparator, decimalSeparator));
600
+ const fieldError = getFieldError(error, errorMessage);
601
+ const hasError = fieldError !== void 0 && fieldError !== false && fieldError !== null;
602
+ const displayedMessage = hasError ? fieldError : helperText;
603
+ const describedBy = getDescribedBy(ariaDescribedBy, displayedMessage ? messageId2 : void 0);
422
604
  useEffect3(() => {
423
605
  if (!focused) setText(actualValue === null ? "" : formatNumber(actualValue, decimals, thousandSeparator, decimalSeparator));
424
606
  }, [actualValue, decimalSeparator, decimals, focused, thousandSeparator]);
@@ -429,32 +611,32 @@ var NumberInput = forwardRef3(function NumberInput2({ value, defaultValue = null
429
611
  if (!isControlled) setInternalValue(nextValue);
430
612
  onValueChange?.(nextValue);
431
613
  };
432
- return /* @__PURE__ */ jsxs6("label", { className: ["fe-number-input", error && "fe-number-input--error", className].filter(Boolean).join(" "), children: [
433
- label && /* @__PURE__ */ jsx6("span", { className: "fe-number-input__label", children: label }),
434
- /* @__PURE__ */ jsx6("input", { ref, inputMode: allowDecimal ? "decimal" : "numeric", value: text, "aria-invalid": error || void 0, onFocus: (event) => {
614
+ return /* @__PURE__ */ jsxs7("label", { className: ["fe-number-input", hasError && "fe-number-input--error", className].filter(Boolean).join(" "), children: [
615
+ label && /* @__PURE__ */ jsx7("span", { className: "fe-number-input__label", children: label }),
616
+ /* @__PURE__ */ jsx7("input", { ref, inputMode: allowDecimal ? "decimal" : "numeric", value: text, onFocus: (event) => {
435
617
  setFocused(true);
436
618
  onFocus?.(event);
437
619
  }, onChange: (event) => updateValue(event.target.value), onBlur: (event) => {
438
620
  setFocused(false);
439
621
  onBlur?.(event);
440
- }, ...props }),
441
- helperText && /* @__PURE__ */ jsx6("span", { className: "fe-number-input__helper", children: helperText })
622
+ }, ...props, "aria-invalid": hasError || void 0, "aria-describedby": describedBy }),
623
+ displayedMessage && /* @__PURE__ */ jsx7("span", { id: messageId2, className: hasError ? "fe-number-input__error" : "fe-number-input__helper", children: displayedMessage })
442
624
  ] });
443
625
  });
444
626
  NumberInput.displayName = "NumberInput";
445
627
  function CurrencyInput({ suffix = "VND", currencies, currency, defaultCurrency, onCurrencyChange, className, ...props }) {
446
- const [internalCurrency, setInternalCurrency] = useState2(defaultCurrency ?? currencies?.[0]?.code ?? "");
628
+ const [internalCurrency, setInternalCurrency] = useState3(defaultCurrency ?? currencies?.[0]?.code ?? "");
447
629
  const selectedCurrency = currency ?? internalCurrency;
448
630
  const current = currencies?.find((item) => item.code === selectedCurrency);
449
631
  const currencySuffix = current?.suffix ?? current?.code ?? suffix;
450
- return /* @__PURE__ */ jsxs6("div", { className: ["fe-currency-input", className].filter(Boolean).join(" "), children: [
451
- /* @__PURE__ */ jsx6(NumberInput, { ...props, className: "fe-currency-input__number" }),
452
- currencies?.length ? /* @__PURE__ */ jsx6("select", { className: "fe-currency-input__currency", "aria-label": "Currency", value: selectedCurrency, onChange: (event) => {
632
+ return /* @__PURE__ */ jsxs7("div", { className: ["fe-currency-input", className].filter(Boolean).join(" "), children: [
633
+ /* @__PURE__ */ jsx7(NumberInput, { ...props, className: "fe-currency-input__number" }),
634
+ currencies?.length ? /* @__PURE__ */ jsx7("select", { className: "fe-currency-input__currency", "aria-label": "Currency", value: selectedCurrency, onChange: (event) => {
453
635
  const next = currencies.find((item) => item.code === event.target.value);
454
636
  if (!next) return;
455
637
  if (currency === void 0) setInternalCurrency(next.code);
456
638
  onCurrencyChange?.(next);
457
- }, children: currencies.map((item) => /* @__PURE__ */ jsx6("option", { value: item.code, children: item.label ?? item.code }, item.code)) }) : /* @__PURE__ */ jsx6("span", { className: "fe-currency-input__suffix", children: currencySuffix })
639
+ }, 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 })
458
640
  ] });
459
641
  }
460
642
  var pad = (value) => String(value).padStart(2, "0");
@@ -477,13 +659,13 @@ function DateTimePicker(props) {
477
659
  const { label, format = "dd/MM/yyyy HH:mm", disabled, placeholder, locale = "en-US", className, mode = "single" } = props;
478
660
  const isRange = mode === "range";
479
661
  const controlled = props.value !== void 0;
480
- const [singleInternal, setSingleInternal] = useState2((!isRange ? props.defaultValue : null) ?? null);
481
- const [rangeInternal, setRangeInternal] = useState2((isRange ? props.defaultValue : void 0) ?? [null, null]);
662
+ const [singleInternal, setSingleInternal] = useState3((!isRange ? props.defaultValue : null) ?? null);
663
+ const [rangeInternal, setRangeInternal] = useState3((isRange ? props.defaultValue : void 0) ?? [null, null]);
482
664
  const singleValue = !isRange ? props.value ?? singleInternal : null;
483
665
  const rangeValue = isRange ? props.value ?? rangeInternal : [null, null];
484
- const [open, setOpen] = useState2(false);
485
- const [month, setMonth] = useState2(() => new Date((isRange ? rangeValue[0] : singleValue) ?? /* @__PURE__ */ new Date()));
486
- const [editingEnd, setEditingEnd] = useState2(false);
666
+ const [open, setOpen] = useState3(false);
667
+ const [month, setMonth] = useState3(() => new Date((isRange ? rangeValue[0] : singleValue) ?? /* @__PURE__ */ new Date()));
668
+ const [editingEnd, setEditingEnd] = useState3(false);
487
669
  const rootRef = useRef2(null);
488
670
  useEffect3(() => {
489
671
  const onPointerDown = (event) => {
@@ -527,42 +709,42 @@ function DateTimePicker(props) {
527
709
  if (isRange) setRange(editingEnd ? [rangeValue[0], next] : [next, rangeValue[1]]);
528
710
  else setSingle(next);
529
711
  };
530
- return /* @__PURE__ */ jsxs6("div", { ref: rootRef, className: ["fe-datetime-picker", className].filter(Boolean).join(" "), children: [
531
- label && /* @__PURE__ */ jsx6("span", { className: "fe-datetime-picker__label", children: label }),
532
- /* @__PURE__ */ jsxs6("button", { type: "button", className: "fe-datetime-picker__trigger", disabled, "aria-expanded": open, onClick: () => setOpen((current) => !current), children: [
533
- /* @__PURE__ */ jsx6("span", { "aria-hidden": "true", children: "\u25F7" }),
534
- /* @__PURE__ */ jsx6("span", { children: shownValue || placeholder || (isRange ? "Select date range" : "Select date and time") })
712
+ return /* @__PURE__ */ jsxs7("div", { ref: rootRef, className: ["fe-datetime-picker", className].filter(Boolean).join(" "), children: [
713
+ label && /* @__PURE__ */ jsx7("span", { className: "fe-datetime-picker__label", children: label }),
714
+ /* @__PURE__ */ jsxs7("button", { type: "button", className: "fe-datetime-picker__trigger", disabled, "aria-expanded": open, onClick: () => setOpen((current) => !current), children: [
715
+ /* @__PURE__ */ jsx7("span", { "aria-hidden": "true", children: "\u25F7" }),
716
+ /* @__PURE__ */ jsx7("span", { children: shownValue || placeholder || (isRange ? "Select date range" : "Select date and time") })
535
717
  ] }),
536
- open && /* @__PURE__ */ jsxs6("div", { className: "fe-datetime-picker__popper", role: "dialog", "aria-label": "Date and time picker", children: [
537
- /* @__PURE__ */ jsxs6("div", { className: "fe-datetime-picker__month", children: [
538
- /* @__PURE__ */ jsx6("button", { type: "button", "aria-label": "Previous month", onClick: () => setMonth((current) => new Date(current.getFullYear(), current.getMonth() - 1, 1)), children: "\u2039" }),
539
- /* @__PURE__ */ jsx6("strong", { children: month.toLocaleDateString(locale, { month: "long", year: "numeric" }) }),
540
- /* @__PURE__ */ jsx6("button", { type: "button", "aria-label": "Next month", onClick: () => setMonth((current) => new Date(current.getFullYear(), current.getMonth() + 1, 1)), children: "\u203A" })
718
+ open && /* @__PURE__ */ jsxs7("div", { className: "fe-datetime-picker__popper", role: "dialog", "aria-label": "Date and time picker", children: [
719
+ /* @__PURE__ */ jsxs7("div", { className: "fe-datetime-picker__month", children: [
720
+ /* @__PURE__ */ jsx7("button", { type: "button", "aria-label": "Previous month", onClick: () => setMonth((current) => new Date(current.getFullYear(), current.getMonth() - 1, 1)), children: "\u2039" }),
721
+ /* @__PURE__ */ jsx7("strong", { children: month.toLocaleDateString(locale, { month: "long", year: "numeric" }) }),
722
+ /* @__PURE__ */ jsx7("button", { type: "button", "aria-label": "Next month", onClick: () => setMonth((current) => new Date(current.getFullYear(), current.getMonth() + 1, 1)), children: "\u203A" })
541
723
  ] }),
542
- /* @__PURE__ */ jsx6("div", { className: "fe-datetime-picker__weekdays", children: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"].map((day) => /* @__PURE__ */ jsx6("span", { children: day }, day)) }),
543
- /* @__PURE__ */ jsx6("div", { className: "fe-datetime-picker__days", children: days.map((day) => {
724
+ /* @__PURE__ */ jsx7("div", { className: "fe-datetime-picker__weekdays", children: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"].map((day) => /* @__PURE__ */ jsx7("span", { children: day }, day)) }),
725
+ /* @__PURE__ */ jsx7("div", { className: "fe-datetime-picker__days", children: days.map((day) => {
544
726
  const inMonth = day.getMonth() === month.getMonth();
545
727
  const selected = isRange ? sameDay(day, rangeValue[0]) || sameDay(day, rangeValue[1]) : sameDay(day, singleValue);
546
728
  const inRange = isRange && rangeValue[0] && rangeValue[1] && day > startOfDay(rangeValue[0]) && day < startOfDay(rangeValue[1]);
547
- return /* @__PURE__ */ jsx6("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());
729
+ 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());
548
730
  }) }),
549
- isRange && /* @__PURE__ */ jsxs6("div", { className: "fe-datetime-picker__range-tabs", children: [
550
- /* @__PURE__ */ jsx6("button", { type: "button", className: !editingEnd ? "is-active" : "", onClick: () => setEditingEnd(false), children: "Start" }),
551
- /* @__PURE__ */ jsx6("button", { type: "button", className: editingEnd ? "is-active" : "", onClick: () => setEditingEnd(true), children: "End" })
731
+ isRange && /* @__PURE__ */ jsxs7("div", { className: "fe-datetime-picker__range-tabs", children: [
732
+ /* @__PURE__ */ jsx7("button", { type: "button", className: !editingEnd ? "is-active" : "", onClick: () => setEditingEnd(false), children: "Start" }),
733
+ /* @__PURE__ */ jsx7("button", { type: "button", className: editingEnd ? "is-active" : "", onClick: () => setEditingEnd(true), children: "End" })
552
734
  ] }),
553
- /* @__PURE__ */ jsxs6("label", { className: "fe-datetime-picker__time", children: [
735
+ /* @__PURE__ */ jsxs7("label", { className: "fe-datetime-picker__time", children: [
554
736
  "Time",
555
- /* @__PURE__ */ jsx6("input", { type: "time", value: selectedForTime ? `${pad(selectedForTime.getHours())}:${pad(selectedForTime.getMinutes())}` : "00:00", onChange: (event) => setTime(event.target.value), disabled: !selectedForTime })
737
+ /* @__PURE__ */ jsx7("input", { type: "time", value: selectedForTime ? `${pad(selectedForTime.getHours())}:${pad(selectedForTime.getMinutes())}` : "00:00", onChange: (event) => setTime(event.target.value), disabled: !selectedForTime })
556
738
  ] })
557
739
  ] })
558
740
  ] });
559
741
  }
560
742
 
561
743
  // packages/tooltip/src/index.tsx
562
- import { cloneElement, useId as useId2, useState as useState3 } from "react";
563
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
744
+ import { cloneElement, useId as useId2, useState as useState4 } from "react";
745
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
564
746
  function Tooltip({ content, children, placement = "top", disabled, className, ...props }) {
565
- const [visible, setVisible] = useState3(false);
747
+ const [visible, setVisible] = useState4(false);
566
748
  const id = useId2();
567
749
  const trigger = cloneElement(children, { "aria-describedby": visible ? id : void 0, onMouseEnter: (event) => {
568
750
  children.props.onMouseEnter?.(event);
@@ -577,17 +759,17 @@ function Tooltip({ content, children, placement = "top", disabled, className, ..
577
759
  children.props.onBlur?.(event);
578
760
  setVisible(false);
579
761
  } });
580
- return /* @__PURE__ */ jsxs7("span", { className: ["fe-tooltip", `fe-tooltip--${placement}`, className].filter(Boolean).join(" "), ...props, children: [
762
+ return /* @__PURE__ */ jsxs8("span", { className: ["fe-tooltip", `fe-tooltip--${placement}`, className].filter(Boolean).join(" "), ...props, children: [
581
763
  trigger,
582
- visible && !disabled && /* @__PURE__ */ jsx7("span", { id, role: "tooltip", className: "fe-tooltip__content", children: content })
764
+ visible && !disabled && /* @__PURE__ */ jsx8("span", { id, role: "tooltip", className: "fe-tooltip__content", children: content })
583
765
  ] });
584
766
  }
585
767
 
586
768
  // packages/expandable-section/src/index.tsx
587
- import { useId as useId3, useState as useState4 } from "react";
588
- import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
769
+ import { useId as useId3, useState as useState5 } from "react";
770
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
589
771
  function ExpandableSection({ title, children, expanded, defaultExpanded = false, onExpandedChange, disabled, className, ...props }) {
590
- const [internalExpanded, setInternalExpanded] = useState4(defaultExpanded);
772
+ const [internalExpanded, setInternalExpanded] = useState5(defaultExpanded);
591
773
  const isExpanded = expanded ?? internalExpanded;
592
774
  const id = useId3();
593
775
  const toggle = () => {
@@ -596,26 +778,304 @@ function ExpandableSection({ title, children, expanded, defaultExpanded = false,
596
778
  if (expanded === void 0) setInternalExpanded(next);
597
779
  onExpandedChange?.(next);
598
780
  };
599
- return /* @__PURE__ */ jsxs8("section", { className: ["fe-expandable-section", isExpanded && "fe-expandable-section--expanded", disabled && "fe-expandable-section--disabled", className].filter(Boolean).join(" "), ...props, children: [
600
- /* @__PURE__ */ jsxs8("button", { className: "fe-expandable-section__trigger", type: "button", "aria-expanded": isExpanded, "aria-controls": id, disabled, onClick: toggle, children: [
601
- /* @__PURE__ */ jsx8("span", { children: title }),
602
- /* @__PURE__ */ jsx8("span", { className: "fe-expandable-section__chevron", "aria-hidden": "true" })
781
+ return /* @__PURE__ */ jsxs9("section", { className: ["fe-expandable-section", isExpanded && "fe-expandable-section--expanded", disabled && "fe-expandable-section--disabled", className].filter(Boolean).join(" "), ...props, children: [
782
+ /* @__PURE__ */ jsxs9("button", { className: "fe-expandable-section__trigger", type: "button", "aria-expanded": isExpanded, "aria-controls": id, disabled, onClick: toggle, children: [
783
+ /* @__PURE__ */ jsx9("span", { children: title }),
784
+ /* @__PURE__ */ jsx9("span", { className: "fe-expandable-section__chevron", "aria-hidden": "true" })
785
+ ] }),
786
+ /* @__PURE__ */ jsx9("div", { id, className: "fe-expandable-section__content", "aria-hidden": !isExpanded, children: /* @__PURE__ */ jsx9("div", { className: "fe-expandable-section__content-inner", children }) })
787
+ ] });
788
+ }
789
+
790
+ // packages/loading/src/index.tsx
791
+ import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
792
+ var sizes = {
793
+ small: "16px",
794
+ medium: "24px",
795
+ large: "40px"
796
+ };
797
+ function Loading({ size = "medium", color = "#2878f0", label, className, style, ...props }) {
798
+ const diameter = typeof size === "number" ? `${size}px` : sizes[size];
799
+ const loadingStyle = {
800
+ "--fe-loading-size": diameter,
801
+ "--fe-loading-color": color,
802
+ ...style
803
+ };
804
+ return /* @__PURE__ */ jsxs10("span", { className: ["fe-loading", className].filter(Boolean).join(" "), style: loadingStyle, role: "status", ...props, children: [
805
+ /* @__PURE__ */ jsx10("span", { className: "fe-loading__spinner", "aria-hidden": "true" }),
806
+ label && /* @__PURE__ */ jsx10("span", { className: "fe-loading__label", children: label }),
807
+ !label && /* @__PURE__ */ jsx10("span", { className: "fe-loading__sr-only", children: "Loading" })
808
+ ] });
809
+ }
810
+
811
+ // packages/skeleton/src/index.tsx
812
+ import { Fragment as Fragment2, jsx as jsx11 } from "react/jsx-runtime";
813
+ var pixels = (value) => typeof value === "number" ? `${value}px` : value;
814
+ function SkeletonBase({ variant = "box", shape, width, height, count = 1, animated = true, className, style, ...props }) {
815
+ const resolvedVariant = shape ?? variant;
816
+ const resolvedWidth = pixels(width) ?? (resolvedVariant === "circle" ? "40px" : "100%");
817
+ const resolvedHeight = pixels(height) ?? (resolvedVariant === "circle" ? resolvedWidth : resolvedVariant === "line" ? "12px" : "80px");
818
+ const skeletonStyle = {
819
+ "--fe-skeleton-width": resolvedWidth,
820
+ "--fe-skeleton-height": resolvedHeight,
821
+ ...style
822
+ };
823
+ return /* @__PURE__ */ jsx11(Fragment2, { children: Array.from({ length: Math.max(1, count) }, (_, index) => /* @__PURE__ */ jsx11(
824
+ "div",
825
+ {
826
+ className: ["fe-skeleton", `fe-skeleton--${resolvedVariant}`, animated && "fe-skeleton--animated", className].filter(Boolean).join(" "),
827
+ style: skeletonStyle,
828
+ "aria-hidden": "true",
829
+ ...props
830
+ },
831
+ index
832
+ )) });
833
+ }
834
+ function SkeletonCircle({ size = 40, ...props }) {
835
+ return /* @__PURE__ */ jsx11(SkeletonBase, { variant: "circle", width: size, height: size, ...props });
836
+ }
837
+ function SkeletonSquare({ size = 80, ...props }) {
838
+ return /* @__PURE__ */ jsx11(SkeletonBase, { variant: "box", width: size, height: size, ...props });
839
+ }
840
+ function SkeletonBox({ width = "100%", height = 80, ...props }) {
841
+ return /* @__PURE__ */ jsx11(SkeletonBase, { variant: "box", width, height, ...props });
842
+ }
843
+ function SkeletonLine({ width = "100%", height = 12, ...props }) {
844
+ return /* @__PURE__ */ jsx11(SkeletonBase, { variant: "line", width, height, ...props });
845
+ }
846
+ var Skeleton = Object.assign(SkeletonBase, {
847
+ Circle: SkeletonCircle,
848
+ Square: SkeletonSquare,
849
+ Box: SkeletonBox,
850
+ Line: SkeletonLine
851
+ });
852
+
853
+ // packages/modal/src/index.tsx
854
+ import { useEffect as useEffect4, useId as useId4, useRef as useRef3 } from "react";
855
+ import { createPortal as createPortal2 } from "react-dom";
856
+ import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
857
+ function Modal({
858
+ open,
859
+ onClose,
860
+ title,
861
+ description,
862
+ children,
863
+ footer,
864
+ actions = [],
865
+ size = "medium",
866
+ closeOnBackdropClick = true,
867
+ closeButton = true,
868
+ closeLabel = "Close modal",
869
+ className,
870
+ ...props
871
+ }) {
872
+ const titleId = useId4();
873
+ const panelRef = useRef3(null);
874
+ useEffect4(() => {
875
+ if (!open) return;
876
+ const onKeyDown = (event) => {
877
+ if (event.key === "Escape") onClose();
878
+ };
879
+ document.addEventListener("keydown", onKeyDown);
880
+ panelRef.current?.focus();
881
+ return () => document.removeEventListener("keydown", onKeyDown);
882
+ }, [onClose, open]);
883
+ if (!open || typeof document === "undefined") return null;
884
+ const hasFooter = footer || actions.length > 0;
885
+ return createPortal2(
886
+ /* @__PURE__ */ jsx12("div", { className: "fe-modal-backdrop", role: "presentation", onMouseDown: (event) => {
887
+ if (event.target === event.currentTarget && closeOnBackdropClick) onClose();
888
+ }, children: /* @__PURE__ */ jsxs11(
889
+ "div",
890
+ {
891
+ ref: panelRef,
892
+ className: ["fe-modal", `fe-modal--${size}`, className].filter(Boolean).join(" "),
893
+ role: "dialog",
894
+ "aria-modal": "true",
895
+ "aria-labelledby": title ? titleId : void 0,
896
+ "aria-label": title ? void 0 : "Modal",
897
+ tabIndex: -1,
898
+ ...props,
899
+ children: [
900
+ (title || description || closeButton) && /* @__PURE__ */ jsxs11("header", { className: "fe-modal__header", children: [
901
+ /* @__PURE__ */ jsxs11("div", { className: "fe-modal__heading", children: [
902
+ title && /* @__PURE__ */ jsx12("h2", { id: titleId, children: title }),
903
+ description && /* @__PURE__ */ jsx12("p", { children: description })
904
+ ] }),
905
+ closeButton && /* @__PURE__ */ jsx12(Button, { hierarchy: "tertiary-gray", size: "32", iconOnly: true, icon: /* @__PURE__ */ jsx12(CloseIcon, {}), "aria-label": closeLabel, onClick: onClose })
906
+ ] }),
907
+ /* @__PURE__ */ jsx12("div", { className: "fe-modal__body", children }),
908
+ hasFooter && /* @__PURE__ */ jsxs11("footer", { className: "fe-modal__footer", children: [
909
+ footer && /* @__PURE__ */ jsx12("div", { className: "fe-modal__footer-content", children: footer }),
910
+ actions.length > 0 && /* @__PURE__ */ jsx12("div", { className: "fe-modal__actions", children: actions.map(({ label, ...action }, index) => /* @__PURE__ */ jsx12(Button, { ...action, children: label }, index)) })
911
+ ] })
912
+ ]
913
+ }
914
+ ) }),
915
+ document.body
916
+ );
917
+ }
918
+
919
+ // packages/progress/src/index.tsx
920
+ import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
921
+ function ProgressBar({ value, max = 100, label, showValue = true, size = "medium", color = "#2878f0", className, style, "aria-label": ariaLabel, ...props }) {
922
+ const indeterminate = value === null || value === void 0;
923
+ const percentage = indeterminate ? 0 : Math.min(100, Math.max(0, Number(value) / Math.max(1, max) * 100));
924
+ const progressStyle = {
925
+ "--fe-progress-value": `${percentage}%`,
926
+ "--fe-progress-color": color,
927
+ ...style
928
+ };
929
+ const visibleValue = `${Math.round(percentage)}%`;
930
+ return /* @__PURE__ */ jsxs12("div", { className: ["fe-progress", `fe-progress--${size}`, indeterminate && "fe-progress--indeterminate", className].filter(Boolean).join(" "), style: progressStyle, ...props, children: [
931
+ (label || !indeterminate && showValue) && /* @__PURE__ */ jsxs12("div", { className: "fe-progress__meta", children: [
932
+ label && /* @__PURE__ */ jsx13("span", { className: "fe-progress__label", children: label }),
933
+ !indeterminate && showValue && /* @__PURE__ */ jsx13("output", { className: "fe-progress__value", children: visibleValue })
603
934
  ] }),
604
- /* @__PURE__ */ jsx8("div", { id, className: "fe-expandable-section__content", "aria-hidden": !isExpanded, children: /* @__PURE__ */ jsx8("div", { className: "fe-expandable-section__content-inner", children }) })
935
+ /* @__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" }) })
936
+ ] });
937
+ }
938
+
939
+ // packages/chip/src/index.tsx
940
+ import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
941
+ var statuses = ["default", "info", "success", "warning", "error", "neutral", "pending", "processing"];
942
+ function Chip({ children, status = "default", color, variant = "subtle", dot = false, onRemove, removeLabel = "Remove", className, style, ...props }) {
943
+ const usesCustomColor = Boolean(color);
944
+ const chipStyle = {
945
+ ...usesCustomColor ? { "--fe-chip-custom-color": color } : {},
946
+ ...style
947
+ };
948
+ const resolvedStatus = statuses.includes(status) ? status : "default";
949
+ return /* @__PURE__ */ jsxs13("span", { className: ["fe-chip", `fe-chip--${variant}`, `fe-chip--${usesCustomColor ? "custom" : resolvedStatus}`, className].filter(Boolean).join(" "), style: chipStyle, ...props, children: [
950
+ dot && /* @__PURE__ */ jsx14("span", { className: "fe-chip__dot", "aria-hidden": "true" }),
951
+ /* @__PURE__ */ jsx14("span", { className: "fe-chip__content", children }),
952
+ 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" })
605
953
  ] });
606
954
  }
955
+
956
+ // packages/message/src/index.tsx
957
+ import { useEffect as useEffect5, useState as useState6 } from "react";
958
+ import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
959
+ var messageId = 0;
960
+ var entries = [];
961
+ var listeners = /* @__PURE__ */ new Set();
962
+ var timers = /* @__PURE__ */ new Map();
963
+ var publish = () => listeners.forEach((listener) => listener(entries));
964
+ function dismiss(id) {
965
+ const timer = timers.get(id);
966
+ if (timer) window.clearTimeout(timer);
967
+ timers.delete(id);
968
+ const entry = entries.find((item) => item.id === id);
969
+ entries = entries.filter((item) => item.id !== id);
970
+ entry?.onClose?.();
971
+ publish();
972
+ }
973
+ function show({ duration = 4500, severity = "info", ...options }) {
974
+ const id = ++messageId;
975
+ entries = [...entries, { id, duration, severity, ...options }];
976
+ publish();
977
+ if (duration !== null) timers.set(id, window.setTimeout(() => dismiss(id), duration));
978
+ return id;
979
+ }
980
+ var message = {
981
+ show,
982
+ success: (content, options = {}) => show({ content, severity: "success", ...options }),
983
+ info: (content, options = {}) => show({ content, severity: "info", ...options }),
984
+ warning: (content, options = {}) => show({ content, severity: "warning", ...options }),
985
+ error: (content, options = {}) => show({ content, severity: "error", ...options }),
986
+ dismiss,
987
+ clear: () => [...entries].forEach((entry) => dismiss(entry.id))
988
+ };
989
+ var icons = { success: "\u2713", info: "i", warning: "!", error: "\xD7" };
990
+ function Message({ maxCount = 4, closeLabel = "Close notification", className, ...props }) {
991
+ const [visibleEntries, setVisibleEntries] = useState6(entries);
992
+ useEffect5(() => {
993
+ const listener = (nextEntries) => setVisibleEntries(nextEntries);
994
+ listeners.add(listener);
995
+ return () => {
996
+ listeners.delete(listener);
997
+ };
998
+ }, []);
999
+ 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: [
1000
+ /* @__PURE__ */ jsx15("span", { className: "fe-message__icon", "aria-hidden": "true", children: icons[entry.severity ?? "info"] }),
1001
+ /* @__PURE__ */ jsxs14("div", { className: "fe-message__body", children: [
1002
+ entry.title && /* @__PURE__ */ jsx15("strong", { className: "fe-message__title", children: entry.title }),
1003
+ /* @__PURE__ */ jsx15("div", { className: "fe-message__content", children: entry.content })
1004
+ ] }),
1005
+ entry.action && /* @__PURE__ */ jsx15("span", { className: "fe-message__action", children: entry.action }),
1006
+ /* @__PURE__ */ jsx15(Button, { className: "fe-message__close", hierarchy: "tertiary-gray", size: "24", iconOnly: true, icon: "\xD7", "aria-label": closeLabel, onClick: () => dismiss(entry.id) })
1007
+ ] }, entry.id)) });
1008
+ }
1009
+ ((Message2) => {
1010
+ Message2.show = message.show;
1011
+ Message2.success = message.success;
1012
+ Message2.info = message.info;
1013
+ Message2.warning = message.warning;
1014
+ Message2.error = message.error;
1015
+ Message2.dismiss = message.dismiss;
1016
+ Message2.clear = message.clear;
1017
+ })(Message || (Message = {}));
1018
+
1019
+ // packages/snackbar/src/index.tsx
1020
+ import { useEffect as useEffect6 } from "react";
1021
+ import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
1022
+ function Snackbar({
1023
+ open,
1024
+ message: message2,
1025
+ autoHideDuration = 5e3,
1026
+ onClose,
1027
+ action,
1028
+ anchorOrigin = {},
1029
+ closeLabel = "Close notification",
1030
+ className,
1031
+ ...props
1032
+ }) {
1033
+ const vertical = anchorOrigin.vertical ?? "bottom";
1034
+ const horizontal = anchorOrigin.horizontal ?? "center";
1035
+ useEffect6(() => {
1036
+ if (!open || autoHideDuration === null) return void 0;
1037
+ const timer = window.setTimeout(() => onClose?.("timeout"), autoHideDuration);
1038
+ return () => window.clearTimeout(timer);
1039
+ }, [open, autoHideDuration, onClose]);
1040
+ useEffect6(() => {
1041
+ if (!open) return void 0;
1042
+ const onKeyDown = (event) => {
1043
+ if (event.key === "Escape") onClose?.("escapeKeyDown");
1044
+ };
1045
+ window.addEventListener("keydown", onKeyDown);
1046
+ return () => window.removeEventListener("keydown", onKeyDown);
1047
+ }, [open, onClose]);
1048
+ if (!open) return null;
1049
+ 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: [
1050
+ /* @__PURE__ */ jsx16("span", { className: "fe-snackbar__message", children: message2 }),
1051
+ action && /* @__PURE__ */ jsx16("span", { className: "fe-snackbar__action", children: action }),
1052
+ onClose && /* @__PURE__ */ jsx16(Button, { className: "fe-snackbar__close", hierarchy: "tertiary-gray", size: "24", iconOnly: true, icon: "\xD7", "aria-label": closeLabel, onClick: () => onClose("closeButton") })
1053
+ ] }) });
1054
+ }
607
1055
  export {
608
1056
  Button,
609
1057
  ChevronDownIcon,
1058
+ Chip,
610
1059
  CloseIcon,
611
1060
  CurrencyInput,
612
1061
  DateTimePicker,
613
1062
  Drawer,
614
1063
  ExpandableSection,
1064
+ Loading,
1065
+ Message,
1066
+ Modal,
615
1067
  NumberInput,
1068
+ Pagination,
616
1069
  PlusIcon,
1070
+ ProgressBar,
617
1071
  SearchIcon,
618
1072
  Selection,
1073
+ Skeleton,
1074
+ SkeletonBox,
1075
+ SkeletonCircle,
1076
+ SkeletonLine,
1077
+ SkeletonSquare,
1078
+ Snackbar,
619
1079
  Table,
620
1080
  TableBody,
621
1081
  TableCaption,
@@ -623,8 +1083,11 @@ export {
623
1083
  TableHead,
624
1084
  TableHeader,
625
1085
  TableRow,
1086
+ TextArea,
1087
+ TextInput,
626
1088
  Toggle,
627
1089
  Tooltip,
628
1090
  formatNumber,
629
- getIconSize
1091
+ getIconSize,
1092
+ message
630
1093
  };