@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/README.md +51 -14
- package/dist/index.d.mts +234 -5
- package/dist/index.d.ts +234 -5
- package/dist/index.js +636 -158
- package/dist/index.mjs +601 -138
- package/dist/styles.css +669 -10
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22,15 +22,27 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
Button: () => Button,
|
|
24
24
|
ChevronDownIcon: () => ChevronDownIcon,
|
|
25
|
+
Chip: () => Chip,
|
|
25
26
|
CloseIcon: () => CloseIcon,
|
|
26
27
|
CurrencyInput: () => CurrencyInput,
|
|
27
28
|
DateTimePicker: () => DateTimePicker,
|
|
28
29
|
Drawer: () => Drawer,
|
|
29
30
|
ExpandableSection: () => ExpandableSection,
|
|
31
|
+
Loading: () => Loading,
|
|
32
|
+
Message: () => Message,
|
|
33
|
+
Modal: () => Modal,
|
|
30
34
|
NumberInput: () => NumberInput,
|
|
35
|
+
Pagination: () => Pagination,
|
|
31
36
|
PlusIcon: () => PlusIcon,
|
|
37
|
+
ProgressBar: () => ProgressBar,
|
|
32
38
|
SearchIcon: () => SearchIcon,
|
|
33
39
|
Selection: () => Selection,
|
|
40
|
+
Skeleton: () => Skeleton,
|
|
41
|
+
SkeletonBox: () => SkeletonBox,
|
|
42
|
+
SkeletonCircle: () => SkeletonCircle,
|
|
43
|
+
SkeletonLine: () => SkeletonLine,
|
|
44
|
+
SkeletonSquare: () => SkeletonSquare,
|
|
45
|
+
Snackbar: () => Snackbar,
|
|
34
46
|
Table: () => Table,
|
|
35
47
|
TableBody: () => TableBody,
|
|
36
48
|
TableCaption: () => TableCaption,
|
|
@@ -38,10 +50,13 @@ __export(index_exports, {
|
|
|
38
50
|
TableHead: () => TableHead,
|
|
39
51
|
TableHeader: () => TableHeader,
|
|
40
52
|
TableRow: () => TableRow,
|
|
53
|
+
TextArea: () => TextArea,
|
|
54
|
+
TextInput: () => TextInput,
|
|
41
55
|
Toggle: () => Toggle,
|
|
42
56
|
Tooltip: () => Tooltip,
|
|
43
57
|
formatNumber: () => formatNumber,
|
|
44
|
-
getIconSize: () => getIconSize
|
|
58
|
+
getIconSize: () => getIconSize,
|
|
59
|
+
message: () => message
|
|
45
60
|
});
|
|
46
61
|
module.exports = __toCommonJS(index_exports);
|
|
47
62
|
|
|
@@ -138,9 +153,76 @@ function SearchIcon(props) {
|
|
|
138
153
|
}
|
|
139
154
|
|
|
140
155
|
// packages/table/src/index.tsx
|
|
156
|
+
var import_react3 = require("react");
|
|
157
|
+
|
|
158
|
+
// packages/pagination/src/index.tsx
|
|
141
159
|
var import_react2 = require("react");
|
|
142
160
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
143
|
-
var
|
|
161
|
+
var clamp = (value, min, max) => Math.min(Math.max(value, min), max);
|
|
162
|
+
var range = (start, end) => Array.from({ length: Math.max(0, end - start + 1) }, (_, index) => start + index);
|
|
163
|
+
function getItems(totalPages, page, siblingCount, boundaryCount) {
|
|
164
|
+
const visibleCount = boundaryCount * 2 + siblingCount * 2 + 3;
|
|
165
|
+
if (totalPages <= visibleCount) return range(1, totalPages);
|
|
166
|
+
const startPages = range(1, boundaryCount);
|
|
167
|
+
const endPages = range(totalPages - boundaryCount + 1, totalPages);
|
|
168
|
+
const siblingsStart = Math.max(Math.min(page - siblingCount, totalPages - boundaryCount - siblingCount * 2 - 1), boundaryCount + 2);
|
|
169
|
+
const siblingsEnd = Math.min(Math.max(page + siblingCount, boundaryCount + siblingCount * 2 + 2), totalPages - boundaryCount - 1);
|
|
170
|
+
return [
|
|
171
|
+
...startPages,
|
|
172
|
+
...siblingsStart > boundaryCount + 2 ? ["start-ellipsis"] : siblingsStart === boundaryCount + 2 ? [boundaryCount + 1] : [],
|
|
173
|
+
...range(siblingsStart, siblingsEnd),
|
|
174
|
+
...siblingsEnd < totalPages - boundaryCount - 1 ? ["end-ellipsis"] : siblingsEnd === totalPages - boundaryCount - 1 ? [totalPages - boundaryCount] : [],
|
|
175
|
+
...endPages
|
|
176
|
+
];
|
|
177
|
+
}
|
|
178
|
+
function Pagination({
|
|
179
|
+
page,
|
|
180
|
+
defaultPage = 1,
|
|
181
|
+
totalPages,
|
|
182
|
+
onPageChange,
|
|
183
|
+
siblingCount = 1,
|
|
184
|
+
boundaryCount = 1,
|
|
185
|
+
disabled = false,
|
|
186
|
+
previousLabel = "Previous page",
|
|
187
|
+
nextLabel = "Next page",
|
|
188
|
+
className,
|
|
189
|
+
...props
|
|
190
|
+
}) {
|
|
191
|
+
const safeTotalPages = Math.max(1, Math.floor(totalPages));
|
|
192
|
+
const [uncontrolledPage, setUncontrolledPage] = (0, import_react2.useState)(() => clamp(defaultPage, 1, safeTotalPages));
|
|
193
|
+
const currentPage = clamp(page ?? uncontrolledPage, 1, safeTotalPages);
|
|
194
|
+
const items = (0, import_react2.useMemo)(
|
|
195
|
+
() => getItems(safeTotalPages, currentPage, Math.max(0, siblingCount), Math.max(0, boundaryCount)),
|
|
196
|
+
[safeTotalPages, currentPage, siblingCount, boundaryCount]
|
|
197
|
+
);
|
|
198
|
+
const selectPage = (nextPage) => {
|
|
199
|
+
const resolvedPage = clamp(nextPage, 1, safeTotalPages);
|
|
200
|
+
if (page === void 0) setUncontrolledPage(resolvedPage);
|
|
201
|
+
if (resolvedPage !== currentPage) onPageChange?.(resolvedPage);
|
|
202
|
+
};
|
|
203
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("nav", { className: ["fe-pagination", className].filter(Boolean).join(" "), "aria-label": "Pagination", ...props, children: [
|
|
204
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(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) }),
|
|
205
|
+
items.map((item, index) => item === "start-ellipsis" || item === "end-ellipsis" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fe-pagination__ellipsis", "aria-hidden": "true", children: "\u2026" }, `${item}-${index}`) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
206
|
+
Button,
|
|
207
|
+
{
|
|
208
|
+
className: "fe-pagination__button",
|
|
209
|
+
hierarchy: item === currentPage ? "primary" : "secondary-gray",
|
|
210
|
+
size: "40",
|
|
211
|
+
"aria-label": `Page ${item}`,
|
|
212
|
+
"aria-current": item === currentPage ? "page" : void 0,
|
|
213
|
+
disabled,
|
|
214
|
+
onClick: () => selectPage(item),
|
|
215
|
+
children: item
|
|
216
|
+
},
|
|
217
|
+
item
|
|
218
|
+
)),
|
|
219
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(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) })
|
|
220
|
+
] });
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// packages/table/src/index.tsx
|
|
224
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
225
|
+
var TableContext = (0, import_react3.createContext)({ striped: false });
|
|
144
226
|
var MIN_COLUMN_WIDTH = 96;
|
|
145
227
|
var MAX_COLUMN_WIDTH = 1200;
|
|
146
228
|
function getColumnCount(headers, data) {
|
|
@@ -149,7 +231,7 @@ function getColumnCount(headers, data) {
|
|
|
149
231
|
function getText(value) {
|
|
150
232
|
if (typeof value === "string" || typeof value === "number") return String(value);
|
|
151
233
|
if (Array.isArray(value)) return value.map(getText).join("");
|
|
152
|
-
if ((0,
|
|
234
|
+
if ((0, import_react3.isValidElement)(value)) return getText(value.props.children);
|
|
153
235
|
return "";
|
|
154
236
|
}
|
|
155
237
|
function autoColumnSize(columnIndex, headers, data) {
|
|
@@ -157,9 +239,9 @@ function autoColumnSize(columnIndex, headers, data) {
|
|
|
157
239
|
const longestText = values.reduce((longest, value) => Math.max(longest, getText(value).length), 0);
|
|
158
240
|
return Math.min(MAX_COLUMN_WIDTH, Math.max(MIN_COLUMN_WIDTH, longestText * 8 + 40));
|
|
159
241
|
}
|
|
160
|
-
function getInitialColumnSizes(headers, data,
|
|
242
|
+
function getInitialColumnSizes(headers, data, sizes2, minColumnWidth = MIN_COLUMN_WIDTH) {
|
|
161
243
|
return Array.from({ length: getColumnCount(headers, data) }, (_, columnIndex) => {
|
|
162
|
-
const suppliedSize =
|
|
244
|
+
const suppliedSize = sizes2?.[columnIndex];
|
|
163
245
|
return typeof suppliedSize === "number" && Number.isFinite(suppliedSize) ? Math.min(MAX_COLUMN_WIDTH, Math.max(minColumnWidth, suppliedSize)) : autoColumnSize(columnIndex, headers, data);
|
|
164
246
|
});
|
|
165
247
|
}
|
|
@@ -174,33 +256,48 @@ function DataTable({
|
|
|
174
256
|
columnSizes,
|
|
175
257
|
onColumnResize,
|
|
176
258
|
minColumnWidth = MIN_COLUMN_WIDTH,
|
|
259
|
+
pagination,
|
|
260
|
+
pageSize,
|
|
261
|
+
page,
|
|
262
|
+
defaultPage = 1,
|
|
263
|
+
onPageChange,
|
|
264
|
+
paginationPosition = "bottom-right",
|
|
177
265
|
className,
|
|
178
266
|
...props
|
|
179
267
|
}) {
|
|
180
268
|
const columnCount = getColumnCount(headers, data);
|
|
181
269
|
const safeMinWidth = Math.max(1, minColumnWidth);
|
|
182
|
-
const generatedSizes = (0,
|
|
270
|
+
const generatedSizes = (0, import_react3.useMemo)(
|
|
183
271
|
() => getInitialColumnSizes(headers, data, defaultColumnSizes, safeMinWidth),
|
|
184
272
|
[headers, data, defaultColumnSizes, safeMinWidth]
|
|
185
273
|
);
|
|
186
|
-
const [uncontrolledSizes, setUncontrolledSizes] = (0,
|
|
187
|
-
const
|
|
188
|
-
const
|
|
189
|
-
const
|
|
190
|
-
(0,
|
|
274
|
+
const [uncontrolledSizes, setUncontrolledSizes] = (0, import_react3.useState)(generatedSizes);
|
|
275
|
+
const shouldPaginate = pagination ?? pageSize !== void 0;
|
|
276
|
+
const safePageSize = Math.max(1, Math.floor(pageSize ?? 10));
|
|
277
|
+
const totalPages = Math.max(1, Math.ceil(data.length / safePageSize));
|
|
278
|
+
const [uncontrolledPage, setUncontrolledPage] = (0, import_react3.useState)(() => Math.min(Math.max(1, defaultPage), totalPages));
|
|
279
|
+
const currentPage = Math.min(Math.max(1, page ?? uncontrolledPage), totalPages);
|
|
280
|
+
const pagedData = shouldPaginate ? data.slice((currentPage - 1) * safePageSize, currentPage * safePageSize) : data;
|
|
281
|
+
const resizeState = (0, import_react3.useRef)();
|
|
282
|
+
const [isResizing, setIsResizing] = (0, import_react3.useState)(false);
|
|
283
|
+
const sizes2 = columnSizes ? getInitialColumnSizes(headers, data, columnSizes, safeMinWidth).map((size) => Math.max(safeMinWidth, size)) : uncontrolledSizes.map((size) => Math.max(safeMinWidth, size));
|
|
284
|
+
(0, import_react3.useEffect)(() => {
|
|
191
285
|
if (columnSizes) return;
|
|
192
286
|
setUncontrolledSizes((currentSizes) => {
|
|
193
287
|
const nextSizes = generatedSizes.map((generatedSize, index) => currentSizes[index] ?? generatedSize);
|
|
194
288
|
return sameSizes(currentSizes, nextSizes) ? currentSizes : nextSizes;
|
|
195
289
|
});
|
|
196
290
|
}, [columnSizes, generatedSizes]);
|
|
197
|
-
|
|
291
|
+
(0, import_react3.useEffect)(() => {
|
|
292
|
+
if (page === void 0 && uncontrolledPage > totalPages) setUncontrolledPage(totalPages);
|
|
293
|
+
}, [page, totalPages, uncontrolledPage]);
|
|
294
|
+
const updateColumnSize = (0, import_react3.useCallback)((columnIndex, nextSize) => {
|
|
198
295
|
const clampedSize = Math.min(MAX_COLUMN_WIDTH, Math.max(safeMinWidth, Math.round(nextSize)));
|
|
199
|
-
const nextSizes =
|
|
296
|
+
const nextSizes = sizes2.map((size, index) => index === columnIndex ? clampedSize : size);
|
|
200
297
|
if (!columnSizes) setUncontrolledSizes(nextSizes);
|
|
201
298
|
onColumnResize?.(nextSizes, columnIndex);
|
|
202
|
-
}, [columnSizes, onColumnResize, safeMinWidth,
|
|
203
|
-
(0,
|
|
299
|
+
}, [columnSizes, onColumnResize, safeMinWidth, sizes2]);
|
|
300
|
+
(0, import_react3.useEffect)(() => {
|
|
204
301
|
const onPointerMove = (event) => {
|
|
205
302
|
const activeResize = resizeState.current;
|
|
206
303
|
if (!activeResize) return;
|
|
@@ -219,84 +316,106 @@ function DataTable({
|
|
|
219
316
|
window.removeEventListener("pointercancel", stopResizing);
|
|
220
317
|
};
|
|
221
318
|
}, [updateColumnSize]);
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
"
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
319
|
+
const changePage = (nextPage) => {
|
|
320
|
+
if (page === void 0) setUncontrolledPage(nextPage);
|
|
321
|
+
if (nextPage !== currentPage) onPageChange?.(nextPage);
|
|
322
|
+
};
|
|
323
|
+
const resolvedPaginationPosition = paginationPosition === "middle-bottom" ? "bottom-center" : paginationPosition;
|
|
324
|
+
const paginationControl = shouldPaginate && totalPages > 1 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: `fe-table__pagination fe-table__pagination--${resolvedPaginationPosition}`, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Pagination, { page: currentPage, totalPages, onPageChange: changePage }) }) : null;
|
|
325
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "fe-table", "data-resizing": isResizing || void 0, children: [
|
|
326
|
+
resolvedPaginationPosition === "top-right" && paginationControl,
|
|
327
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("table", { className: ["fe-table__table", className].filter(Boolean).join(" "), "data-fe-table": true, "data-striped": striped || void 0, ...props, children: [
|
|
328
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("colgroup", { children: sizes2.map((size, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("col", { style: { width: `${size}px` } }, index)) }),
|
|
329
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("tr", { children: Array.from({ length: columnCount }, (_, columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("th", { scope: "col", children: [
|
|
330
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "fe-table__header-content", children: headers[columnIndex] ?? `Column ${columnIndex + 1}` }),
|
|
331
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
332
|
+
"span",
|
|
333
|
+
{
|
|
334
|
+
className: "fe-table__resize-handle",
|
|
335
|
+
role: "separator",
|
|
336
|
+
"aria-label": `Resize ${getText(headers[columnIndex]) || `column ${columnIndex + 1}`}`,
|
|
337
|
+
"aria-orientation": "vertical",
|
|
338
|
+
"aria-valuemin": safeMinWidth,
|
|
339
|
+
"aria-valuemax": MAX_COLUMN_WIDTH,
|
|
340
|
+
"aria-valuenow": sizes2[columnIndex] ?? safeMinWidth,
|
|
341
|
+
tabIndex: 0,
|
|
342
|
+
onPointerDown: (event) => {
|
|
343
|
+
event.preventDefault();
|
|
344
|
+
resizeState.current = { columnIndex, startX: event.clientX, startWidth: sizes2[columnIndex] ?? safeMinWidth };
|
|
345
|
+
setIsResizing(true);
|
|
346
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
347
|
+
},
|
|
348
|
+
onKeyDown: (event) => {
|
|
349
|
+
if (event.key === "ArrowLeft") updateColumnSize(columnIndex, (sizes2[columnIndex] ?? safeMinWidth) - 16);
|
|
350
|
+
if (event.key === "ArrowRight") updateColumnSize(columnIndex, (sizes2[columnIndex] ?? safeMinWidth) + 16);
|
|
351
|
+
}
|
|
246
352
|
}
|
|
247
|
-
|
|
248
|
-
)
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
353
|
+
)
|
|
354
|
+
] }, columnIndex)) }) }),
|
|
355
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("tbody", { children: pagedData.map((row, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("tr", { children: Array.from({ length: columnCount }, (_, columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("td", { children: row[columnIndex] }, columnIndex)) }, shouldPaginate ? (currentPage - 1) * safePageSize + rowIndex : rowIndex)) })
|
|
356
|
+
] }),
|
|
357
|
+
resolvedPaginationPosition !== "top-right" && paginationControl
|
|
358
|
+
] });
|
|
252
359
|
}
|
|
253
|
-
function Table({
|
|
254
|
-
|
|
255
|
-
|
|
360
|
+
function Table({
|
|
361
|
+
headers,
|
|
362
|
+
data,
|
|
363
|
+
striped,
|
|
364
|
+
children,
|
|
365
|
+
pagination,
|
|
366
|
+
pageSize,
|
|
367
|
+
page,
|
|
368
|
+
defaultPage,
|
|
369
|
+
onPageChange,
|
|
370
|
+
paginationPosition,
|
|
371
|
+
...props
|
|
372
|
+
}) {
|
|
373
|
+
if (headers || data) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DataTable, { headers: headers ?? [], data: data ?? [], striped: striped ?? true, pagination, pageSize, page, defaultPage, onPageChange, paginationPosition, ...props });
|
|
374
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TableContext.Provider, { value: { striped: striped ?? false }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("table", { "data-fe-table": true, "data-striped": striped || void 0, ...props, children }) });
|
|
256
375
|
}
|
|
257
376
|
function TableHead(props) {
|
|
258
|
-
return /* @__PURE__ */ (0,
|
|
377
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("thead", { ...props });
|
|
259
378
|
}
|
|
260
379
|
function TableBody(props) {
|
|
261
|
-
return /* @__PURE__ */ (0,
|
|
380
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("tbody", { ...props });
|
|
262
381
|
}
|
|
263
382
|
function TableRow({ children, ...props }) {
|
|
264
|
-
const { striped } = (0,
|
|
265
|
-
return /* @__PURE__ */ (0,
|
|
383
|
+
const { striped } = (0, import_react3.useContext)(TableContext);
|
|
384
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("tr", { "data-striped": striped || void 0, ...props, children });
|
|
266
385
|
}
|
|
267
386
|
function TableCell({ children, ...props }) {
|
|
268
|
-
return /* @__PURE__ */ (0,
|
|
387
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("td", { ...props, children });
|
|
269
388
|
}
|
|
270
389
|
function TableHeader({ children, ...props }) {
|
|
271
|
-
return /* @__PURE__ */ (0,
|
|
390
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("th", { scope: "col", ...props, children });
|
|
272
391
|
}
|
|
273
392
|
function TableCaption(props) {
|
|
274
|
-
return /* @__PURE__ */ (0,
|
|
393
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("caption", { ...props });
|
|
275
394
|
}
|
|
276
395
|
|
|
277
396
|
// packages/toggle/src/index.tsx
|
|
278
|
-
var
|
|
279
|
-
var
|
|
280
|
-
var Toggle = (0,
|
|
397
|
+
var import_react4 = require("react");
|
|
398
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
399
|
+
var Toggle = (0, import_react4.forwardRef)(function Toggle2({ color = "#16a34a", label, className, style, id, ...props }, ref) {
|
|
281
400
|
const classes = ["fe-toggle", className].filter(Boolean).join(" ");
|
|
282
401
|
const toggleStyle = {
|
|
283
402
|
"--fe-toggle-color": color,
|
|
284
403
|
...style
|
|
285
404
|
};
|
|
286
|
-
return /* @__PURE__ */ (0,
|
|
287
|
-
/* @__PURE__ */ (0,
|
|
288
|
-
/* @__PURE__ */ (0,
|
|
289
|
-
label && /* @__PURE__ */ (0,
|
|
405
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: classes, style: toggleStyle, children: [
|
|
406
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { ref, id, className: "fe-toggle__input", type: "checkbox", role: "switch", ...props }),
|
|
407
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "fe-toggle__control", "aria-hidden": "true" }),
|
|
408
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "fe-toggle__label", children: label })
|
|
290
409
|
] });
|
|
291
410
|
});
|
|
292
411
|
Toggle.displayName = "Toggle";
|
|
293
412
|
|
|
294
413
|
// packages/drawer/src/index.tsx
|
|
295
|
-
var
|
|
414
|
+
var import_react5 = require("react");
|
|
296
415
|
var import_react_dom = require("react-dom");
|
|
297
|
-
var
|
|
416
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
298
417
|
function Drawer({ open, onClose, title, footer, side = "right", width = 400, fullScreen = false, children, closeOnBackdropClick = true, className, style, ...props }) {
|
|
299
|
-
(0,
|
|
418
|
+
(0, import_react5.useEffect)(() => {
|
|
300
419
|
if (!open) return;
|
|
301
420
|
const onKeyDown = (event) => {
|
|
302
421
|
if (event.key === "Escape") onClose();
|
|
@@ -306,34 +425,106 @@ function Drawer({ open, onClose, title, footer, side = "right", width = 400, ful
|
|
|
306
425
|
}, [onClose, open]);
|
|
307
426
|
if (!open || typeof document === "undefined") return null;
|
|
308
427
|
const panelStyle = !fullScreen && (side === "left" || side === "right") ? { ...style, width: typeof width === "number" ? `${width}px` : width } : style;
|
|
309
|
-
return (0, import_react_dom.createPortal)(/* @__PURE__ */ (0,
|
|
428
|
+
return (0, import_react_dom.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "fe-drawer-backdrop", role: "presentation", onMouseDown: (event) => {
|
|
310
429
|
if (event.target === event.currentTarget && closeOnBackdropClick) onClose();
|
|
311
|
-
}, children: /* @__PURE__ */ (0,
|
|
312
|
-
/* @__PURE__ */ (0,
|
|
313
|
-
title && /* @__PURE__ */ (0,
|
|
314
|
-
/* @__PURE__ */ (0,
|
|
430
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("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: [
|
|
431
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("header", { className: "fe-drawer__header", children: [
|
|
432
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { children: title }),
|
|
433
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", "aria-label": "Close drawer", onClick: onClose, children: "\xD7" })
|
|
315
434
|
] }),
|
|
316
|
-
/* @__PURE__ */ (0,
|
|
317
|
-
footer && /* @__PURE__ */ (0,
|
|
435
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "fe-drawer__body", children }),
|
|
436
|
+
footer && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("footer", { className: "fe-drawer__footer", children: footer })
|
|
318
437
|
] }) }), document.body);
|
|
319
438
|
}
|
|
320
439
|
|
|
321
440
|
// packages/form-controls/src/index.tsx
|
|
322
|
-
var
|
|
323
|
-
var
|
|
324
|
-
|
|
325
|
-
|
|
441
|
+
var import_react6 = require("react");
|
|
442
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
443
|
+
function getFieldError(error, errorMessage) {
|
|
444
|
+
if (errorMessage !== void 0 && errorMessage !== null) return errorMessage;
|
|
445
|
+
if (typeof error !== "boolean") return error;
|
|
446
|
+
return error ? "Invalid value" : void 0;
|
|
447
|
+
}
|
|
448
|
+
function getDescribedBy(existing, messageId2) {
|
|
449
|
+
return [existing, messageId2].filter(Boolean).join(" ") || void 0;
|
|
450
|
+
}
|
|
451
|
+
var TextInput = (0, import_react6.forwardRef)(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) {
|
|
452
|
+
const generatedId = (0, import_react6.useId)();
|
|
453
|
+
const inputId = id ?? `${generatedId}-input`;
|
|
454
|
+
const labelId = `${generatedId}-label`;
|
|
455
|
+
const messageId2 = `${generatedId}-message`;
|
|
456
|
+
const controlled = value !== void 0;
|
|
457
|
+
const [internalValue, setInternalValue] = (0, import_react6.useState)(defaultValue);
|
|
458
|
+
const currentValue = controlled ? value : internalValue;
|
|
459
|
+
const fieldError = getFieldError(error, errorMessage);
|
|
460
|
+
const hasError = fieldError !== void 0 && fieldError !== false && fieldError !== null;
|
|
461
|
+
const displayedMessage = hasError ? fieldError : helperText;
|
|
462
|
+
const describedBy = getDescribedBy(ariaDescribedBy, displayedMessage ? messageId2 : void 0);
|
|
463
|
+
const clear = () => {
|
|
464
|
+
if (!controlled) setInternalValue("");
|
|
465
|
+
onValueChange?.("");
|
|
466
|
+
onClear?.();
|
|
467
|
+
};
|
|
468
|
+
const labelledBy = getDescribedBy(ariaLabelledBy, label ? labelId : void 0);
|
|
469
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: ["fe-text-input", hasError && "fe-text-input--error", className].filter(Boolean).join(" "), children: [
|
|
470
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { id: labelId, className: "fe-text-input__label", children: label }),
|
|
471
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "fe-text-input__control", children: [
|
|
472
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { ref, id: inputId, value: currentValue, disabled, readOnly, "aria-invalid": hasError || void 0, "aria-labelledby": labelledBy, "aria-describedby": describedBy, onChange: (event) => {
|
|
473
|
+
if (!controlled) setInternalValue(event.target.value);
|
|
474
|
+
onValueChange?.(event.target.value);
|
|
475
|
+
onChange?.(event);
|
|
476
|
+
}, ...props }),
|
|
477
|
+
clearable && currentValue && !disabled && !readOnly && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Button, { hierarchy: "tertiary-gray", size: "24", iconOnly: true, icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CloseIcon, { size: 14 }), "aria-label": clearLabel, onClick: clear, className: "fe-text-input__clear" })
|
|
478
|
+
] }),
|
|
479
|
+
displayedMessage && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { id: messageId2, className: hasError ? "fe-text-input__error" : "fe-text-input__helper", children: displayedMessage })
|
|
480
|
+
] });
|
|
481
|
+
});
|
|
482
|
+
TextInput.displayName = "TextInput";
|
|
483
|
+
var TextArea = (0, import_react6.forwardRef)(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) {
|
|
484
|
+
const generatedId = (0, import_react6.useId)();
|
|
485
|
+
const inputId = id ?? `${generatedId}-input`;
|
|
486
|
+
const labelId = `${generatedId}-label`;
|
|
487
|
+
const messageId2 = `${generatedId}-message`;
|
|
488
|
+
const controlled = value !== void 0;
|
|
489
|
+
const [internalValue, setInternalValue] = (0, import_react6.useState)(defaultValue);
|
|
490
|
+
const currentValue = controlled ? value : internalValue;
|
|
491
|
+
const fieldError = getFieldError(error, errorMessage);
|
|
492
|
+
const hasError = fieldError !== void 0 && fieldError !== false && fieldError !== null;
|
|
493
|
+
const displayedMessage = hasError ? fieldError : helperText;
|
|
494
|
+
const describedBy = getDescribedBy(ariaDescribedBy, displayedMessage ? messageId2 : void 0);
|
|
495
|
+
const clear = () => {
|
|
496
|
+
if (!controlled) setInternalValue("");
|
|
497
|
+
onValueChange?.("");
|
|
498
|
+
onClear?.();
|
|
499
|
+
};
|
|
500
|
+
const labelledBy = getDescribedBy(ariaLabelledBy, label ? labelId : void 0);
|
|
501
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: ["fe-text-area", hasError && "fe-text-area--error", className].filter(Boolean).join(" "), children: [
|
|
502
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { id: labelId, className: "fe-text-area__label", children: label }),
|
|
503
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "fe-text-area__control", children: [
|
|
504
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("textarea", { ref, id: inputId, value: currentValue, disabled, readOnly, "aria-invalid": hasError || void 0, "aria-labelledby": labelledBy, "aria-describedby": describedBy, onChange: (event) => {
|
|
505
|
+
if (!controlled) setInternalValue(event.target.value);
|
|
506
|
+
onValueChange?.(event.target.value);
|
|
507
|
+
onChange?.(event);
|
|
508
|
+
}, ...props }),
|
|
509
|
+
clearable && currentValue && !disabled && !readOnly && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Button, { hierarchy: "tertiary-gray", size: "24", iconOnly: true, icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CloseIcon, { size: 14 }), "aria-label": clearLabel, onClick: clear, className: "fe-text-area__clear" })
|
|
510
|
+
] }),
|
|
511
|
+
displayedMessage && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { id: messageId2, className: hasError ? "fe-text-area__error" : "fe-text-area__helper", children: displayedMessage })
|
|
512
|
+
] });
|
|
513
|
+
});
|
|
514
|
+
TextArea.displayName = "TextArea";
|
|
515
|
+
var Selection = (0, import_react6.forwardRef)(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) {
|
|
516
|
+
const generatedId = (0, import_react6.useId)();
|
|
326
517
|
const listboxId = id ?? generatedId;
|
|
327
518
|
const isControlled = value !== void 0;
|
|
328
|
-
const [internalValue, setInternalValue] = (0,
|
|
519
|
+
const [internalValue, setInternalValue] = (0, import_react6.useState)(defaultValue ?? (multiple ? [] : ""));
|
|
329
520
|
const selectedValue = isControlled ? value : internalValue;
|
|
330
521
|
const selectedValues = Array.isArray(selectedValue) ? selectedValue : selectedValue === "" || selectedValue === null || selectedValue === void 0 ? [] : [selectedValue];
|
|
331
522
|
const selectedOptions = options.filter((option) => selectedValues.some((item) => String(item) === String(option.value)));
|
|
332
|
-
const [open, setOpen] = (0,
|
|
333
|
-
const [query, setQuery] = (0,
|
|
334
|
-
const [activeIndex, setActiveIndex] = (0,
|
|
335
|
-
const rootRef = (0,
|
|
336
|
-
(0,
|
|
523
|
+
const [open, setOpen] = (0, import_react6.useState)(false);
|
|
524
|
+
const [query, setQuery] = (0, import_react6.useState)("");
|
|
525
|
+
const [activeIndex, setActiveIndex] = (0, import_react6.useState)(0);
|
|
526
|
+
const rootRef = (0, import_react6.useRef)(null);
|
|
527
|
+
(0, import_react6.useEffect)(() => {
|
|
337
528
|
const close = (event) => {
|
|
338
529
|
if (!rootRef.current?.contains(event.target)) setOpen(false);
|
|
339
530
|
};
|
|
@@ -376,39 +567,39 @@ var Selection = (0, import_react5.forwardRef)(function Selection2({ className, l
|
|
|
376
567
|
}
|
|
377
568
|
if (event.key === "Escape") setOpen(false);
|
|
378
569
|
};
|
|
379
|
-
return /* @__PURE__ */ (0,
|
|
380
|
-
label && /* @__PURE__ */ (0,
|
|
381
|
-
/* @__PURE__ */ (0,
|
|
382
|
-
name && selectedValues.map((item) => /* @__PURE__ */ (0,
|
|
383
|
-
/* @__PURE__ */ (0,
|
|
384
|
-
/* @__PURE__ */ (0,
|
|
570
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("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: [
|
|
571
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "fe-selection__label", children: label }),
|
|
572
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { ref: rootRef, className: "fe-selection__control", children: [
|
|
573
|
+
name && selectedValues.map((item) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { type: "hidden", name: multiple ? `${name}[]` : name, value: item }, String(item))),
|
|
574
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("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: [
|
|
575
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("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__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "fe-selection__tag", children: [
|
|
385
576
|
option.label,
|
|
386
|
-
/* @__PURE__ */ (0,
|
|
387
|
-
] }, String(option.value))) : displayLabel.map((item, index) => /* @__PURE__ */ (0,
|
|
577
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "aria-hidden": "true", children: "\xD7" })
|
|
578
|
+
] }, String(option.value))) : displayLabel.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
|
|
388
579
|
item,
|
|
389
580
|
index < displayLabel.length - 1 ? ", " : ""
|
|
390
581
|
] }, index)) : placeholder }),
|
|
391
|
-
/* @__PURE__ */ (0,
|
|
582
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "fe-selection__actions", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "fe-selection__chevron", "aria-hidden": "true" }) })
|
|
392
583
|
] }),
|
|
393
|
-
clearable && selectedOptions.length > 0 && /* @__PURE__ */ (0,
|
|
394
|
-
open && /* @__PURE__ */ (0,
|
|
395
|
-
searchable && /* @__PURE__ */ (0,
|
|
396
|
-
/* @__PURE__ */ (0,
|
|
397
|
-
/* @__PURE__ */ (0,
|
|
584
|
+
clearable && selectedOptions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: "fe-selection__clear", "aria-label": "Clear selection", onClick: clear }),
|
|
585
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { id: listboxId, className: "fe-selection__menu", role: "listbox", "aria-multiselectable": multiple || void 0, children: [
|
|
586
|
+
searchable && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "fe-selection__search", children: [
|
|
587
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "aria-hidden": "true", children: "\u2315" }),
|
|
588
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { autoFocus: true, value: query, onChange: (event) => {
|
|
398
589
|
setQuery(event.target.value);
|
|
399
590
|
setActiveIndex(0);
|
|
400
591
|
}, placeholder: "Search\u2026", "aria-label": "Search options" })
|
|
401
592
|
] }),
|
|
402
|
-
/* @__PURE__ */ (0,
|
|
593
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "fe-selection__options", children: filteredOptions.length ? filteredOptions.map((option, index) => {
|
|
403
594
|
const isSelected = selectedValues.some((item) => String(item) === String(option.value));
|
|
404
|
-
return /* @__PURE__ */ (0,
|
|
405
|
-
/* @__PURE__ */ (0,
|
|
406
|
-
isSelected && /* @__PURE__ */ (0,
|
|
595
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("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: [
|
|
596
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: option.label }),
|
|
597
|
+
isSelected && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "fe-selection__check", "aria-hidden": "true", children: "\u2713" })
|
|
407
598
|
] }, String(option.value));
|
|
408
|
-
}) : /* @__PURE__ */ (0,
|
|
599
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "fe-selection__empty", children: "No matching options" }) })
|
|
409
600
|
] })
|
|
410
601
|
] }),
|
|
411
|
-
helperText && /* @__PURE__ */ (0,
|
|
602
|
+
helperText && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "fe-selection__helper", children: helperText })
|
|
412
603
|
] });
|
|
413
604
|
});
|
|
414
605
|
Selection.displayName = "Selection";
|
|
@@ -445,13 +636,19 @@ function normalizeNumberInput(raw, options) {
|
|
|
445
636
|
if (value !== numericValue) return { display: formatNumber(value, decimals, thousandSeparator, decimalSeparator), value };
|
|
446
637
|
return { display: `${negative ? "-" : ""}${groupInteger(integer || "0", thousandSeparator)}${hasDecimal ? `${decimalSeparator}${fraction}` : ""}`, value };
|
|
447
638
|
}
|
|
448
|
-
var NumberInput = (0,
|
|
639
|
+
var NumberInput = (0, import_react6.forwardRef)(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) {
|
|
640
|
+
const generatedId = (0, import_react6.useId)();
|
|
641
|
+
const messageId2 = `${generatedId}-message`;
|
|
449
642
|
const isControlled = value !== void 0;
|
|
450
|
-
const [internalValue, setInternalValue] = (0,
|
|
451
|
-
const [focused, setFocused] = (0,
|
|
643
|
+
const [internalValue, setInternalValue] = (0, import_react6.useState)(defaultValue);
|
|
644
|
+
const [focused, setFocused] = (0, import_react6.useState)(false);
|
|
452
645
|
const actualValue = isControlled ? value ?? null : internalValue;
|
|
453
|
-
const [text, setText] = (0,
|
|
454
|
-
(
|
|
646
|
+
const [text, setText] = (0, import_react6.useState)(actualValue === null ? "" : formatNumber(actualValue, decimals, thousandSeparator, decimalSeparator));
|
|
647
|
+
const fieldError = getFieldError(error, errorMessage);
|
|
648
|
+
const hasError = fieldError !== void 0 && fieldError !== false && fieldError !== null;
|
|
649
|
+
const displayedMessage = hasError ? fieldError : helperText;
|
|
650
|
+
const describedBy = getDescribedBy(ariaDescribedBy, displayedMessage ? messageId2 : void 0);
|
|
651
|
+
(0, import_react6.useEffect)(() => {
|
|
455
652
|
if (!focused) setText(actualValue === null ? "" : formatNumber(actualValue, decimals, thousandSeparator, decimalSeparator));
|
|
456
653
|
}, [actualValue, decimalSeparator, decimals, focused, thousandSeparator]);
|
|
457
654
|
const updateValue = (nextText) => {
|
|
@@ -461,32 +658,32 @@ var NumberInput = (0, import_react5.forwardRef)(function NumberInput2({ value, d
|
|
|
461
658
|
if (!isControlled) setInternalValue(nextValue);
|
|
462
659
|
onValueChange?.(nextValue);
|
|
463
660
|
};
|
|
464
|
-
return /* @__PURE__ */ (0,
|
|
465
|
-
label && /* @__PURE__ */ (0,
|
|
466
|
-
/* @__PURE__ */ (0,
|
|
661
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: ["fe-number-input", hasError && "fe-number-input--error", className].filter(Boolean).join(" "), children: [
|
|
662
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "fe-number-input__label", children: label }),
|
|
663
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { ref, inputMode: allowDecimal ? "decimal" : "numeric", value: text, onFocus: (event) => {
|
|
467
664
|
setFocused(true);
|
|
468
665
|
onFocus?.(event);
|
|
469
666
|
}, onChange: (event) => updateValue(event.target.value), onBlur: (event) => {
|
|
470
667
|
setFocused(false);
|
|
471
668
|
onBlur?.(event);
|
|
472
|
-
}, ...props }),
|
|
473
|
-
|
|
669
|
+
}, ...props, "aria-invalid": hasError || void 0, "aria-describedby": describedBy }),
|
|
670
|
+
displayedMessage && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { id: messageId2, className: hasError ? "fe-number-input__error" : "fe-number-input__helper", children: displayedMessage })
|
|
474
671
|
] });
|
|
475
672
|
});
|
|
476
673
|
NumberInput.displayName = "NumberInput";
|
|
477
674
|
function CurrencyInput({ suffix = "VND", currencies, currency, defaultCurrency, onCurrencyChange, className, ...props }) {
|
|
478
|
-
const [internalCurrency, setInternalCurrency] = (0,
|
|
675
|
+
const [internalCurrency, setInternalCurrency] = (0, import_react6.useState)(defaultCurrency ?? currencies?.[0]?.code ?? "");
|
|
479
676
|
const selectedCurrency = currency ?? internalCurrency;
|
|
480
677
|
const current = currencies?.find((item) => item.code === selectedCurrency);
|
|
481
678
|
const currencySuffix = current?.suffix ?? current?.code ?? suffix;
|
|
482
|
-
return /* @__PURE__ */ (0,
|
|
483
|
-
/* @__PURE__ */ (0,
|
|
484
|
-
currencies?.length ? /* @__PURE__ */ (0,
|
|
679
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: ["fe-currency-input", className].filter(Boolean).join(" "), children: [
|
|
680
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(NumberInput, { ...props, className: "fe-currency-input__number" }),
|
|
681
|
+
currencies?.length ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("select", { className: "fe-currency-input__currency", "aria-label": "Currency", value: selectedCurrency, onChange: (event) => {
|
|
485
682
|
const next = currencies.find((item) => item.code === event.target.value);
|
|
486
683
|
if (!next) return;
|
|
487
684
|
if (currency === void 0) setInternalCurrency(next.code);
|
|
488
685
|
onCurrencyChange?.(next);
|
|
489
|
-
}, children: currencies.map((item) => /* @__PURE__ */ (0,
|
|
686
|
+
}, children: currencies.map((item) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: item.code, children: item.label ?? item.code }, item.code)) }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "fe-currency-input__suffix", children: currencySuffix })
|
|
490
687
|
] });
|
|
491
688
|
}
|
|
492
689
|
var pad = (value) => String(value).padStart(2, "0");
|
|
@@ -509,15 +706,15 @@ function DateTimePicker(props) {
|
|
|
509
706
|
const { label, format = "dd/MM/yyyy HH:mm", disabled, placeholder, locale = "en-US", className, mode = "single" } = props;
|
|
510
707
|
const isRange = mode === "range";
|
|
511
708
|
const controlled = props.value !== void 0;
|
|
512
|
-
const [singleInternal, setSingleInternal] = (0,
|
|
513
|
-
const [rangeInternal, setRangeInternal] = (0,
|
|
709
|
+
const [singleInternal, setSingleInternal] = (0, import_react6.useState)((!isRange ? props.defaultValue : null) ?? null);
|
|
710
|
+
const [rangeInternal, setRangeInternal] = (0, import_react6.useState)((isRange ? props.defaultValue : void 0) ?? [null, null]);
|
|
514
711
|
const singleValue = !isRange ? props.value ?? singleInternal : null;
|
|
515
712
|
const rangeValue = isRange ? props.value ?? rangeInternal : [null, null];
|
|
516
|
-
const [open, setOpen] = (0,
|
|
517
|
-
const [month, setMonth] = (0,
|
|
518
|
-
const [editingEnd, setEditingEnd] = (0,
|
|
519
|
-
const rootRef = (0,
|
|
520
|
-
(0,
|
|
713
|
+
const [open, setOpen] = (0, import_react6.useState)(false);
|
|
714
|
+
const [month, setMonth] = (0, import_react6.useState)(() => new Date((isRange ? rangeValue[0] : singleValue) ?? /* @__PURE__ */ new Date()));
|
|
715
|
+
const [editingEnd, setEditingEnd] = (0, import_react6.useState)(false);
|
|
716
|
+
const rootRef = (0, import_react6.useRef)(null);
|
|
717
|
+
(0, import_react6.useEffect)(() => {
|
|
521
718
|
const onPointerDown = (event) => {
|
|
522
719
|
if (!rootRef.current?.contains(event.target)) setOpen(false);
|
|
523
720
|
};
|
|
@@ -559,44 +756,44 @@ function DateTimePicker(props) {
|
|
|
559
756
|
if (isRange) setRange(editingEnd ? [rangeValue[0], next] : [next, rangeValue[1]]);
|
|
560
757
|
else setSingle(next);
|
|
561
758
|
};
|
|
562
|
-
return /* @__PURE__ */ (0,
|
|
563
|
-
label && /* @__PURE__ */ (0,
|
|
564
|
-
/* @__PURE__ */ (0,
|
|
565
|
-
/* @__PURE__ */ (0,
|
|
566
|
-
/* @__PURE__ */ (0,
|
|
759
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { ref: rootRef, className: ["fe-datetime-picker", className].filter(Boolean).join(" "), children: [
|
|
760
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "fe-datetime-picker__label", children: label }),
|
|
761
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("button", { type: "button", className: "fe-datetime-picker__trigger", disabled, "aria-expanded": open, onClick: () => setOpen((current) => !current), children: [
|
|
762
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "aria-hidden": "true", children: "\u25F7" }),
|
|
763
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: shownValue || placeholder || (isRange ? "Select date range" : "Select date and time") })
|
|
567
764
|
] }),
|
|
568
|
-
open && /* @__PURE__ */ (0,
|
|
569
|
-
/* @__PURE__ */ (0,
|
|
570
|
-
/* @__PURE__ */ (0,
|
|
571
|
-
/* @__PURE__ */ (0,
|
|
572
|
-
/* @__PURE__ */ (0,
|
|
765
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "fe-datetime-picker__popper", role: "dialog", "aria-label": "Date and time picker", children: [
|
|
766
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "fe-datetime-picker__month", children: [
|
|
767
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", "aria-label": "Previous month", onClick: () => setMonth((current) => new Date(current.getFullYear(), current.getMonth() - 1, 1)), children: "\u2039" }),
|
|
768
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("strong", { children: month.toLocaleDateString(locale, { month: "long", year: "numeric" }) }),
|
|
769
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", "aria-label": "Next month", onClick: () => setMonth((current) => new Date(current.getFullYear(), current.getMonth() + 1, 1)), children: "\u203A" })
|
|
573
770
|
] }),
|
|
574
|
-
/* @__PURE__ */ (0,
|
|
575
|
-
/* @__PURE__ */ (0,
|
|
771
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "fe-datetime-picker__weekdays", children: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"].map((day) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: day }, day)) }),
|
|
772
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "fe-datetime-picker__days", children: days.map((day) => {
|
|
576
773
|
const inMonth = day.getMonth() === month.getMonth();
|
|
577
774
|
const selected = isRange ? sameDay(day, rangeValue[0]) || sameDay(day, rangeValue[1]) : sameDay(day, singleValue);
|
|
578
775
|
const inRange = isRange && rangeValue[0] && rangeValue[1] && day > startOfDay(rangeValue[0]) && day < startOfDay(rangeValue[1]);
|
|
579
|
-
return /* @__PURE__ */ (0,
|
|
776
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("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());
|
|
580
777
|
}) }),
|
|
581
|
-
isRange && /* @__PURE__ */ (0,
|
|
582
|
-
/* @__PURE__ */ (0,
|
|
583
|
-
/* @__PURE__ */ (0,
|
|
778
|
+
isRange && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "fe-datetime-picker__range-tabs", children: [
|
|
779
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: !editingEnd ? "is-active" : "", onClick: () => setEditingEnd(false), children: "Start" }),
|
|
780
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: editingEnd ? "is-active" : "", onClick: () => setEditingEnd(true), children: "End" })
|
|
584
781
|
] }),
|
|
585
|
-
/* @__PURE__ */ (0,
|
|
782
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "fe-datetime-picker__time", children: [
|
|
586
783
|
"Time",
|
|
587
|
-
/* @__PURE__ */ (0,
|
|
784
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { type: "time", value: selectedForTime ? `${pad(selectedForTime.getHours())}:${pad(selectedForTime.getMinutes())}` : "00:00", onChange: (event) => setTime(event.target.value), disabled: !selectedForTime })
|
|
588
785
|
] })
|
|
589
786
|
] })
|
|
590
787
|
] });
|
|
591
788
|
}
|
|
592
789
|
|
|
593
790
|
// packages/tooltip/src/index.tsx
|
|
594
|
-
var
|
|
595
|
-
var
|
|
791
|
+
var import_react7 = require("react");
|
|
792
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
596
793
|
function Tooltip({ content, children, placement = "top", disabled, className, ...props }) {
|
|
597
|
-
const [visible, setVisible] = (0,
|
|
598
|
-
const id = (0,
|
|
599
|
-
const trigger = (0,
|
|
794
|
+
const [visible, setVisible] = (0, import_react7.useState)(false);
|
|
795
|
+
const id = (0, import_react7.useId)();
|
|
796
|
+
const trigger = (0, import_react7.cloneElement)(children, { "aria-describedby": visible ? id : void 0, onMouseEnter: (event) => {
|
|
600
797
|
children.props.onMouseEnter?.(event);
|
|
601
798
|
setVisible(true);
|
|
602
799
|
}, onMouseLeave: (event) => {
|
|
@@ -609,46 +806,324 @@ function Tooltip({ content, children, placement = "top", disabled, className, ..
|
|
|
609
806
|
children.props.onBlur?.(event);
|
|
610
807
|
setVisible(false);
|
|
611
808
|
} });
|
|
612
|
-
return /* @__PURE__ */ (0,
|
|
809
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: ["fe-tooltip", `fe-tooltip--${placement}`, className].filter(Boolean).join(" "), ...props, children: [
|
|
613
810
|
trigger,
|
|
614
|
-
visible && !disabled && /* @__PURE__ */ (0,
|
|
811
|
+
visible && !disabled && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { id, role: "tooltip", className: "fe-tooltip__content", children: content })
|
|
615
812
|
] });
|
|
616
813
|
}
|
|
617
814
|
|
|
618
815
|
// packages/expandable-section/src/index.tsx
|
|
619
|
-
var
|
|
620
|
-
var
|
|
816
|
+
var import_react8 = require("react");
|
|
817
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
621
818
|
function ExpandableSection({ title, children, expanded, defaultExpanded = false, onExpandedChange, disabled, className, ...props }) {
|
|
622
|
-
const [internalExpanded, setInternalExpanded] = (0,
|
|
819
|
+
const [internalExpanded, setInternalExpanded] = (0, import_react8.useState)(defaultExpanded);
|
|
623
820
|
const isExpanded = expanded ?? internalExpanded;
|
|
624
|
-
const id = (0,
|
|
821
|
+
const id = (0, import_react8.useId)();
|
|
625
822
|
const toggle = () => {
|
|
626
823
|
if (disabled) return;
|
|
627
824
|
const next = !isExpanded;
|
|
628
825
|
if (expanded === void 0) setInternalExpanded(next);
|
|
629
826
|
onExpandedChange?.(next);
|
|
630
827
|
};
|
|
631
|
-
return /* @__PURE__ */ (0,
|
|
632
|
-
/* @__PURE__ */ (0,
|
|
633
|
-
/* @__PURE__ */ (0,
|
|
634
|
-
/* @__PURE__ */ (0,
|
|
828
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("section", { className: ["fe-expandable-section", isExpanded && "fe-expandable-section--expanded", disabled && "fe-expandable-section--disabled", className].filter(Boolean).join(" "), ...props, children: [
|
|
829
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("button", { className: "fe-expandable-section__trigger", type: "button", "aria-expanded": isExpanded, "aria-controls": id, disabled, onClick: toggle, children: [
|
|
830
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: title }),
|
|
831
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "fe-expandable-section__chevron", "aria-hidden": "true" })
|
|
832
|
+
] }),
|
|
833
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { id, className: "fe-expandable-section__content", "aria-hidden": !isExpanded, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "fe-expandable-section__content-inner", children }) })
|
|
834
|
+
] });
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
// packages/loading/src/index.tsx
|
|
838
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
839
|
+
var sizes = {
|
|
840
|
+
small: "16px",
|
|
841
|
+
medium: "24px",
|
|
842
|
+
large: "40px"
|
|
843
|
+
};
|
|
844
|
+
function Loading({ size = "medium", color = "#2878f0", label, className, style, ...props }) {
|
|
845
|
+
const diameter = typeof size === "number" ? `${size}px` : sizes[size];
|
|
846
|
+
const loadingStyle = {
|
|
847
|
+
"--fe-loading-size": diameter,
|
|
848
|
+
"--fe-loading-color": color,
|
|
849
|
+
...style
|
|
850
|
+
};
|
|
851
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: ["fe-loading", className].filter(Boolean).join(" "), style: loadingStyle, role: "status", ...props, children: [
|
|
852
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "fe-loading__spinner", "aria-hidden": "true" }),
|
|
853
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "fe-loading__label", children: label }),
|
|
854
|
+
!label && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "fe-loading__sr-only", children: "Loading" })
|
|
855
|
+
] });
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
// packages/skeleton/src/index.tsx
|
|
859
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
860
|
+
var pixels = (value) => typeof value === "number" ? `${value}px` : value;
|
|
861
|
+
function SkeletonBase({ variant = "box", shape, width, height, count = 1, animated = true, className, style, ...props }) {
|
|
862
|
+
const resolvedVariant = shape ?? variant;
|
|
863
|
+
const resolvedWidth = pixels(width) ?? (resolvedVariant === "circle" ? "40px" : "100%");
|
|
864
|
+
const resolvedHeight = pixels(height) ?? (resolvedVariant === "circle" ? resolvedWidth : resolvedVariant === "line" ? "12px" : "80px");
|
|
865
|
+
const skeletonStyle = {
|
|
866
|
+
"--fe-skeleton-width": resolvedWidth,
|
|
867
|
+
"--fe-skeleton-height": resolvedHeight,
|
|
868
|
+
...style
|
|
869
|
+
};
|
|
870
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, { children: Array.from({ length: Math.max(1, count) }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
871
|
+
"div",
|
|
872
|
+
{
|
|
873
|
+
className: ["fe-skeleton", `fe-skeleton--${resolvedVariant}`, animated && "fe-skeleton--animated", className].filter(Boolean).join(" "),
|
|
874
|
+
style: skeletonStyle,
|
|
875
|
+
"aria-hidden": "true",
|
|
876
|
+
...props
|
|
877
|
+
},
|
|
878
|
+
index
|
|
879
|
+
)) });
|
|
880
|
+
}
|
|
881
|
+
function SkeletonCircle({ size = 40, ...props }) {
|
|
882
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SkeletonBase, { variant: "circle", width: size, height: size, ...props });
|
|
883
|
+
}
|
|
884
|
+
function SkeletonSquare({ size = 80, ...props }) {
|
|
885
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SkeletonBase, { variant: "box", width: size, height: size, ...props });
|
|
886
|
+
}
|
|
887
|
+
function SkeletonBox({ width = "100%", height = 80, ...props }) {
|
|
888
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SkeletonBase, { variant: "box", width, height, ...props });
|
|
889
|
+
}
|
|
890
|
+
function SkeletonLine({ width = "100%", height = 12, ...props }) {
|
|
891
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SkeletonBase, { variant: "line", width, height, ...props });
|
|
892
|
+
}
|
|
893
|
+
var Skeleton = Object.assign(SkeletonBase, {
|
|
894
|
+
Circle: SkeletonCircle,
|
|
895
|
+
Square: SkeletonSquare,
|
|
896
|
+
Box: SkeletonBox,
|
|
897
|
+
Line: SkeletonLine
|
|
898
|
+
});
|
|
899
|
+
|
|
900
|
+
// packages/modal/src/index.tsx
|
|
901
|
+
var import_react9 = require("react");
|
|
902
|
+
var import_react_dom2 = require("react-dom");
|
|
903
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
904
|
+
function Modal({
|
|
905
|
+
open,
|
|
906
|
+
onClose,
|
|
907
|
+
title,
|
|
908
|
+
description,
|
|
909
|
+
children,
|
|
910
|
+
footer,
|
|
911
|
+
actions = [],
|
|
912
|
+
size = "medium",
|
|
913
|
+
closeOnBackdropClick = true,
|
|
914
|
+
closeButton = true,
|
|
915
|
+
closeLabel = "Close modal",
|
|
916
|
+
className,
|
|
917
|
+
...props
|
|
918
|
+
}) {
|
|
919
|
+
const titleId = (0, import_react9.useId)();
|
|
920
|
+
const panelRef = (0, import_react9.useRef)(null);
|
|
921
|
+
(0, import_react9.useEffect)(() => {
|
|
922
|
+
if (!open) return;
|
|
923
|
+
const onKeyDown = (event) => {
|
|
924
|
+
if (event.key === "Escape") onClose();
|
|
925
|
+
};
|
|
926
|
+
document.addEventListener("keydown", onKeyDown);
|
|
927
|
+
panelRef.current?.focus();
|
|
928
|
+
return () => document.removeEventListener("keydown", onKeyDown);
|
|
929
|
+
}, [onClose, open]);
|
|
930
|
+
if (!open || typeof document === "undefined") return null;
|
|
931
|
+
const hasFooter = footer || actions.length > 0;
|
|
932
|
+
return (0, import_react_dom2.createPortal)(
|
|
933
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "fe-modal-backdrop", role: "presentation", onMouseDown: (event) => {
|
|
934
|
+
if (event.target === event.currentTarget && closeOnBackdropClick) onClose();
|
|
935
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
936
|
+
"div",
|
|
937
|
+
{
|
|
938
|
+
ref: panelRef,
|
|
939
|
+
className: ["fe-modal", `fe-modal--${size}`, className].filter(Boolean).join(" "),
|
|
940
|
+
role: "dialog",
|
|
941
|
+
"aria-modal": "true",
|
|
942
|
+
"aria-labelledby": title ? titleId : void 0,
|
|
943
|
+
"aria-label": title ? void 0 : "Modal",
|
|
944
|
+
tabIndex: -1,
|
|
945
|
+
...props,
|
|
946
|
+
children: [
|
|
947
|
+
(title || description || closeButton) && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("header", { className: "fe-modal__header", children: [
|
|
948
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "fe-modal__heading", children: [
|
|
949
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h2", { id: titleId, children: title }),
|
|
950
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { children: description })
|
|
951
|
+
] }),
|
|
952
|
+
closeButton && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Button, { hierarchy: "tertiary-gray", size: "32", iconOnly: true, icon: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CloseIcon, {}), "aria-label": closeLabel, onClick: onClose })
|
|
953
|
+
] }),
|
|
954
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "fe-modal__body", children }),
|
|
955
|
+
hasFooter && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("footer", { className: "fe-modal__footer", children: [
|
|
956
|
+
footer && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "fe-modal__footer-content", children: footer }),
|
|
957
|
+
actions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "fe-modal__actions", children: actions.map(({ label, ...action }, index) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Button, { ...action, children: label }, index)) })
|
|
958
|
+
] })
|
|
959
|
+
]
|
|
960
|
+
}
|
|
961
|
+
) }),
|
|
962
|
+
document.body
|
|
963
|
+
);
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
// packages/progress/src/index.tsx
|
|
967
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
968
|
+
function ProgressBar({ value, max = 100, label, showValue = true, size = "medium", color = "#2878f0", className, style, "aria-label": ariaLabel, ...props }) {
|
|
969
|
+
const indeterminate = value === null || value === void 0;
|
|
970
|
+
const percentage = indeterminate ? 0 : Math.min(100, Math.max(0, Number(value) / Math.max(1, max) * 100));
|
|
971
|
+
const progressStyle = {
|
|
972
|
+
"--fe-progress-value": `${percentage}%`,
|
|
973
|
+
"--fe-progress-color": color,
|
|
974
|
+
...style
|
|
975
|
+
};
|
|
976
|
+
const visibleValue = `${Math.round(percentage)}%`;
|
|
977
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: ["fe-progress", `fe-progress--${size}`, indeterminate && "fe-progress--indeterminate", className].filter(Boolean).join(" "), style: progressStyle, ...props, children: [
|
|
978
|
+
(label || !indeterminate && showValue) && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "fe-progress__meta", children: [
|
|
979
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "fe-progress__label", children: label }),
|
|
980
|
+
!indeterminate && showValue && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("output", { className: "fe-progress__value", children: visibleValue })
|
|
635
981
|
] }),
|
|
636
|
-
/* @__PURE__ */ (0,
|
|
982
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("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__ */ (0, import_jsx_runtime13.jsx)("span", { className: "fe-progress__indicator" }) })
|
|
637
983
|
] });
|
|
638
984
|
}
|
|
985
|
+
|
|
986
|
+
// packages/chip/src/index.tsx
|
|
987
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
988
|
+
var statuses = ["default", "info", "success", "warning", "error", "neutral", "pending", "processing"];
|
|
989
|
+
function Chip({ children, status = "default", color, variant = "subtle", dot = false, onRemove, removeLabel = "Remove", className, style, ...props }) {
|
|
990
|
+
const usesCustomColor = Boolean(color);
|
|
991
|
+
const chipStyle = {
|
|
992
|
+
...usesCustomColor ? { "--fe-chip-custom-color": color } : {},
|
|
993
|
+
...style
|
|
994
|
+
};
|
|
995
|
+
const resolvedStatus = statuses.includes(status) ? status : "default";
|
|
996
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: ["fe-chip", `fe-chip--${variant}`, `fe-chip--${usesCustomColor ? "custom" : resolvedStatus}`, className].filter(Boolean).join(" "), style: chipStyle, ...props, children: [
|
|
997
|
+
dot && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "fe-chip__dot", "aria-hidden": "true" }),
|
|
998
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "fe-chip__content", children }),
|
|
999
|
+
onRemove && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Button, { hierarchy: "tertiary-gray", size: "24", iconOnly: true, icon: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(CloseIcon, { size: 14 }), "aria-label": removeLabel, onClick: onRemove, className: "fe-chip__remove" })
|
|
1000
|
+
] });
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
// packages/message/src/index.tsx
|
|
1004
|
+
var import_react10 = require("react");
|
|
1005
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1006
|
+
var messageId = 0;
|
|
1007
|
+
var entries = [];
|
|
1008
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
1009
|
+
var timers = /* @__PURE__ */ new Map();
|
|
1010
|
+
var publish = () => listeners.forEach((listener) => listener(entries));
|
|
1011
|
+
function dismiss(id) {
|
|
1012
|
+
const timer = timers.get(id);
|
|
1013
|
+
if (timer) window.clearTimeout(timer);
|
|
1014
|
+
timers.delete(id);
|
|
1015
|
+
const entry = entries.find((item) => item.id === id);
|
|
1016
|
+
entries = entries.filter((item) => item.id !== id);
|
|
1017
|
+
entry?.onClose?.();
|
|
1018
|
+
publish();
|
|
1019
|
+
}
|
|
1020
|
+
function show({ duration = 4500, severity = "info", ...options }) {
|
|
1021
|
+
const id = ++messageId;
|
|
1022
|
+
entries = [...entries, { id, duration, severity, ...options }];
|
|
1023
|
+
publish();
|
|
1024
|
+
if (duration !== null) timers.set(id, window.setTimeout(() => dismiss(id), duration));
|
|
1025
|
+
return id;
|
|
1026
|
+
}
|
|
1027
|
+
var message = {
|
|
1028
|
+
show,
|
|
1029
|
+
success: (content, options = {}) => show({ content, severity: "success", ...options }),
|
|
1030
|
+
info: (content, options = {}) => show({ content, severity: "info", ...options }),
|
|
1031
|
+
warning: (content, options = {}) => show({ content, severity: "warning", ...options }),
|
|
1032
|
+
error: (content, options = {}) => show({ content, severity: "error", ...options }),
|
|
1033
|
+
dismiss,
|
|
1034
|
+
clear: () => [...entries].forEach((entry) => dismiss(entry.id))
|
|
1035
|
+
};
|
|
1036
|
+
var icons = { success: "\u2713", info: "i", warning: "!", error: "\xD7" };
|
|
1037
|
+
function Message({ maxCount = 4, closeLabel = "Close notification", className, ...props }) {
|
|
1038
|
+
const [visibleEntries, setVisibleEntries] = (0, import_react10.useState)(entries);
|
|
1039
|
+
(0, import_react10.useEffect)(() => {
|
|
1040
|
+
const listener = (nextEntries) => setVisibleEntries(nextEntries);
|
|
1041
|
+
listeners.add(listener);
|
|
1042
|
+
return () => {
|
|
1043
|
+
listeners.delete(listener);
|
|
1044
|
+
};
|
|
1045
|
+
}, []);
|
|
1046
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: ["fe-message-viewport", className].filter(Boolean).join(" "), "aria-live": "polite", ...props, children: visibleEntries.slice(-Math.max(1, maxCount)).map((entry) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: `fe-message fe-message--${entry.severity ?? "info"}`, role: entry.severity === "error" ? "alert" : "status", children: [
|
|
1047
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "fe-message__icon", "aria-hidden": "true", children: icons[entry.severity ?? "info"] }),
|
|
1048
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "fe-message__body", children: [
|
|
1049
|
+
entry.title && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("strong", { className: "fe-message__title", children: entry.title }),
|
|
1050
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "fe-message__content", children: entry.content })
|
|
1051
|
+
] }),
|
|
1052
|
+
entry.action && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "fe-message__action", children: entry.action }),
|
|
1053
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { className: "fe-message__close", hierarchy: "tertiary-gray", size: "24", iconOnly: true, icon: "\xD7", "aria-label": closeLabel, onClick: () => dismiss(entry.id) })
|
|
1054
|
+
] }, entry.id)) });
|
|
1055
|
+
}
|
|
1056
|
+
((Message2) => {
|
|
1057
|
+
Message2.show = message.show;
|
|
1058
|
+
Message2.success = message.success;
|
|
1059
|
+
Message2.info = message.info;
|
|
1060
|
+
Message2.warning = message.warning;
|
|
1061
|
+
Message2.error = message.error;
|
|
1062
|
+
Message2.dismiss = message.dismiss;
|
|
1063
|
+
Message2.clear = message.clear;
|
|
1064
|
+
})(Message || (Message = {}));
|
|
1065
|
+
|
|
1066
|
+
// packages/snackbar/src/index.tsx
|
|
1067
|
+
var import_react11 = require("react");
|
|
1068
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1069
|
+
function Snackbar({
|
|
1070
|
+
open,
|
|
1071
|
+
message: message2,
|
|
1072
|
+
autoHideDuration = 5e3,
|
|
1073
|
+
onClose,
|
|
1074
|
+
action,
|
|
1075
|
+
anchorOrigin = {},
|
|
1076
|
+
closeLabel = "Close notification",
|
|
1077
|
+
className,
|
|
1078
|
+
...props
|
|
1079
|
+
}) {
|
|
1080
|
+
const vertical = anchorOrigin.vertical ?? "bottom";
|
|
1081
|
+
const horizontal = anchorOrigin.horizontal ?? "center";
|
|
1082
|
+
(0, import_react11.useEffect)(() => {
|
|
1083
|
+
if (!open || autoHideDuration === null) return void 0;
|
|
1084
|
+
const timer = window.setTimeout(() => onClose?.("timeout"), autoHideDuration);
|
|
1085
|
+
return () => window.clearTimeout(timer);
|
|
1086
|
+
}, [open, autoHideDuration, onClose]);
|
|
1087
|
+
(0, import_react11.useEffect)(() => {
|
|
1088
|
+
if (!open) return void 0;
|
|
1089
|
+
const onKeyDown = (event) => {
|
|
1090
|
+
if (event.key === "Escape") onClose?.("escapeKeyDown");
|
|
1091
|
+
};
|
|
1092
|
+
window.addEventListener("keydown", onKeyDown);
|
|
1093
|
+
return () => window.removeEventListener("keydown", onKeyDown);
|
|
1094
|
+
}, [open, onClose]);
|
|
1095
|
+
if (!open) return null;
|
|
1096
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: ["fe-snackbar", `fe-snackbar--${vertical}`, `fe-snackbar--${horizontal}`, className].filter(Boolean).join(" "), ...props, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "fe-snackbar__content", role: "status", "aria-live": "polite", children: [
|
|
1097
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "fe-snackbar__message", children: message2 }),
|
|
1098
|
+
action && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "fe-snackbar__action", children: action }),
|
|
1099
|
+
onClose && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Button, { className: "fe-snackbar__close", hierarchy: "tertiary-gray", size: "24", iconOnly: true, icon: "\xD7", "aria-label": closeLabel, onClick: () => onClose("closeButton") })
|
|
1100
|
+
] }) });
|
|
1101
|
+
}
|
|
639
1102
|
// Annotate the CommonJS export names for ESM import in node:
|
|
640
1103
|
0 && (module.exports = {
|
|
641
1104
|
Button,
|
|
642
1105
|
ChevronDownIcon,
|
|
1106
|
+
Chip,
|
|
643
1107
|
CloseIcon,
|
|
644
1108
|
CurrencyInput,
|
|
645
1109
|
DateTimePicker,
|
|
646
1110
|
Drawer,
|
|
647
1111
|
ExpandableSection,
|
|
1112
|
+
Loading,
|
|
1113
|
+
Message,
|
|
1114
|
+
Modal,
|
|
648
1115
|
NumberInput,
|
|
1116
|
+
Pagination,
|
|
649
1117
|
PlusIcon,
|
|
1118
|
+
ProgressBar,
|
|
650
1119
|
SearchIcon,
|
|
651
1120
|
Selection,
|
|
1121
|
+
Skeleton,
|
|
1122
|
+
SkeletonBox,
|
|
1123
|
+
SkeletonCircle,
|
|
1124
|
+
SkeletonLine,
|
|
1125
|
+
SkeletonSquare,
|
|
1126
|
+
Snackbar,
|
|
652
1127
|
Table,
|
|
653
1128
|
TableBody,
|
|
654
1129
|
TableCaption,
|
|
@@ -656,8 +1131,11 @@ function ExpandableSection({ title, children, expanded, defaultExpanded = false,
|
|
|
656
1131
|
TableHead,
|
|
657
1132
|
TableHeader,
|
|
658
1133
|
TableRow,
|
|
1134
|
+
TextArea,
|
|
1135
|
+
TextInput,
|
|
659
1136
|
Toggle,
|
|
660
1137
|
Tooltip,
|
|
661
1138
|
formatNumber,
|
|
662
|
-
getIconSize
|
|
1139
|
+
getIconSize,
|
|
1140
|
+
message
|
|
663
1141
|
});
|