@sentropic/design-system-react 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/catalog.js CHANGED
@@ -1316,4 +1316,389 @@ export function TreeView({ nodes, selectedId, expandedIds, defaultExpandedIds =
1316
1316
  export function UnorderedList({ items, className, ...rest }) {
1317
1317
  return (_jsx("ul", { ...rest, className: classNames("st-unorderedList", className), children: items.map((item, index) => renderListItem(item, index, false)) }));
1318
1318
  }
1319
+ function StarIcon({ size, fill }) {
1320
+ return (_jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: fill, stroke: "currentColor", strokeWidth: 1.75, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("polygon", { points: "12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" }) }));
1321
+ }
1322
+ function StarHalfIcon({ size }) {
1323
+ return (_jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.75, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("path", { d: "M12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2v15.77z", fill: "currentColor" }), _jsx("path", { d: "M12 2v15.77l6.18 3.25L17 14.14 22 9.27l-6.91-1.01L12 2z" })] }));
1324
+ }
1325
+ export function Rating({ value, max = 5, onChange, readonly = false, allowHalf = false, size = "md", name, label, className, ...rest }) {
1326
+ const [current, setCurrent] = useControlled(value, value ?? 0, onChange);
1327
+ const iconSize = size === "sm" ? 16 : size === "lg" ? 28 : 22;
1328
+ const stars = Array.from({ length: max }, (_, i) => i + 1);
1329
+ // L'étoile « focusable » (tabindex 0) suit la valeur ; à 0 c'est la première.
1330
+ const focusedStar = current > 0 ? Math.ceil(current) : 1;
1331
+ function fill(star) {
1332
+ if (current >= star)
1333
+ return "full";
1334
+ if (allowHalf && current >= star - 0.5)
1335
+ return "half";
1336
+ return "empty";
1337
+ }
1338
+ function commit(next) {
1339
+ if (readonly)
1340
+ return;
1341
+ setCurrent(Math.max(0, Math.min(max, next)));
1342
+ }
1343
+ function onStarClick(event, star) {
1344
+ if (readonly)
1345
+ return;
1346
+ let next = star;
1347
+ if (allowHalf) {
1348
+ const rect = event.currentTarget.getBoundingClientRect();
1349
+ const isLeftHalf = event.clientX - rect.left < rect.width / 2;
1350
+ next = isLeftHalf ? star - 0.5 : star;
1351
+ }
1352
+ // Re-cliquer la valeur déjà sélectionnée remet à zéro.
1353
+ if (next === current) {
1354
+ commit(0);
1355
+ return;
1356
+ }
1357
+ commit(next);
1358
+ }
1359
+ function onKeyDown(event) {
1360
+ if (readonly)
1361
+ return;
1362
+ const step = allowHalf ? 0.5 : 1;
1363
+ let handled = true;
1364
+ switch (event.key) {
1365
+ case "ArrowRight":
1366
+ case "ArrowUp":
1367
+ commit(Math.min(max, current + step));
1368
+ break;
1369
+ case "ArrowLeft":
1370
+ case "ArrowDown":
1371
+ commit(Math.max(0, current - step));
1372
+ break;
1373
+ case "Home":
1374
+ commit(0);
1375
+ break;
1376
+ case "End":
1377
+ commit(max);
1378
+ break;
1379
+ default:
1380
+ handled = false;
1381
+ }
1382
+ if (handled)
1383
+ event.preventDefault();
1384
+ }
1385
+ return (_jsx("div", { ...rest, className: classNames("st-rating", `st-rating--${size}`, readonly && "st-rating--readonly", className), role: "radiogroup", "aria-label": label, "aria-readonly": readonly ? "true" : undefined, children: stars.map((star) => {
1386
+ const state = fill(star);
1387
+ return (_jsx("button", { type: "button", className: classNames("st-rating__star", state === "full" && "st-rating__star--full", state === "half" && "st-rating__star--half"), role: "radio", name: name, "aria-checked": Math.ceil(current) === star ? "true" : "false", "aria-label": `${star} / ${max}`, tabIndex: !readonly && star === focusedStar ? 0 : -1, disabled: readonly, onClick: (event) => onStarClick(event, star), onKeyDown: onKeyDown, children: state === "half" ? (_jsx(StarHalfIcon, { size: iconSize })) : (_jsx(StarIcon, { size: iconSize, fill: state === "full" ? "currentColor" : "none" })) }, star));
1388
+ }) }));
1389
+ }
1390
+ function timeToMinutes(hhmm) {
1391
+ if (!hhmm)
1392
+ return null;
1393
+ const match = /^(\d{1,2}):(\d{2})$/.exec(hhmm);
1394
+ if (!match)
1395
+ return null;
1396
+ const h = Number(match[1]);
1397
+ const m = Number(match[2]);
1398
+ if (h < 0 || h > 23 || m < 0 || m > 59)
1399
+ return null;
1400
+ return h * 60 + m;
1401
+ }
1402
+ function timeFromMinutes(total) {
1403
+ const h = Math.floor(total / 60);
1404
+ const m = total % 60;
1405
+ return `${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}`;
1406
+ }
1407
+ export function TimePicker({ value, onChange, step = 15, min, max, format = "24", size = "md", disabled = false, label, className, id, ...rest }) {
1408
+ const reactId = React.useId();
1409
+ const fieldId = id ?? `st-timepicker-${reactId}`;
1410
+ const listId = `${fieldId}-list`;
1411
+ const hostRef = React.useRef(null);
1412
+ const [open, setOpen] = React.useState(false);
1413
+ const [current, setCurrent] = useControlled(value, value ?? "", onChange);
1414
+ function display(hhmm) {
1415
+ if (format === "24")
1416
+ return hhmm;
1417
+ const total = timeToMinutes(hhmm);
1418
+ if (total === null)
1419
+ return hhmm;
1420
+ const h24 = Math.floor(total / 60);
1421
+ const m = total % 60;
1422
+ const period = h24 < 12 ? "AM" : "PM";
1423
+ let h12 = h24 % 12;
1424
+ if (h12 === 0)
1425
+ h12 = 12;
1426
+ return `${String(h12).padStart(2, "0")}:${String(m).padStart(2, "0")} ${period}`;
1427
+ }
1428
+ const slots = React.useMemo(() => {
1429
+ const safeStep = step > 0 ? step : 15;
1430
+ const lower = timeToMinutes(min) ?? 0;
1431
+ const upper = timeToMinutes(max) ?? 23 * 60 + 59;
1432
+ const result = [];
1433
+ for (let t = lower; t <= upper; t += safeStep) {
1434
+ result.push(timeFromMinutes(t));
1435
+ }
1436
+ return result;
1437
+ }, [step, min, max]);
1438
+ const displayValue = current ? display(current) : "";
1439
+ function toggleOpen() {
1440
+ if (disabled)
1441
+ return;
1442
+ setOpen((prev) => !prev);
1443
+ }
1444
+ function pick(slot) {
1445
+ setCurrent(slot);
1446
+ setOpen(false);
1447
+ }
1448
+ useOutsideMouseDown(open, hostRef, () => setOpen(false));
1449
+ return (_jsxs("div", { className: classNames("st-field", className), ref: hostRef, ...rest, children: [_jsxs("div", { className: "st-field__control", children: [label ? (_jsx("label", { className: "st-field__label", htmlFor: fieldId, children: label })) : null, _jsxs("span", { className: classNames("st-timepicker", `st-timepicker--${size}`), children: [_jsx("input", { id: fieldId, type: "text", readOnly: true, className: "st-timepicker__control", value: displayValue, placeholder: format === "24" ? "HH:mm" : "hh:mm AM", disabled: disabled, role: "combobox", "aria-haspopup": "listbox", "aria-controls": listId, "aria-expanded": open ? "true" : "false", onClick: toggleOpen }), _jsx("button", { type: "button", className: "st-timepicker__trigger", "aria-label": "Ouvrir la liste des horaires", "aria-haspopup": "listbox", "aria-expanded": open ? "true" : "false", disabled: disabled, onClick: toggleOpen, children: _jsx(ClockIcon, { size: 16 }) })] })] }), open ? (_jsx("ul", { id: listId, className: "st-timepicker__list", role: "listbox", "aria-label": label ?? "Horaires", tabIndex: -1, onKeyDown: (event) => {
1450
+ if (event.key === "Escape") {
1451
+ event.preventDefault();
1452
+ setOpen(false);
1453
+ }
1454
+ }, children: slots.map((slot) => (_jsx("li", { role: "presentation", children: _jsx("button", { type: "button", className: classNames("st-timepicker__option", slot === current && "st-timepicker__option--selected"), role: "option", "aria-selected": slot === current ? "true" : "false", onClick: () => pick(slot), children: display(slot) }) }, slot))) })) : null] }));
1455
+ }
1456
+ function ClockIcon({ size }) {
1457
+ return (_jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("circle", { cx: "12", cy: "12", r: "10" }), _jsx("polyline", { points: "12 6 12 12 16 14" })] }));
1458
+ }
1459
+ function calStartOfDay(date) {
1460
+ const d = new Date(date);
1461
+ d.setHours(0, 0, 0, 0);
1462
+ return d;
1463
+ }
1464
+ function calToISO(date) {
1465
+ const y = date.getFullYear();
1466
+ const m = String(date.getMonth() + 1).padStart(2, "0");
1467
+ const d = String(date.getDate()).padStart(2, "0");
1468
+ return `${y}-${m}-${d}`;
1469
+ }
1470
+ function calParseISO(iso) {
1471
+ if (!iso)
1472
+ return null;
1473
+ const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(iso);
1474
+ if (!match)
1475
+ return null;
1476
+ const d = new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3]));
1477
+ return Number.isNaN(d.getTime()) ? null : calStartOfDay(d);
1478
+ }
1479
+ function calIsSameDay(a, b) {
1480
+ if (!a || !b)
1481
+ return false;
1482
+ return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
1483
+ }
1484
+ export function Calendar({ value, onChange, min, max, range = false, weekStartsOn = 1, locale = "fr-FR", month, className, previousMonthLabel, nextMonthLabel, ...rest }) {
1485
+ const [activeValue, setCurrent] = useControlled(value, value ?? null, onChange);
1486
+ const isFr = (locale ?? "fr-FR").toLowerCase().startsWith("fr");
1487
+ const resolvedPrevLabel = previousMonthLabel ?? (isFr ? "Mois précédent" : "Previous month");
1488
+ const resolvedNextLabel = nextMonthLabel ?? (isFr ? "Mois suivant" : "Next month");
1489
+ const monthFormatter = React.useMemo(() => new Intl.DateTimeFormat(locale, { month: "long", year: "numeric" }), [locale]);
1490
+ const weekdayFormatter = React.useMemo(() => new Intl.DateTimeFormat(locale, { weekday: "short" }), [locale]);
1491
+ const cellFormatter = React.useMemo(() => new Intl.DateTimeFormat(locale, { day: "numeric", month: "long", year: "numeric" }), [locale]);
1492
+ const single = range ? null : calParseISO(activeValue);
1493
+ const rangeStart = range && Array.isArray(activeValue) ? calParseISO(activeValue[0]) : null;
1494
+ const rangeEnd = range && Array.isArray(activeValue) ? calParseISO(activeValue[1]) : null;
1495
+ function pickInitialMonth() {
1496
+ const parsed = calParseISO(month ? `${month}-01` : undefined);
1497
+ if (parsed)
1498
+ return parsed;
1499
+ if (!range && single)
1500
+ return single;
1501
+ if (range && rangeStart)
1502
+ return rangeStart;
1503
+ return calStartOfDay(new Date());
1504
+ }
1505
+ const initial = React.useRef(pickInitialMonth());
1506
+ const [viewYear, setViewYear] = React.useState(initial.current.getFullYear());
1507
+ const [viewMonth, setViewMonth] = React.useState(initial.current.getMonth());
1508
+ // Resynchronise le mois affiché lorsque la prop `month` change.
1509
+ React.useEffect(() => {
1510
+ const parsed = calParseISO(month ? `${month}-01` : undefined);
1511
+ if (parsed) {
1512
+ setViewYear(parsed.getFullYear());
1513
+ setViewMonth(parsed.getMonth());
1514
+ }
1515
+ }, [month]);
1516
+ const today = React.useMemo(() => calStartOfDay(new Date()), []);
1517
+ const weekdayLabels = React.useMemo(() => {
1518
+ // 2024-01-07 est un dimanche : on énumère puis on tourne selon weekStartsOn.
1519
+ const sample = new Date(Date.UTC(2024, 0, 7));
1520
+ const labels = [];
1521
+ for (let i = 0; i < 7; i++) {
1522
+ const d = new Date(sample);
1523
+ d.setUTCDate(sample.getUTCDate() + i);
1524
+ labels.push(weekdayFormatter.format(d));
1525
+ }
1526
+ return [...labels.slice(weekStartsOn), ...labels.slice(0, weekStartsOn)];
1527
+ }, [weekdayFormatter, weekStartsOn]);
1528
+ const grid = React.useMemo(() => {
1529
+ const first = new Date(viewYear, viewMonth, 1);
1530
+ const firstDayIdx = first.getDay();
1531
+ const offset = (firstDayIdx - weekStartsOn + 7) % 7;
1532
+ const start = new Date(viewYear, viewMonth, 1 - offset);
1533
+ const cells = [];
1534
+ for (let i = 0; i < 42; i++) {
1535
+ const d = new Date(start);
1536
+ d.setDate(start.getDate() + i);
1537
+ cells.push({ date: calStartOfDay(d), inMonth: d.getMonth() === viewMonth });
1538
+ }
1539
+ return cells;
1540
+ }, [viewYear, viewMonth, weekStartsOn]);
1541
+ const minDate = calParseISO(min);
1542
+ const maxDate = calParseISO(max);
1543
+ function isOutOfBounds(date) {
1544
+ const d = calStartOfDay(date).getTime();
1545
+ if (minDate && d < minDate.getTime())
1546
+ return true;
1547
+ if (maxDate && d > maxDate.getTime())
1548
+ return true;
1549
+ return false;
1550
+ }
1551
+ function isSelected(date) {
1552
+ if (!range)
1553
+ return calIsSameDay(single, date);
1554
+ return calIsSameDay(rangeStart, date) || calIsSameDay(rangeEnd, date);
1555
+ }
1556
+ function isInRange(date) {
1557
+ if (!range || !rangeStart || !rangeEnd)
1558
+ return false;
1559
+ const d = calStartOfDay(date).getTime();
1560
+ return d > rangeStart.getTime() && d < rangeEnd.getTime();
1561
+ }
1562
+ function previousMonth() {
1563
+ if (viewMonth === 0) {
1564
+ setViewMonth(11);
1565
+ setViewYear((y) => y - 1);
1566
+ }
1567
+ else {
1568
+ setViewMonth((m) => m - 1);
1569
+ }
1570
+ }
1571
+ function nextMonth() {
1572
+ if (viewMonth === 11) {
1573
+ setViewMonth(0);
1574
+ setViewYear((y) => y + 1);
1575
+ }
1576
+ else {
1577
+ setViewMonth((m) => m + 1);
1578
+ }
1579
+ }
1580
+ function pickDate(date) {
1581
+ if (isOutOfBounds(date))
1582
+ return;
1583
+ const picked = calStartOfDay(date);
1584
+ const iso = calToISO(picked);
1585
+ if (!range) {
1586
+ setCurrent(iso);
1587
+ return;
1588
+ }
1589
+ // Mode plage : (re)démarrage si pas de début, ou si plage déjà complète,
1590
+ // ou si la date est antérieure au début courant.
1591
+ if (!rangeStart || (rangeStart && rangeEnd) || picked.getTime() < rangeStart.getTime()) {
1592
+ setCurrent([iso, null]);
1593
+ return;
1594
+ }
1595
+ setCurrent([calToISO(rangeStart), iso]);
1596
+ }
1597
+ const monthLabel = monthFormatter.format(new Date(viewYear, viewMonth, 1));
1598
+ return (_jsxs("div", { className: classNames("st-calendar", className), ...rest, children: [_jsxs("div", { className: "st-calendar__nav", children: [_jsx("button", { type: "button", className: "st-calendar__navBtn", "aria-label": resolvedPrevLabel, onClick: previousMonth, children: _jsx(ChevronLeftIcon, { size: 18 }) }), _jsx("span", { className: "st-calendar__monthLabel", "aria-live": "polite", children: monthLabel }), _jsx("button", { type: "button", className: "st-calendar__navBtn", "aria-label": resolvedNextLabel, onClick: nextMonth, children: _jsx(ChevronRightIcon, { size: 18 }) })] }), _jsxs("div", { className: "st-calendar__grid", role: "grid", tabIndex: -1, "aria-label": monthLabel, onKeyDown: (event) => {
1599
+ if (event.key === "PageUp") {
1600
+ event.preventDefault();
1601
+ previousMonth();
1602
+ }
1603
+ else if (event.key === "PageDown") {
1604
+ event.preventDefault();
1605
+ nextMonth();
1606
+ }
1607
+ }, children: [_jsx("div", { className: "st-calendar__weekdays", role: "row", children: weekdayLabels.map((wd, i) => (_jsx("span", { className: "st-calendar__weekday", role: "columnheader", children: wd }, `${wd}-${i}`))) }), _jsx("div", { className: "st-calendar__days", children: grid.map((cell, i) => {
1608
+ const oob = isOutOfBounds(cell.date);
1609
+ const selected = isSelected(cell.date);
1610
+ const inRange = isInRange(cell.date);
1611
+ const isToday = calIsSameDay(cell.date, today);
1612
+ return (_jsx("button", { type: "button", className: classNames("st-calendar__day", !cell.inMonth && "st-calendar__day--outside", selected && "st-calendar__day--selected", inRange && "st-calendar__day--inRange", isToday && "st-calendar__day--today"), role: "gridcell", "aria-label": cellFormatter.format(cell.date), "aria-selected": selected ? "true" : "false", "aria-current": isToday ? "date" : undefined, "aria-disabled": oob ? "true" : undefined, disabled: oob, onClick: () => pickDate(cell.date), children: cell.date.getDate() }, i));
1613
+ }) })] })] }));
1614
+ }
1615
+ function ChevronLeftIcon({ size }) {
1616
+ return (_jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("polyline", { points: "15 18 9 12 15 6" }) }));
1617
+ }
1618
+ function ChevronRightIcon({ size }) {
1619
+ return (_jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("polyline", { points: "9 18 15 12 9 6" }) }));
1620
+ }
1621
+ export function SlideIndicator({ count, current = 0, onChange, size = "md", variant = "dots", label = "Diapositive", className, ...rest }) {
1622
+ const items = Array.from({ length: Math.max(0, count) }, (_, i) => i);
1623
+ function select(index) {
1624
+ if (index < 0 || index >= count || index === current)
1625
+ return;
1626
+ onChange?.(index);
1627
+ }
1628
+ function onKeyDown(event, index) {
1629
+ let target = index;
1630
+ switch (event.key) {
1631
+ case "ArrowRight":
1632
+ case "ArrowDown":
1633
+ target = Math.min(count - 1, index + 1);
1634
+ break;
1635
+ case "ArrowLeft":
1636
+ case "ArrowUp":
1637
+ target = Math.max(0, index - 1);
1638
+ break;
1639
+ case "Home":
1640
+ target = 0;
1641
+ break;
1642
+ case "End":
1643
+ target = count - 1;
1644
+ break;
1645
+ default:
1646
+ return;
1647
+ }
1648
+ event.preventDefault();
1649
+ select(target);
1650
+ }
1651
+ return (_jsx("div", { ...rest, className: classNames("st-slideIndicator", `st-slideIndicator--${size}`, `st-slideIndicator--${variant}`, className), role: "tablist", "aria-label": label, children: items.map((index) => (_jsx("button", { type: "button", className: classNames("st-slideIndicator__dot", index === current && "st-slideIndicator__dot--current"), role: "tab", "aria-selected": index === current ? "true" : "false", "aria-current": index === current ? "true" : undefined, "aria-label": `${label} ${index + 1}`, tabIndex: index === current ? 0 : -1, onClick: () => select(index), onKeyDown: (event) => onKeyDown(event, index) }, index))) }));
1652
+ }
1653
+ export function Autosave({ status = "idle", lastSaved, onRetry, labels, retryLabel, locale = "fr-FR", className, ...rest }) {
1654
+ const isFr = (locale ?? "fr-FR").toLowerCase().startsWith("fr");
1655
+ const DEFAULT_LABELS = isFr
1656
+ ? {
1657
+ idle: "Modifications enregistrées",
1658
+ saving: "Enregistrement…",
1659
+ saved: "Enregistré",
1660
+ error: "Échec de l'enregistrement",
1661
+ }
1662
+ : {
1663
+ idle: "All changes saved",
1664
+ saving: "Saving…",
1665
+ saved: "Saved",
1666
+ error: "Failed to save",
1667
+ };
1668
+ const resolvedRetryLabel = retryLabel ?? (isFr ? "Réessayer" : "Retry");
1669
+ const statusLabel = labels?.[status] ?? DEFAULT_LABELS[status];
1670
+ const role = status === "error" ? "alert" : "status";
1671
+ // Heure relative de la dernière sauvegarde (rendu uniquement sur idle/saved).
1672
+ const relativeTime = (() => {
1673
+ if (!lastSaved)
1674
+ return "";
1675
+ const date = lastSaved instanceof Date ? lastSaved : new Date(lastSaved);
1676
+ if (Number.isNaN(date.getTime()))
1677
+ return "";
1678
+ const diffMs = Date.now() - date.getTime();
1679
+ const diffSec = Math.round(diffMs / 1000);
1680
+ const rtf = new Intl.RelativeTimeFormat(locale, { numeric: "auto" });
1681
+ if (Math.abs(diffSec) < 60)
1682
+ return rtf.format(-diffSec, "second");
1683
+ const diffMin = Math.round(diffSec / 60);
1684
+ if (Math.abs(diffMin) < 60)
1685
+ return rtf.format(-diffMin, "minute");
1686
+ const diffHour = Math.round(diffMin / 60);
1687
+ if (Math.abs(diffHour) < 24)
1688
+ return rtf.format(-diffHour, "hour");
1689
+ const diffDay = Math.round(diffHour / 24);
1690
+ return rtf.format(-diffDay, "day");
1691
+ })();
1692
+ const showRelative = (status === "saved" || status === "idle") && relativeTime !== "";
1693
+ return (_jsxs("div", { ...rest, className: classNames("st-autosave", `st-autosave--${status}`, className), role: role, "aria-live": "polite", children: [_jsx("span", { className: "st-autosave__icon", "aria-hidden": "true", children: status === "saving" ? (_jsx("span", { className: "st-autosave__spinner", children: _jsx(LoaderCircleIcon, { size: 16 }) })) : status === "saved" ? (_jsx(CircleCheckIcon, { size: 16 })) : status === "error" ? (_jsx(CircleAlertIcon, { size: 16 })) : null }), _jsx("span", { className: "st-autosave__label", children: statusLabel }), showRelative ? _jsx("span", { className: "st-autosave__time", children: relativeTime }) : null, status === "error" && onRetry ? (_jsx("button", { type: "button", className: "st-autosave__retry", onClick: () => onRetry?.(), children: resolvedRetryLabel })) : null] }));
1694
+ }
1695
+ function LoaderCircleIcon({ size }) {
1696
+ return (_jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) }));
1697
+ }
1698
+ function CircleCheckIcon({ size }) {
1699
+ return (_jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("circle", { cx: "12", cy: "12", r: "10" }), _jsx("path", { d: "m9 12 2 2 4-4" })] }));
1700
+ }
1701
+ function CircleAlertIcon({ size }) {
1702
+ return (_jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("circle", { cx: "12", cy: "12", r: "10" }), _jsx("line", { x1: "12", x2: "12", y1: "8", y2: "12" }), _jsx("line", { x1: "12", x2: "12.01", y1: "16", y2: "16" })] }));
1703
+ }
1319
1704
  //# sourceMappingURL=catalog.js.map