@dragunio/fe-libs 0.1.2 → 0.1.4
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 +51 -14
- package/dist/index.d.mts +234 -5
- package/dist/index.d.ts +234 -5
- package/dist/index.js +656 -160
- package/dist/index.mjs +622 -140
- package/dist/styles.css +669 -10
- package/package.json +1 -1
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,
|
|
189
|
+
function getInitialColumnSizes(headers, data, sizes2, minColumnWidth = MIN_COLUMN_WIDTH) {
|
|
123
190
|
return Array.from({ length: getColumnCount(headers, data) }, (_, columnIndex) => {
|
|
124
|
-
const suppliedSize =
|
|
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 =
|
|
217
|
+
const generatedSizes = useMemo2(
|
|
145
218
|
() => getInitialColumnSizes(headers, data, defaultColumnSizes, safeMinWidth),
|
|
146
219
|
[headers, data, defaultColumnSizes, safeMinWidth]
|
|
147
220
|
);
|
|
148
|
-
const [uncontrolledSizes, setUncontrolledSizes] =
|
|
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] =
|
|
151
|
-
const
|
|
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 =
|
|
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,
|
|
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
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
"
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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
|
-
|
|
212
|
-
|
|
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({
|
|
216
|
-
|
|
217
|
-
|
|
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__ */
|
|
324
|
+
return /* @__PURE__ */ jsx4("thead", { ...props });
|
|
221
325
|
}
|
|
222
326
|
function TableBody(props) {
|
|
223
|
-
return /* @__PURE__ */
|
|
327
|
+
return /* @__PURE__ */ jsx4("tbody", { ...props });
|
|
224
328
|
}
|
|
225
329
|
function TableRow({ children, ...props }) {
|
|
226
330
|
const { striped } = useContext(TableContext);
|
|
227
|
-
return /* @__PURE__ */
|
|
331
|
+
return /* @__PURE__ */ jsx4("tr", { "data-striped": striped || void 0, ...props, children });
|
|
228
332
|
}
|
|
229
333
|
function TableCell({ children, ...props }) {
|
|
230
|
-
return /* @__PURE__ */
|
|
334
|
+
return /* @__PURE__ */ jsx4("td", { ...props, children });
|
|
231
335
|
}
|
|
232
336
|
function TableHeader({ children, ...props }) {
|
|
233
|
-
return /* @__PURE__ */
|
|
337
|
+
return /* @__PURE__ */ jsx4("th", { scope: "col", ...props, children });
|
|
234
338
|
}
|
|
235
339
|
function TableCaption(props) {
|
|
236
|
-
return /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
249
|
-
/* @__PURE__ */
|
|
250
|
-
/* @__PURE__ */
|
|
251
|
-
label && /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
274
|
-
/* @__PURE__ */
|
|
275
|
-
title && /* @__PURE__ */
|
|
276
|
-
/* @__PURE__ */
|
|
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__ */
|
|
279
|
-
footer && /* @__PURE__ */
|
|
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
|
|
|
@@ -285,29 +389,120 @@ import {
|
|
|
285
389
|
forwardRef as forwardRef3,
|
|
286
390
|
useEffect as useEffect3,
|
|
287
391
|
useId,
|
|
392
|
+
useLayoutEffect,
|
|
288
393
|
useRef as useRef2,
|
|
289
|
-
useState as
|
|
394
|
+
useState as useState3
|
|
290
395
|
} from "react";
|
|
291
|
-
import {
|
|
396
|
+
import { createPortal as createPortal2 } from "react-dom";
|
|
397
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
398
|
+
function getFieldError(error, errorMessage) {
|
|
399
|
+
if (errorMessage !== void 0 && errorMessage !== null) return errorMessage;
|
|
400
|
+
if (typeof error !== "boolean") return error;
|
|
401
|
+
return error ? "Invalid value" : void 0;
|
|
402
|
+
}
|
|
403
|
+
function getDescribedBy(existing, messageId2) {
|
|
404
|
+
return [existing, messageId2].filter(Boolean).join(" ") || void 0;
|
|
405
|
+
}
|
|
406
|
+
var TextInput = forwardRef3(function TextInput2({ value, defaultValue = "", onChange, onValueChange, label, helperText, error, errorMessage, clearable = false, onClear, clearLabel = "Clear input", className, disabled, readOnly, id, "aria-describedby": ariaDescribedBy, "aria-labelledby": ariaLabelledBy, ...props }, ref) {
|
|
407
|
+
const generatedId = useId();
|
|
408
|
+
const inputId = id ?? `${generatedId}-input`;
|
|
409
|
+
const labelId = `${generatedId}-label`;
|
|
410
|
+
const messageId2 = `${generatedId}-message`;
|
|
411
|
+
const controlled = value !== void 0;
|
|
412
|
+
const [internalValue, setInternalValue] = useState3(defaultValue);
|
|
413
|
+
const currentValue = controlled ? value : internalValue;
|
|
414
|
+
const fieldError = getFieldError(error, errorMessage);
|
|
415
|
+
const hasError = fieldError !== void 0 && fieldError !== false && fieldError !== null;
|
|
416
|
+
const displayedMessage = hasError ? fieldError : helperText;
|
|
417
|
+
const describedBy = getDescribedBy(ariaDescribedBy, displayedMessage ? messageId2 : void 0);
|
|
418
|
+
const clear = () => {
|
|
419
|
+
if (!controlled) setInternalValue("");
|
|
420
|
+
onValueChange?.("");
|
|
421
|
+
onClear?.();
|
|
422
|
+
};
|
|
423
|
+
const labelledBy = getDescribedBy(ariaLabelledBy, label ? labelId : void 0);
|
|
424
|
+
return /* @__PURE__ */ jsxs7("label", { className: ["fe-text-input", hasError && "fe-text-input--error", className].filter(Boolean).join(" "), children: [
|
|
425
|
+
label && /* @__PURE__ */ jsx7("span", { id: labelId, className: "fe-text-input__label", children: label }),
|
|
426
|
+
/* @__PURE__ */ jsxs7("span", { className: "fe-text-input__control", children: [
|
|
427
|
+
/* @__PURE__ */ jsx7("input", { ref, id: inputId, value: currentValue, disabled, readOnly, "aria-invalid": hasError || void 0, "aria-labelledby": labelledBy, "aria-describedby": describedBy, onChange: (event) => {
|
|
428
|
+
if (!controlled) setInternalValue(event.target.value);
|
|
429
|
+
onValueChange?.(event.target.value);
|
|
430
|
+
onChange?.(event);
|
|
431
|
+
}, ...props }),
|
|
432
|
+
clearable && currentValue && !disabled && !readOnly && /* @__PURE__ */ jsx7(Button, { hierarchy: "tertiary-gray", size: "24", iconOnly: true, icon: /* @__PURE__ */ jsx7(CloseIcon, { size: 14 }), "aria-label": clearLabel, onClick: clear, className: "fe-text-input__clear" })
|
|
433
|
+
] }),
|
|
434
|
+
displayedMessage && /* @__PURE__ */ jsx7("span", { id: messageId2, className: hasError ? "fe-text-input__error" : "fe-text-input__helper", children: displayedMessage })
|
|
435
|
+
] });
|
|
436
|
+
});
|
|
437
|
+
TextInput.displayName = "TextInput";
|
|
438
|
+
var TextArea = forwardRef3(function TextArea2({ value, defaultValue = "", onChange, onValueChange, label, helperText, error, errorMessage, clearable = false, onClear, clearLabel = "Clear text area", className, disabled, readOnly, id, "aria-describedby": ariaDescribedBy, "aria-labelledby": ariaLabelledBy, ...props }, ref) {
|
|
439
|
+
const generatedId = useId();
|
|
440
|
+
const inputId = id ?? `${generatedId}-input`;
|
|
441
|
+
const labelId = `${generatedId}-label`;
|
|
442
|
+
const messageId2 = `${generatedId}-message`;
|
|
443
|
+
const controlled = value !== void 0;
|
|
444
|
+
const [internalValue, setInternalValue] = useState3(defaultValue);
|
|
445
|
+
const currentValue = controlled ? value : internalValue;
|
|
446
|
+
const fieldError = getFieldError(error, errorMessage);
|
|
447
|
+
const hasError = fieldError !== void 0 && fieldError !== false && fieldError !== null;
|
|
448
|
+
const displayedMessage = hasError ? fieldError : helperText;
|
|
449
|
+
const describedBy = getDescribedBy(ariaDescribedBy, displayedMessage ? messageId2 : void 0);
|
|
450
|
+
const clear = () => {
|
|
451
|
+
if (!controlled) setInternalValue("");
|
|
452
|
+
onValueChange?.("");
|
|
453
|
+
onClear?.();
|
|
454
|
+
};
|
|
455
|
+
const labelledBy = getDescribedBy(ariaLabelledBy, label ? labelId : void 0);
|
|
456
|
+
return /* @__PURE__ */ jsxs7("label", { className: ["fe-text-area", hasError && "fe-text-area--error", className].filter(Boolean).join(" "), children: [
|
|
457
|
+
label && /* @__PURE__ */ jsx7("span", { id: labelId, className: "fe-text-area__label", children: label }),
|
|
458
|
+
/* @__PURE__ */ jsxs7("span", { className: "fe-text-area__control", children: [
|
|
459
|
+
/* @__PURE__ */ jsx7("textarea", { ref, id: inputId, value: currentValue, disabled, readOnly, "aria-invalid": hasError || void 0, "aria-labelledby": labelledBy, "aria-describedby": describedBy, onChange: (event) => {
|
|
460
|
+
if (!controlled) setInternalValue(event.target.value);
|
|
461
|
+
onValueChange?.(event.target.value);
|
|
462
|
+
onChange?.(event);
|
|
463
|
+
}, ...props }),
|
|
464
|
+
clearable && currentValue && !disabled && !readOnly && /* @__PURE__ */ jsx7(Button, { hierarchy: "tertiary-gray", size: "24", iconOnly: true, icon: /* @__PURE__ */ jsx7(CloseIcon, { size: 14 }), "aria-label": clearLabel, onClick: clear, className: "fe-text-area__clear" })
|
|
465
|
+
] }),
|
|
466
|
+
displayedMessage && /* @__PURE__ */ jsx7("span", { id: messageId2, className: hasError ? "fe-text-area__error" : "fe-text-area__helper", children: displayedMessage })
|
|
467
|
+
] });
|
|
468
|
+
});
|
|
469
|
+
TextArea.displayName = "TextArea";
|
|
292
470
|
var Selection = forwardRef3(function Selection2({ className, label, helperText, error, options, placeholder = "Select an option", size = "medium", id, value, defaultValue, onChange, multiple = false, searchable = false, tag = false, clearable = false, disabled = false, name, onKeyDown, ...props }, ref) {
|
|
293
471
|
const generatedId = useId();
|
|
294
472
|
const listboxId = id ?? generatedId;
|
|
295
473
|
const isControlled = value !== void 0;
|
|
296
|
-
const [internalValue, setInternalValue] =
|
|
474
|
+
const [internalValue, setInternalValue] = useState3(defaultValue ?? (multiple ? [] : ""));
|
|
297
475
|
const selectedValue = isControlled ? value : internalValue;
|
|
298
476
|
const selectedValues = Array.isArray(selectedValue) ? selectedValue : selectedValue === "" || selectedValue === null || selectedValue === void 0 ? [] : [selectedValue];
|
|
299
477
|
const selectedOptions = options.filter((option) => selectedValues.some((item) => String(item) === String(option.value)));
|
|
300
|
-
const [open, setOpen] =
|
|
301
|
-
const [query, setQuery] =
|
|
302
|
-
const [activeIndex, setActiveIndex] =
|
|
478
|
+
const [open, setOpen] = useState3(false);
|
|
479
|
+
const [query, setQuery] = useState3("");
|
|
480
|
+
const [activeIndex, setActiveIndex] = useState3(0);
|
|
303
481
|
const rootRef = useRef2(null);
|
|
482
|
+
const menuRef = useRef2(null);
|
|
483
|
+
const [menuPosition, setMenuPosition] = useState3(null);
|
|
304
484
|
useEffect3(() => {
|
|
305
485
|
const close = (event) => {
|
|
306
|
-
|
|
486
|
+
const target = event.target;
|
|
487
|
+
if (!rootRef.current?.contains(target) && !menuRef.current?.contains(target)) setOpen(false);
|
|
307
488
|
};
|
|
308
489
|
document.addEventListener("mousedown", close);
|
|
309
490
|
return () => document.removeEventListener("mousedown", close);
|
|
310
491
|
}, []);
|
|
492
|
+
useLayoutEffect(() => {
|
|
493
|
+
if (!open) return;
|
|
494
|
+
const updateMenuPosition = () => {
|
|
495
|
+
const rect = rootRef.current?.getBoundingClientRect();
|
|
496
|
+
if (rect) setMenuPosition({ top: rect.bottom + 7, left: rect.left, width: rect.width });
|
|
497
|
+
};
|
|
498
|
+
updateMenuPosition();
|
|
499
|
+
window.addEventListener("resize", updateMenuPosition);
|
|
500
|
+
document.addEventListener("scroll", updateMenuPosition, true);
|
|
501
|
+
return () => {
|
|
502
|
+
window.removeEventListener("resize", updateMenuPosition);
|
|
503
|
+
document.removeEventListener("scroll", updateMenuPosition, true);
|
|
504
|
+
};
|
|
505
|
+
}, [open]);
|
|
311
506
|
const filteredOptions = options.filter((option) => !query || (option.searchText ?? (typeof option.label === "string" ? option.label : String(option.value))).toLowerCase().includes(query.toLowerCase()));
|
|
312
507
|
const commit = (next) => {
|
|
313
508
|
if (!isControlled) setInternalValue(next);
|
|
@@ -344,39 +539,39 @@ var Selection = forwardRef3(function Selection2({ className, label, helperText,
|
|
|
344
539
|
}
|
|
345
540
|
if (event.key === "Escape") setOpen(false);
|
|
346
541
|
};
|
|
347
|
-
return /* @__PURE__ */
|
|
348
|
-
label && /* @__PURE__ */
|
|
349
|
-
/* @__PURE__ */
|
|
350
|
-
name && selectedValues.map((item) => /* @__PURE__ */
|
|
351
|
-
/* @__PURE__ */
|
|
352
|
-
/* @__PURE__ */
|
|
542
|
+
return /* @__PURE__ */ jsxs7("div", { ref, className: ["fe-selection", `fe-selection--${size}`, open && "fe-selection--open", clearable && selectedOptions.length > 0 && "fe-selection--clearable", error && "fe-selection--error", disabled && "fe-selection--disabled", className].filter(Boolean).join(" "), ...props, children: [
|
|
543
|
+
label && /* @__PURE__ */ jsx7("span", { className: "fe-selection__label", children: label }),
|
|
544
|
+
/* @__PURE__ */ jsxs7("div", { ref: rootRef, className: "fe-selection__control", children: [
|
|
545
|
+
name && selectedValues.map((item) => /* @__PURE__ */ jsx7("input", { type: "hidden", name: multiple ? `${name}[]` : name, value: item }, String(item))),
|
|
546
|
+
/* @__PURE__ */ jsxs7("button", { type: "button", className: "fe-selection__trigger", disabled, "aria-invalid": error || void 0, "aria-haspopup": "listbox", "aria-expanded": open, "aria-controls": listboxId, onClick: () => setOpen((current) => !current), onKeyDown: onTriggerKeyDown, children: [
|
|
547
|
+
/* @__PURE__ */ jsx7("span", { className: ["fe-selection__value", !selectedOptions.length && "is-placeholder", tag && selectedOptions.length > 1 && "is-tags"].filter(Boolean).join(" "), children: displayLabel ? tag && multiple ? selectedOptions.map((option) => /* @__PURE__ */ jsxs7("span", { className: "fe-selection__tag", children: [
|
|
353
548
|
option.label,
|
|
354
|
-
/* @__PURE__ */
|
|
355
|
-
] }, String(option.value))) : displayLabel.map((item, index) => /* @__PURE__ */
|
|
549
|
+
/* @__PURE__ */ jsx7("span", { "aria-hidden": "true", children: "\xD7" })
|
|
550
|
+
] }, String(option.value))) : displayLabel.map((item, index) => /* @__PURE__ */ jsxs7("span", { children: [
|
|
356
551
|
item,
|
|
357
552
|
index < displayLabel.length - 1 ? ", " : ""
|
|
358
553
|
] }, index)) : placeholder }),
|
|
359
|
-
/* @__PURE__ */
|
|
554
|
+
/* @__PURE__ */ jsx7("span", { className: "fe-selection__actions", children: /* @__PURE__ */ jsx7("span", { className: "fe-selection__chevron", "aria-hidden": "true" }) })
|
|
360
555
|
] }),
|
|
361
|
-
clearable && selectedOptions.length > 0 && /* @__PURE__ */
|
|
362
|
-
open && /* @__PURE__ */
|
|
363
|
-
searchable && /* @__PURE__ */
|
|
364
|
-
/* @__PURE__ */
|
|
365
|
-
/* @__PURE__ */
|
|
556
|
+
clearable && selectedOptions.length > 0 && /* @__PURE__ */ jsx7("button", { type: "button", className: "fe-selection__clear", "aria-label": "Clear selection", onClick: clear }),
|
|
557
|
+
open && menuPosition && createPortal2(/* @__PURE__ */ jsxs7("div", { ref: menuRef, id: listboxId, className: "fe-selection__menu", style: { position: "fixed", top: menuPosition.top, left: menuPosition.left, width: menuPosition.width }, role: "listbox", "aria-multiselectable": multiple || void 0, children: [
|
|
558
|
+
searchable && /* @__PURE__ */ jsxs7("div", { className: "fe-selection__search", children: [
|
|
559
|
+
/* @__PURE__ */ jsx7("span", { "aria-hidden": "true", children: "\u2315" }),
|
|
560
|
+
/* @__PURE__ */ jsx7("input", { autoFocus: true, value: query, onChange: (event) => {
|
|
366
561
|
setQuery(event.target.value);
|
|
367
562
|
setActiveIndex(0);
|
|
368
563
|
}, placeholder: "Search\u2026", "aria-label": "Search options" })
|
|
369
564
|
] }),
|
|
370
|
-
/* @__PURE__ */
|
|
565
|
+
/* @__PURE__ */ jsx7("div", { className: "fe-selection__options", children: filteredOptions.length ? filteredOptions.map((option, index) => {
|
|
371
566
|
const isSelected = selectedValues.some((item) => String(item) === String(option.value));
|
|
372
|
-
return /* @__PURE__ */
|
|
373
|
-
/* @__PURE__ */
|
|
374
|
-
isSelected && /* @__PURE__ */
|
|
567
|
+
return /* @__PURE__ */ jsxs7("button", { type: "button", className: [isSelected && "is-selected", index === activeIndex && "is-active"].filter(Boolean).join(" "), role: "option", "aria-selected": isSelected, disabled: option.disabled, onMouseMove: () => setActiveIndex(index), onClick: () => choose(option), children: [
|
|
568
|
+
/* @__PURE__ */ jsx7("span", { children: option.label }),
|
|
569
|
+
isSelected && /* @__PURE__ */ jsx7("span", { className: "fe-selection__check", "aria-hidden": "true", children: "\u2713" })
|
|
375
570
|
] }, String(option.value));
|
|
376
|
-
}) : /* @__PURE__ */
|
|
377
|
-
] })
|
|
571
|
+
}) : /* @__PURE__ */ jsx7("p", { className: "fe-selection__empty", children: "No matching options" }) })
|
|
572
|
+
] }), document.body)
|
|
378
573
|
] }),
|
|
379
|
-
helperText && /* @__PURE__ */
|
|
574
|
+
helperText && /* @__PURE__ */ jsx7("span", { className: "fe-selection__helper", children: helperText })
|
|
380
575
|
] });
|
|
381
576
|
});
|
|
382
577
|
Selection.displayName = "Selection";
|
|
@@ -413,12 +608,18 @@ function normalizeNumberInput(raw, options) {
|
|
|
413
608
|
if (value !== numericValue) return { display: formatNumber(value, decimals, thousandSeparator, decimalSeparator), value };
|
|
414
609
|
return { display: `${negative ? "-" : ""}${groupInteger(integer || "0", thousandSeparator)}${hasDecimal ? `${decimalSeparator}${fraction}` : ""}`, value };
|
|
415
610
|
}
|
|
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) {
|
|
611
|
+
var NumberInput = forwardRef3(function NumberInput2({ value, defaultValue = null, onValueChange, allowDecimal = true, decimals = 2, min, max, decimalSeparator = ".", thousandSeparator = ",", label, helperText, error, errorMessage, className, onBlur, onFocus, "aria-describedby": ariaDescribedBy, ...props }, ref) {
|
|
612
|
+
const generatedId = useId();
|
|
613
|
+
const messageId2 = `${generatedId}-message`;
|
|
417
614
|
const isControlled = value !== void 0;
|
|
418
|
-
const [internalValue, setInternalValue] =
|
|
419
|
-
const [focused, setFocused] =
|
|
615
|
+
const [internalValue, setInternalValue] = useState3(defaultValue);
|
|
616
|
+
const [focused, setFocused] = useState3(false);
|
|
420
617
|
const actualValue = isControlled ? value ?? null : internalValue;
|
|
421
|
-
const [text, setText] =
|
|
618
|
+
const [text, setText] = useState3(actualValue === null ? "" : formatNumber(actualValue, decimals, thousandSeparator, decimalSeparator));
|
|
619
|
+
const fieldError = getFieldError(error, errorMessage);
|
|
620
|
+
const hasError = fieldError !== void 0 && fieldError !== false && fieldError !== null;
|
|
621
|
+
const displayedMessage = hasError ? fieldError : helperText;
|
|
622
|
+
const describedBy = getDescribedBy(ariaDescribedBy, displayedMessage ? messageId2 : void 0);
|
|
422
623
|
useEffect3(() => {
|
|
423
624
|
if (!focused) setText(actualValue === null ? "" : formatNumber(actualValue, decimals, thousandSeparator, decimalSeparator));
|
|
424
625
|
}, [actualValue, decimalSeparator, decimals, focused, thousandSeparator]);
|
|
@@ -429,32 +630,32 @@ var NumberInput = forwardRef3(function NumberInput2({ value, defaultValue = null
|
|
|
429
630
|
if (!isControlled) setInternalValue(nextValue);
|
|
430
631
|
onValueChange?.(nextValue);
|
|
431
632
|
};
|
|
432
|
-
return /* @__PURE__ */
|
|
433
|
-
label && /* @__PURE__ */
|
|
434
|
-
/* @__PURE__ */
|
|
633
|
+
return /* @__PURE__ */ jsxs7("label", { className: ["fe-number-input", hasError && "fe-number-input--error", className].filter(Boolean).join(" "), children: [
|
|
634
|
+
label && /* @__PURE__ */ jsx7("span", { className: "fe-number-input__label", children: label }),
|
|
635
|
+
/* @__PURE__ */ jsx7("input", { ref, inputMode: allowDecimal ? "decimal" : "numeric", value: text, onFocus: (event) => {
|
|
435
636
|
setFocused(true);
|
|
436
637
|
onFocus?.(event);
|
|
437
638
|
}, onChange: (event) => updateValue(event.target.value), onBlur: (event) => {
|
|
438
639
|
setFocused(false);
|
|
439
640
|
onBlur?.(event);
|
|
440
|
-
}, ...props }),
|
|
441
|
-
|
|
641
|
+
}, ...props, "aria-invalid": hasError || void 0, "aria-describedby": describedBy }),
|
|
642
|
+
displayedMessage && /* @__PURE__ */ jsx7("span", { id: messageId2, className: hasError ? "fe-number-input__error" : "fe-number-input__helper", children: displayedMessage })
|
|
442
643
|
] });
|
|
443
644
|
});
|
|
444
645
|
NumberInput.displayName = "NumberInput";
|
|
445
646
|
function CurrencyInput({ suffix = "VND", currencies, currency, defaultCurrency, onCurrencyChange, className, ...props }) {
|
|
446
|
-
const [internalCurrency, setInternalCurrency] =
|
|
647
|
+
const [internalCurrency, setInternalCurrency] = useState3(defaultCurrency ?? currencies?.[0]?.code ?? "");
|
|
447
648
|
const selectedCurrency = currency ?? internalCurrency;
|
|
448
649
|
const current = currencies?.find((item) => item.code === selectedCurrency);
|
|
449
650
|
const currencySuffix = current?.suffix ?? current?.code ?? suffix;
|
|
450
|
-
return /* @__PURE__ */
|
|
451
|
-
/* @__PURE__ */
|
|
452
|
-
currencies?.length ? /* @__PURE__ */
|
|
651
|
+
return /* @__PURE__ */ jsxs7("div", { className: ["fe-currency-input", className].filter(Boolean).join(" "), children: [
|
|
652
|
+
/* @__PURE__ */ jsx7(NumberInput, { ...props, className: "fe-currency-input__number" }),
|
|
653
|
+
currencies?.length ? /* @__PURE__ */ jsx7("select", { className: "fe-currency-input__currency", "aria-label": "Currency", value: selectedCurrency, onChange: (event) => {
|
|
453
654
|
const next = currencies.find((item) => item.code === event.target.value);
|
|
454
655
|
if (!next) return;
|
|
455
656
|
if (currency === void 0) setInternalCurrency(next.code);
|
|
456
657
|
onCurrencyChange?.(next);
|
|
457
|
-
}, children: currencies.map((item) => /* @__PURE__ */
|
|
658
|
+
}, children: currencies.map((item) => /* @__PURE__ */ jsx7("option", { value: item.code, children: item.label ?? item.code }, item.code)) }) : /* @__PURE__ */ jsx7("span", { className: "fe-currency-input__suffix", children: currencySuffix })
|
|
458
659
|
] });
|
|
459
660
|
}
|
|
460
661
|
var pad = (value) => String(value).padStart(2, "0");
|
|
@@ -477,13 +678,13 @@ function DateTimePicker(props) {
|
|
|
477
678
|
const { label, format = "dd/MM/yyyy HH:mm", disabled, placeholder, locale = "en-US", className, mode = "single" } = props;
|
|
478
679
|
const isRange = mode === "range";
|
|
479
680
|
const controlled = props.value !== void 0;
|
|
480
|
-
const [singleInternal, setSingleInternal] =
|
|
481
|
-
const [rangeInternal, setRangeInternal] =
|
|
681
|
+
const [singleInternal, setSingleInternal] = useState3((!isRange ? props.defaultValue : null) ?? null);
|
|
682
|
+
const [rangeInternal, setRangeInternal] = useState3((isRange ? props.defaultValue : void 0) ?? [null, null]);
|
|
482
683
|
const singleValue = !isRange ? props.value ?? singleInternal : null;
|
|
483
684
|
const rangeValue = isRange ? props.value ?? rangeInternal : [null, null];
|
|
484
|
-
const [open, setOpen] =
|
|
485
|
-
const [month, setMonth] =
|
|
486
|
-
const [editingEnd, setEditingEnd] =
|
|
685
|
+
const [open, setOpen] = useState3(false);
|
|
686
|
+
const [month, setMonth] = useState3(() => new Date((isRange ? rangeValue[0] : singleValue) ?? /* @__PURE__ */ new Date()));
|
|
687
|
+
const [editingEnd, setEditingEnd] = useState3(false);
|
|
487
688
|
const rootRef = useRef2(null);
|
|
488
689
|
useEffect3(() => {
|
|
489
690
|
const onPointerDown = (event) => {
|
|
@@ -527,42 +728,42 @@ function DateTimePicker(props) {
|
|
|
527
728
|
if (isRange) setRange(editingEnd ? [rangeValue[0], next] : [next, rangeValue[1]]);
|
|
528
729
|
else setSingle(next);
|
|
529
730
|
};
|
|
530
|
-
return /* @__PURE__ */
|
|
531
|
-
label && /* @__PURE__ */
|
|
532
|
-
/* @__PURE__ */
|
|
533
|
-
/* @__PURE__ */
|
|
534
|
-
/* @__PURE__ */
|
|
731
|
+
return /* @__PURE__ */ jsxs7("div", { ref: rootRef, className: ["fe-datetime-picker", className].filter(Boolean).join(" "), children: [
|
|
732
|
+
label && /* @__PURE__ */ jsx7("span", { className: "fe-datetime-picker__label", children: label }),
|
|
733
|
+
/* @__PURE__ */ jsxs7("button", { type: "button", className: "fe-datetime-picker__trigger", disabled, "aria-expanded": open, onClick: () => setOpen((current) => !current), children: [
|
|
734
|
+
/* @__PURE__ */ jsx7("span", { "aria-hidden": "true", children: "\u25F7" }),
|
|
735
|
+
/* @__PURE__ */ jsx7("span", { children: shownValue || placeholder || (isRange ? "Select date range" : "Select date and time") })
|
|
535
736
|
] }),
|
|
536
|
-
open && /* @__PURE__ */
|
|
537
|
-
/* @__PURE__ */
|
|
538
|
-
/* @__PURE__ */
|
|
539
|
-
/* @__PURE__ */
|
|
540
|
-
/* @__PURE__ */
|
|
737
|
+
open && /* @__PURE__ */ jsxs7("div", { className: "fe-datetime-picker__popper", role: "dialog", "aria-label": "Date and time picker", children: [
|
|
738
|
+
/* @__PURE__ */ jsxs7("div", { className: "fe-datetime-picker__month", children: [
|
|
739
|
+
/* @__PURE__ */ jsx7("button", { type: "button", "aria-label": "Previous month", onClick: () => setMonth((current) => new Date(current.getFullYear(), current.getMonth() - 1, 1)), children: "\u2039" }),
|
|
740
|
+
/* @__PURE__ */ jsx7("strong", { children: month.toLocaleDateString(locale, { month: "long", year: "numeric" }) }),
|
|
741
|
+
/* @__PURE__ */ jsx7("button", { type: "button", "aria-label": "Next month", onClick: () => setMonth((current) => new Date(current.getFullYear(), current.getMonth() + 1, 1)), children: "\u203A" })
|
|
541
742
|
] }),
|
|
542
|
-
/* @__PURE__ */
|
|
543
|
-
/* @__PURE__ */
|
|
743
|
+
/* @__PURE__ */ jsx7("div", { className: "fe-datetime-picker__weekdays", children: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"].map((day) => /* @__PURE__ */ jsx7("span", { children: day }, day)) }),
|
|
744
|
+
/* @__PURE__ */ jsx7("div", { className: "fe-datetime-picker__days", children: days.map((day) => {
|
|
544
745
|
const inMonth = day.getMonth() === month.getMonth();
|
|
545
746
|
const selected = isRange ? sameDay(day, rangeValue[0]) || sameDay(day, rangeValue[1]) : sameDay(day, singleValue);
|
|
546
747
|
const inRange = isRange && rangeValue[0] && rangeValue[1] && day > startOfDay(rangeValue[0]) && day < startOfDay(rangeValue[1]);
|
|
547
|
-
return /* @__PURE__ */
|
|
748
|
+
return /* @__PURE__ */ jsx7("button", { type: "button", className: [!inMonth && "is-other-month", selected && "is-selected", inRange && "is-in-range"].filter(Boolean).join(" "), onClick: () => selectDay(day), children: day.getDate() }, day.toISOString());
|
|
548
749
|
}) }),
|
|
549
|
-
isRange && /* @__PURE__ */
|
|
550
|
-
/* @__PURE__ */
|
|
551
|
-
/* @__PURE__ */
|
|
750
|
+
isRange && /* @__PURE__ */ jsxs7("div", { className: "fe-datetime-picker__range-tabs", children: [
|
|
751
|
+
/* @__PURE__ */ jsx7("button", { type: "button", className: !editingEnd ? "is-active" : "", onClick: () => setEditingEnd(false), children: "Start" }),
|
|
752
|
+
/* @__PURE__ */ jsx7("button", { type: "button", className: editingEnd ? "is-active" : "", onClick: () => setEditingEnd(true), children: "End" })
|
|
552
753
|
] }),
|
|
553
|
-
/* @__PURE__ */
|
|
754
|
+
/* @__PURE__ */ jsxs7("label", { className: "fe-datetime-picker__time", children: [
|
|
554
755
|
"Time",
|
|
555
|
-
/* @__PURE__ */
|
|
756
|
+
/* @__PURE__ */ jsx7("input", { type: "time", value: selectedForTime ? `${pad(selectedForTime.getHours())}:${pad(selectedForTime.getMinutes())}` : "00:00", onChange: (event) => setTime(event.target.value), disabled: !selectedForTime })
|
|
556
757
|
] })
|
|
557
758
|
] })
|
|
558
759
|
] });
|
|
559
760
|
}
|
|
560
761
|
|
|
561
762
|
// packages/tooltip/src/index.tsx
|
|
562
|
-
import { cloneElement, useId as useId2, useState as
|
|
563
|
-
import { jsx as
|
|
763
|
+
import { cloneElement, useId as useId2, useState as useState4 } from "react";
|
|
764
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
564
765
|
function Tooltip({ content, children, placement = "top", disabled, className, ...props }) {
|
|
565
|
-
const [visible, setVisible] =
|
|
766
|
+
const [visible, setVisible] = useState4(false);
|
|
566
767
|
const id = useId2();
|
|
567
768
|
const trigger = cloneElement(children, { "aria-describedby": visible ? id : void 0, onMouseEnter: (event) => {
|
|
568
769
|
children.props.onMouseEnter?.(event);
|
|
@@ -577,17 +778,17 @@ function Tooltip({ content, children, placement = "top", disabled, className, ..
|
|
|
577
778
|
children.props.onBlur?.(event);
|
|
578
779
|
setVisible(false);
|
|
579
780
|
} });
|
|
580
|
-
return /* @__PURE__ */
|
|
781
|
+
return /* @__PURE__ */ jsxs8("span", { className: ["fe-tooltip", `fe-tooltip--${placement}`, className].filter(Boolean).join(" "), ...props, children: [
|
|
581
782
|
trigger,
|
|
582
|
-
visible && !disabled && /* @__PURE__ */
|
|
783
|
+
visible && !disabled && /* @__PURE__ */ jsx8("span", { id, role: "tooltip", className: "fe-tooltip__content", children: content })
|
|
583
784
|
] });
|
|
584
785
|
}
|
|
585
786
|
|
|
586
787
|
// packages/expandable-section/src/index.tsx
|
|
587
|
-
import { useId as useId3, useState as
|
|
588
|
-
import { jsx as
|
|
788
|
+
import { useId as useId3, useState as useState5 } from "react";
|
|
789
|
+
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
589
790
|
function ExpandableSection({ title, children, expanded, defaultExpanded = false, onExpandedChange, disabled, className, ...props }) {
|
|
590
|
-
const [internalExpanded, setInternalExpanded] =
|
|
791
|
+
const [internalExpanded, setInternalExpanded] = useState5(defaultExpanded);
|
|
591
792
|
const isExpanded = expanded ?? internalExpanded;
|
|
592
793
|
const id = useId3();
|
|
593
794
|
const toggle = () => {
|
|
@@ -596,26 +797,304 @@ function ExpandableSection({ title, children, expanded, defaultExpanded = false,
|
|
|
596
797
|
if (expanded === void 0) setInternalExpanded(next);
|
|
597
798
|
onExpandedChange?.(next);
|
|
598
799
|
};
|
|
599
|
-
return /* @__PURE__ */
|
|
600
|
-
/* @__PURE__ */
|
|
601
|
-
/* @__PURE__ */
|
|
602
|
-
/* @__PURE__ */
|
|
800
|
+
return /* @__PURE__ */ jsxs9("section", { className: ["fe-expandable-section", isExpanded && "fe-expandable-section--expanded", disabled && "fe-expandable-section--disabled", className].filter(Boolean).join(" "), ...props, children: [
|
|
801
|
+
/* @__PURE__ */ jsxs9("button", { className: "fe-expandable-section__trigger", type: "button", "aria-expanded": isExpanded, "aria-controls": id, disabled, onClick: toggle, children: [
|
|
802
|
+
/* @__PURE__ */ jsx9("span", { children: title }),
|
|
803
|
+
/* @__PURE__ */ jsx9("span", { className: "fe-expandable-section__chevron", "aria-hidden": "true" })
|
|
804
|
+
] }),
|
|
805
|
+
/* @__PURE__ */ jsx9("div", { id, className: "fe-expandable-section__content", "aria-hidden": !isExpanded, children: /* @__PURE__ */ jsx9("div", { className: "fe-expandable-section__content-inner", children }) })
|
|
806
|
+
] });
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
// packages/loading/src/index.tsx
|
|
810
|
+
import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
811
|
+
var sizes = {
|
|
812
|
+
small: "16px",
|
|
813
|
+
medium: "24px",
|
|
814
|
+
large: "40px"
|
|
815
|
+
};
|
|
816
|
+
function Loading({ size = "medium", color = "#2878f0", label, className, style, ...props }) {
|
|
817
|
+
const diameter = typeof size === "number" ? `${size}px` : sizes[size];
|
|
818
|
+
const loadingStyle = {
|
|
819
|
+
"--fe-loading-size": diameter,
|
|
820
|
+
"--fe-loading-color": color,
|
|
821
|
+
...style
|
|
822
|
+
};
|
|
823
|
+
return /* @__PURE__ */ jsxs10("span", { className: ["fe-loading", className].filter(Boolean).join(" "), style: loadingStyle, role: "status", ...props, children: [
|
|
824
|
+
/* @__PURE__ */ jsx10("span", { className: "fe-loading__spinner", "aria-hidden": "true" }),
|
|
825
|
+
label && /* @__PURE__ */ jsx10("span", { className: "fe-loading__label", children: label }),
|
|
826
|
+
!label && /* @__PURE__ */ jsx10("span", { className: "fe-loading__sr-only", children: "Loading" })
|
|
827
|
+
] });
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
// packages/skeleton/src/index.tsx
|
|
831
|
+
import { Fragment as Fragment2, jsx as jsx11 } from "react/jsx-runtime";
|
|
832
|
+
var pixels = (value) => typeof value === "number" ? `${value}px` : value;
|
|
833
|
+
function SkeletonBase({ variant = "box", shape, width, height, count = 1, animated = true, className, style, ...props }) {
|
|
834
|
+
const resolvedVariant = shape ?? variant;
|
|
835
|
+
const resolvedWidth = pixels(width) ?? (resolvedVariant === "circle" ? "40px" : "100%");
|
|
836
|
+
const resolvedHeight = pixels(height) ?? (resolvedVariant === "circle" ? resolvedWidth : resolvedVariant === "line" ? "12px" : "80px");
|
|
837
|
+
const skeletonStyle = {
|
|
838
|
+
"--fe-skeleton-width": resolvedWidth,
|
|
839
|
+
"--fe-skeleton-height": resolvedHeight,
|
|
840
|
+
...style
|
|
841
|
+
};
|
|
842
|
+
return /* @__PURE__ */ jsx11(Fragment2, { children: Array.from({ length: Math.max(1, count) }, (_, index) => /* @__PURE__ */ jsx11(
|
|
843
|
+
"div",
|
|
844
|
+
{
|
|
845
|
+
className: ["fe-skeleton", `fe-skeleton--${resolvedVariant}`, animated && "fe-skeleton--animated", className].filter(Boolean).join(" "),
|
|
846
|
+
style: skeletonStyle,
|
|
847
|
+
"aria-hidden": "true",
|
|
848
|
+
...props
|
|
849
|
+
},
|
|
850
|
+
index
|
|
851
|
+
)) });
|
|
852
|
+
}
|
|
853
|
+
function SkeletonCircle({ size = 40, ...props }) {
|
|
854
|
+
return /* @__PURE__ */ jsx11(SkeletonBase, { variant: "circle", width: size, height: size, ...props });
|
|
855
|
+
}
|
|
856
|
+
function SkeletonSquare({ size = 80, ...props }) {
|
|
857
|
+
return /* @__PURE__ */ jsx11(SkeletonBase, { variant: "box", width: size, height: size, ...props });
|
|
858
|
+
}
|
|
859
|
+
function SkeletonBox({ width = "100%", height = 80, ...props }) {
|
|
860
|
+
return /* @__PURE__ */ jsx11(SkeletonBase, { variant: "box", width, height, ...props });
|
|
861
|
+
}
|
|
862
|
+
function SkeletonLine({ width = "100%", height = 12, ...props }) {
|
|
863
|
+
return /* @__PURE__ */ jsx11(SkeletonBase, { variant: "line", width, height, ...props });
|
|
864
|
+
}
|
|
865
|
+
var Skeleton = Object.assign(SkeletonBase, {
|
|
866
|
+
Circle: SkeletonCircle,
|
|
867
|
+
Square: SkeletonSquare,
|
|
868
|
+
Box: SkeletonBox,
|
|
869
|
+
Line: SkeletonLine
|
|
870
|
+
});
|
|
871
|
+
|
|
872
|
+
// packages/modal/src/index.tsx
|
|
873
|
+
import { useEffect as useEffect4, useId as useId4, useRef as useRef3 } from "react";
|
|
874
|
+
import { createPortal as createPortal3 } from "react-dom";
|
|
875
|
+
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
876
|
+
function Modal({
|
|
877
|
+
open,
|
|
878
|
+
onClose,
|
|
879
|
+
title,
|
|
880
|
+
description,
|
|
881
|
+
children,
|
|
882
|
+
footer,
|
|
883
|
+
actions = [],
|
|
884
|
+
size = "medium",
|
|
885
|
+
closeOnBackdropClick = true,
|
|
886
|
+
closeButton = true,
|
|
887
|
+
closeLabel = "Close modal",
|
|
888
|
+
className,
|
|
889
|
+
...props
|
|
890
|
+
}) {
|
|
891
|
+
const titleId = useId4();
|
|
892
|
+
const panelRef = useRef3(null);
|
|
893
|
+
useEffect4(() => {
|
|
894
|
+
if (!open) return;
|
|
895
|
+
const onKeyDown = (event) => {
|
|
896
|
+
if (event.key === "Escape") onClose();
|
|
897
|
+
};
|
|
898
|
+
document.addEventListener("keydown", onKeyDown);
|
|
899
|
+
panelRef.current?.focus();
|
|
900
|
+
return () => document.removeEventListener("keydown", onKeyDown);
|
|
901
|
+
}, [onClose, open]);
|
|
902
|
+
if (!open || typeof document === "undefined") return null;
|
|
903
|
+
const hasFooter = footer || actions.length > 0;
|
|
904
|
+
return createPortal3(
|
|
905
|
+
/* @__PURE__ */ jsx12("div", { className: "fe-modal-backdrop", role: "presentation", onMouseDown: (event) => {
|
|
906
|
+
if (event.target === event.currentTarget && closeOnBackdropClick) onClose();
|
|
907
|
+
}, children: /* @__PURE__ */ jsxs11(
|
|
908
|
+
"div",
|
|
909
|
+
{
|
|
910
|
+
ref: panelRef,
|
|
911
|
+
className: ["fe-modal", `fe-modal--${size}`, className].filter(Boolean).join(" "),
|
|
912
|
+
role: "dialog",
|
|
913
|
+
"aria-modal": "true",
|
|
914
|
+
"aria-labelledby": title ? titleId : void 0,
|
|
915
|
+
"aria-label": title ? void 0 : "Modal",
|
|
916
|
+
tabIndex: -1,
|
|
917
|
+
...props,
|
|
918
|
+
children: [
|
|
919
|
+
(title || description || closeButton) && /* @__PURE__ */ jsxs11("header", { className: "fe-modal__header", children: [
|
|
920
|
+
/* @__PURE__ */ jsxs11("div", { className: "fe-modal__heading", children: [
|
|
921
|
+
title && /* @__PURE__ */ jsx12("h2", { id: titleId, children: title }),
|
|
922
|
+
description && /* @__PURE__ */ jsx12("p", { children: description })
|
|
923
|
+
] }),
|
|
924
|
+
closeButton && /* @__PURE__ */ jsx12(Button, { hierarchy: "tertiary-gray", size: "32", iconOnly: true, icon: /* @__PURE__ */ jsx12(CloseIcon, {}), "aria-label": closeLabel, onClick: onClose })
|
|
925
|
+
] }),
|
|
926
|
+
/* @__PURE__ */ jsx12("div", { className: "fe-modal__body", children }),
|
|
927
|
+
hasFooter && /* @__PURE__ */ jsxs11("footer", { className: "fe-modal__footer", children: [
|
|
928
|
+
footer && /* @__PURE__ */ jsx12("div", { className: "fe-modal__footer-content", children: footer }),
|
|
929
|
+
actions.length > 0 && /* @__PURE__ */ jsx12("div", { className: "fe-modal__actions", children: actions.map(({ label, ...action }, index) => /* @__PURE__ */ jsx12(Button, { ...action, children: label }, index)) })
|
|
930
|
+
] })
|
|
931
|
+
]
|
|
932
|
+
}
|
|
933
|
+
) }),
|
|
934
|
+
document.body
|
|
935
|
+
);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
// packages/progress/src/index.tsx
|
|
939
|
+
import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
940
|
+
function ProgressBar({ value, max = 100, label, showValue = true, size = "medium", color = "#2878f0", className, style, "aria-label": ariaLabel, ...props }) {
|
|
941
|
+
const indeterminate = value === null || value === void 0;
|
|
942
|
+
const percentage = indeterminate ? 0 : Math.min(100, Math.max(0, Number(value) / Math.max(1, max) * 100));
|
|
943
|
+
const progressStyle = {
|
|
944
|
+
"--fe-progress-value": `${percentage}%`,
|
|
945
|
+
"--fe-progress-color": color,
|
|
946
|
+
...style
|
|
947
|
+
};
|
|
948
|
+
const visibleValue = `${Math.round(percentage)}%`;
|
|
949
|
+
return /* @__PURE__ */ jsxs12("div", { className: ["fe-progress", `fe-progress--${size}`, indeterminate && "fe-progress--indeterminate", className].filter(Boolean).join(" "), style: progressStyle, ...props, children: [
|
|
950
|
+
(label || !indeterminate && showValue) && /* @__PURE__ */ jsxs12("div", { className: "fe-progress__meta", children: [
|
|
951
|
+
label && /* @__PURE__ */ jsx13("span", { className: "fe-progress__label", children: label }),
|
|
952
|
+
!indeterminate && showValue && /* @__PURE__ */ jsx13("output", { className: "fe-progress__value", children: visibleValue })
|
|
603
953
|
] }),
|
|
604
|
-
/* @__PURE__ */
|
|
954
|
+
/* @__PURE__ */ jsx13("div", { className: "fe-progress__track", role: "progressbar", "aria-label": ariaLabel ?? (typeof label === "string" ? label : "Progress"), "aria-valuemin": indeterminate ? void 0 : 0, "aria-valuemax": indeterminate ? void 0 : max, "aria-valuenow": indeterminate ? void 0 : Number(value), "aria-valuetext": indeterminate ? "Loading" : visibleValue, children: /* @__PURE__ */ jsx13("span", { className: "fe-progress__indicator" }) })
|
|
955
|
+
] });
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
// packages/chip/src/index.tsx
|
|
959
|
+
import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
960
|
+
var statuses = ["default", "info", "success", "warning", "error", "neutral", "pending", "processing"];
|
|
961
|
+
function Chip({ children, status = "default", color, variant = "subtle", dot = false, onRemove, removeLabel = "Remove", className, style, ...props }) {
|
|
962
|
+
const usesCustomColor = Boolean(color);
|
|
963
|
+
const chipStyle = {
|
|
964
|
+
...usesCustomColor ? { "--fe-chip-custom-color": color } : {},
|
|
965
|
+
...style
|
|
966
|
+
};
|
|
967
|
+
const resolvedStatus = statuses.includes(status) ? status : "default";
|
|
968
|
+
return /* @__PURE__ */ jsxs13("span", { className: ["fe-chip", `fe-chip--${variant}`, `fe-chip--${usesCustomColor ? "custom" : resolvedStatus}`, className].filter(Boolean).join(" "), style: chipStyle, ...props, children: [
|
|
969
|
+
dot && /* @__PURE__ */ jsx14("span", { className: "fe-chip__dot", "aria-hidden": "true" }),
|
|
970
|
+
/* @__PURE__ */ jsx14("span", { className: "fe-chip__content", children }),
|
|
971
|
+
onRemove && /* @__PURE__ */ jsx14(Button, { hierarchy: "tertiary-gray", size: "24", iconOnly: true, icon: /* @__PURE__ */ jsx14(CloseIcon, { size: 14 }), "aria-label": removeLabel, onClick: onRemove, className: "fe-chip__remove" })
|
|
605
972
|
] });
|
|
606
973
|
}
|
|
974
|
+
|
|
975
|
+
// packages/message/src/index.tsx
|
|
976
|
+
import { useEffect as useEffect5, useState as useState6 } from "react";
|
|
977
|
+
import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
978
|
+
var messageId = 0;
|
|
979
|
+
var entries = [];
|
|
980
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
981
|
+
var timers = /* @__PURE__ */ new Map();
|
|
982
|
+
var publish = () => listeners.forEach((listener) => listener(entries));
|
|
983
|
+
function dismiss(id) {
|
|
984
|
+
const timer = timers.get(id);
|
|
985
|
+
if (timer) window.clearTimeout(timer);
|
|
986
|
+
timers.delete(id);
|
|
987
|
+
const entry = entries.find((item) => item.id === id);
|
|
988
|
+
entries = entries.filter((item) => item.id !== id);
|
|
989
|
+
entry?.onClose?.();
|
|
990
|
+
publish();
|
|
991
|
+
}
|
|
992
|
+
function show({ duration = 4500, severity = "info", ...options }) {
|
|
993
|
+
const id = ++messageId;
|
|
994
|
+
entries = [...entries, { id, duration, severity, ...options }];
|
|
995
|
+
publish();
|
|
996
|
+
if (duration !== null) timers.set(id, window.setTimeout(() => dismiss(id), duration));
|
|
997
|
+
return id;
|
|
998
|
+
}
|
|
999
|
+
var message = {
|
|
1000
|
+
show,
|
|
1001
|
+
success: (content, options = {}) => show({ content, severity: "success", ...options }),
|
|
1002
|
+
info: (content, options = {}) => show({ content, severity: "info", ...options }),
|
|
1003
|
+
warning: (content, options = {}) => show({ content, severity: "warning", ...options }),
|
|
1004
|
+
error: (content, options = {}) => show({ content, severity: "error", ...options }),
|
|
1005
|
+
dismiss,
|
|
1006
|
+
clear: () => [...entries].forEach((entry) => dismiss(entry.id))
|
|
1007
|
+
};
|
|
1008
|
+
var icons = { success: "\u2713", info: "i", warning: "!", error: "\xD7" };
|
|
1009
|
+
function Message({ maxCount = 4, closeLabel = "Close notification", className, ...props }) {
|
|
1010
|
+
const [visibleEntries, setVisibleEntries] = useState6(entries);
|
|
1011
|
+
useEffect5(() => {
|
|
1012
|
+
const listener = (nextEntries) => setVisibleEntries(nextEntries);
|
|
1013
|
+
listeners.add(listener);
|
|
1014
|
+
return () => {
|
|
1015
|
+
listeners.delete(listener);
|
|
1016
|
+
};
|
|
1017
|
+
}, []);
|
|
1018
|
+
return /* @__PURE__ */ jsx15("div", { className: ["fe-message-viewport", className].filter(Boolean).join(" "), "aria-live": "polite", ...props, children: visibleEntries.slice(-Math.max(1, maxCount)).map((entry) => /* @__PURE__ */ jsxs14("div", { className: `fe-message fe-message--${entry.severity ?? "info"}`, role: entry.severity === "error" ? "alert" : "status", children: [
|
|
1019
|
+
/* @__PURE__ */ jsx15("span", { className: "fe-message__icon", "aria-hidden": "true", children: icons[entry.severity ?? "info"] }),
|
|
1020
|
+
/* @__PURE__ */ jsxs14("div", { className: "fe-message__body", children: [
|
|
1021
|
+
entry.title && /* @__PURE__ */ jsx15("strong", { className: "fe-message__title", children: entry.title }),
|
|
1022
|
+
/* @__PURE__ */ jsx15("div", { className: "fe-message__content", children: entry.content })
|
|
1023
|
+
] }),
|
|
1024
|
+
entry.action && /* @__PURE__ */ jsx15("span", { className: "fe-message__action", children: entry.action }),
|
|
1025
|
+
/* @__PURE__ */ jsx15(Button, { className: "fe-message__close", hierarchy: "tertiary-gray", size: "24", iconOnly: true, icon: "\xD7", "aria-label": closeLabel, onClick: () => dismiss(entry.id) })
|
|
1026
|
+
] }, entry.id)) });
|
|
1027
|
+
}
|
|
1028
|
+
((Message2) => {
|
|
1029
|
+
Message2.show = message.show;
|
|
1030
|
+
Message2.success = message.success;
|
|
1031
|
+
Message2.info = message.info;
|
|
1032
|
+
Message2.warning = message.warning;
|
|
1033
|
+
Message2.error = message.error;
|
|
1034
|
+
Message2.dismiss = message.dismiss;
|
|
1035
|
+
Message2.clear = message.clear;
|
|
1036
|
+
})(Message || (Message = {}));
|
|
1037
|
+
|
|
1038
|
+
// packages/snackbar/src/index.tsx
|
|
1039
|
+
import { useEffect as useEffect6 } from "react";
|
|
1040
|
+
import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1041
|
+
function Snackbar({
|
|
1042
|
+
open,
|
|
1043
|
+
message: message2,
|
|
1044
|
+
autoHideDuration = 5e3,
|
|
1045
|
+
onClose,
|
|
1046
|
+
action,
|
|
1047
|
+
anchorOrigin = {},
|
|
1048
|
+
closeLabel = "Close notification",
|
|
1049
|
+
className,
|
|
1050
|
+
...props
|
|
1051
|
+
}) {
|
|
1052
|
+
const vertical = anchorOrigin.vertical ?? "bottom";
|
|
1053
|
+
const horizontal = anchorOrigin.horizontal ?? "center";
|
|
1054
|
+
useEffect6(() => {
|
|
1055
|
+
if (!open || autoHideDuration === null) return void 0;
|
|
1056
|
+
const timer = window.setTimeout(() => onClose?.("timeout"), autoHideDuration);
|
|
1057
|
+
return () => window.clearTimeout(timer);
|
|
1058
|
+
}, [open, autoHideDuration, onClose]);
|
|
1059
|
+
useEffect6(() => {
|
|
1060
|
+
if (!open) return void 0;
|
|
1061
|
+
const onKeyDown = (event) => {
|
|
1062
|
+
if (event.key === "Escape") onClose?.("escapeKeyDown");
|
|
1063
|
+
};
|
|
1064
|
+
window.addEventListener("keydown", onKeyDown);
|
|
1065
|
+
return () => window.removeEventListener("keydown", onKeyDown);
|
|
1066
|
+
}, [open, onClose]);
|
|
1067
|
+
if (!open) return null;
|
|
1068
|
+
return /* @__PURE__ */ jsx16("div", { className: ["fe-snackbar", `fe-snackbar--${vertical}`, `fe-snackbar--${horizontal}`, className].filter(Boolean).join(" "), ...props, children: /* @__PURE__ */ jsxs15("div", { className: "fe-snackbar__content", role: "status", "aria-live": "polite", children: [
|
|
1069
|
+
/* @__PURE__ */ jsx16("span", { className: "fe-snackbar__message", children: message2 }),
|
|
1070
|
+
action && /* @__PURE__ */ jsx16("span", { className: "fe-snackbar__action", children: action }),
|
|
1071
|
+
onClose && /* @__PURE__ */ jsx16(Button, { className: "fe-snackbar__close", hierarchy: "tertiary-gray", size: "24", iconOnly: true, icon: "\xD7", "aria-label": closeLabel, onClick: () => onClose("closeButton") })
|
|
1072
|
+
] }) });
|
|
1073
|
+
}
|
|
607
1074
|
export {
|
|
608
1075
|
Button,
|
|
609
1076
|
ChevronDownIcon,
|
|
1077
|
+
Chip,
|
|
610
1078
|
CloseIcon,
|
|
611
1079
|
CurrencyInput,
|
|
612
1080
|
DateTimePicker,
|
|
613
1081
|
Drawer,
|
|
614
1082
|
ExpandableSection,
|
|
1083
|
+
Loading,
|
|
1084
|
+
Message,
|
|
1085
|
+
Modal,
|
|
615
1086
|
NumberInput,
|
|
1087
|
+
Pagination,
|
|
616
1088
|
PlusIcon,
|
|
1089
|
+
ProgressBar,
|
|
617
1090
|
SearchIcon,
|
|
618
1091
|
Selection,
|
|
1092
|
+
Skeleton,
|
|
1093
|
+
SkeletonBox,
|
|
1094
|
+
SkeletonCircle,
|
|
1095
|
+
SkeletonLine,
|
|
1096
|
+
SkeletonSquare,
|
|
1097
|
+
Snackbar,
|
|
619
1098
|
Table,
|
|
620
1099
|
TableBody,
|
|
621
1100
|
TableCaption,
|
|
@@ -623,8 +1102,11 @@ export {
|
|
|
623
1102
|
TableHead,
|
|
624
1103
|
TableHeader,
|
|
625
1104
|
TableRow,
|
|
1105
|
+
TextArea,
|
|
1106
|
+
TextInput,
|
|
626
1107
|
Toggle,
|
|
627
1108
|
Tooltip,
|
|
628
1109
|
formatNumber,
|
|
629
|
-
getIconSize
|
|
1110
|
+
getIconSize,
|
|
1111
|
+
message
|
|
630
1112
|
};
|