@apliteni/apliteni-ui 0.43.1 → 0.45.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apliteni/apliteni-ui",
3
- "version": "0.43.1",
3
+ "version": "0.45.0",
4
4
  "workspaces": [
5
5
  "react"
6
6
  ],
package/react/README.md CHANGED
@@ -28,7 +28,7 @@ import '@apliteni/apliteni-ui/react/css'; // React components' shell styles (mo
28
28
  import { DataTable, Modal, Button } from '@apliteni/apliteni-ui/react';
29
29
  ```
30
30
 
31
- Components: `DataTable`, `Pagination`, `StatBand`, `Modal`, `Drawer`, `CommandPalette`, `Dropdown`, `BackLink`, `Snippet`, `Button`, `Badge`, `Card`, `Icon`.
31
+ Components: `DataTable`, `Pagination`, `StatBand`, `Modal`, `Confirm`, `Drawer`, `CommandPalette`, `Dropdown`, `BackLink`, `Snippet`, `Tabs`, `Button`, `Badge`, `Card`, `Icon`.
32
32
 
33
33
  `Snippet` accepts `label`, `code`, `reveal`, and `copyLabel` props. It treats `code`
34
34
  as plain text and copies it exactly as provided. After a successful clipboard write,
@@ -332,3 +332,35 @@ import '@apliteni/apliteni-ui/react/css';
332
332
  ]} />
333
333
  </DrawerSection>
334
334
  ```
335
+
336
+ ## Tabs
337
+
338
+ Tabs is controlled through `value` and `onChange`. Pass items with unique values, labels, optional counts, and React panel content. Provide a label for the tablist and a value that matches one item. Inactive panel content is unmounted.
339
+
340
+ Arrow keys move between tabs and wrap from the last tab to the first. They also activate the selected tab. Home and End select the first and last tabs. Tab moves to the selected panel. New panels use the kit’s fade animation, which is shortened when reduced motion is enabled.
341
+
342
+ ## Confirm
343
+
344
+ Use `Confirm` before an action that has a cost. Put the object name in `title`. In
345
+ `body`, explain what will change and whether the change can be reversed. Give both
346
+ buttons clear, specific labels. For an undoable action, use a toast with Undo instead.
347
+
348
+ ```tsx
349
+ <Confirm open={open} title="Revoke demo token?"
350
+ body="This token will stop working immediately. You cannot restore it."
351
+ confirmLabel="Revoke token" cancelLabel="Keep the token" danger busy={saving}
352
+ onConfirm={revokeToken} onCancel={() => setOpen(false)} />
353
+ ```
354
+
355
+ The consumer controls `open` and `busy`. `Confirm` does not wait for `onConfirm` or
356
+ close itself. Set `busy` while saving. This keeps focus, prevents repeated presses, and
357
+ announces progress. Without `danger`, the committing button uses the primary tone.
358
+
359
+ Escape, the scrim, the close button, and the safe action call `onCancel`, even while
360
+ busy. Closing the dialog does not cancel a write that has already started.
361
+
362
+ `Confirm` uses Modal's focus trap, focus return, and reduced-motion transitions. When it
363
+ opens, focus goes to the safe action. It renders an `alertdialog`, named by its title
364
+ and described by its body. Modal also accepts
365
+ `initialFocusRef` for a mounted, focusable element inside its panel. Without it, Modal
366
+ uses its normal opening focus.
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { ReactNode, ButtonHTMLAttributes, MouseEvent, ElementType, ComponentPropsWithoutRef } from 'react';
2
+ import { ReactNode, ButtonHTMLAttributes, RefObject, MouseEvent, ElementType, ComponentPropsWithoutRef } from 'react';
3
3
 
4
4
  declare function Icon({ name }: {
5
5
  name: string;
@@ -16,7 +16,17 @@ type ButtonProps = {
16
16
  busy?: boolean;
17
17
  children?: ReactNode;
18
18
  } & ButtonHTMLAttributes<HTMLButtonElement>;
19
- declare function Button({ variant, size, icon, iconRight, iconOnly, block, busy, children, type, disabled, onClick, onClickCapture, onKeyDown, onKeyDownCapture, onKeyUp, onKeyUpCapture, ...rest }: ButtonProps): react.JSX.Element;
19
+ declare const Button: react.ForwardRefExoticComponent<{
20
+ variant?: "primary" | "secondary" | "ghost" | "danger";
21
+ size?: "xs" | "sm" | "md" | "lg";
22
+ icon?: string;
23
+ iconRight?: string;
24
+ iconOnly?: boolean;
25
+ block?: boolean;
26
+ /** In flight: keeps focus, blocks activation, announces progress, and shows dots. */
27
+ busy?: boolean;
28
+ children?: ReactNode;
29
+ } & ButtonHTMLAttributes<HTMLButtonElement> & react.RefAttributes<HTMLButtonElement>>;
20
30
 
21
31
  declare function Badge({ variant, children }: {
22
32
  variant?: string;
@@ -55,14 +65,29 @@ interface StatBandProps {
55
65
  }
56
66
  declare function StatBand({ stats, variant, basis, label, id }: StatBandProps): react.JSX.Element;
57
67
 
68
+ type ConfirmProps = {
69
+ open: boolean;
70
+ title: string;
71
+ body: ReactNode;
72
+ confirmLabel: string;
73
+ cancelLabel: string;
74
+ danger?: boolean;
75
+ busy?: boolean;
76
+ onConfirm: () => void;
77
+ onCancel: () => void;
78
+ };
79
+ declare function Confirm({ open, title, body, confirmLabel, cancelLabel, danger, busy, onConfirm, onCancel, }: ConfirmProps): react.JSX.Element;
80
+
58
81
  type ModalProps = {
59
82
  open: boolean;
60
83
  title: string;
61
84
  onClose: () => void;
62
85
  footer?: ReactNode;
63
86
  children?: ReactNode;
87
+ role?: 'dialog' | 'alertdialog';
88
+ initialFocusRef?: RefObject<HTMLElement | null>;
64
89
  };
65
- declare function Modal({ open, title, onClose, footer, children }: ModalProps): react.ReactPortal | null;
90
+ declare function Modal({ open, title, onClose, footer, children, initialFocusRef, role }: ModalProps): react.ReactPortal | null;
66
91
 
67
92
  type DrawerProps = {
68
93
  open: boolean;
@@ -450,7 +475,21 @@ type SnippetProps = {
450
475
  };
451
476
  declare function Snippet({ label, code, reveal, copyLabel }: SnippetProps): react.JSX.Element;
452
477
 
478
+ type TabItem = {
479
+ value: string;
480
+ label: string;
481
+ count?: number;
482
+ panel: ReactNode;
483
+ };
484
+ type TabsProps = {
485
+ items: TabItem[];
486
+ value: string;
487
+ onChange: (value: string) => void;
488
+ label: string;
489
+ };
490
+ declare function Tabs({ items, value, onChange, label }: TabsProps): react.JSX.Element;
491
+
453
492
  declare const PAGE_SIZES: readonly number[];
454
493
  declare const DEFAULT_PAGE_SIZE: number;
455
494
 
456
- export { BackLink, type BackLinkOwnProps, type BackLinkProps, Badge, BusyRegion, type BusyRegionProps, Button, type ButtonProps, Card, type Column, type CommandGroup, type CommandItem, CommandPalette, type CommandPaletteProps, DEFAULT_PAGE_SIZE, DataTable, type DataTableProps, DeltaValue, type DeltaValueProps, Denied, type DeniedProps, Drawer, type DrawerProps, DrawerSection, type DrawerSectionProps, Dropdown, type DropdownBadge, type DropdownEntry, type DropdownItem, type DropdownProps, type DropdownRowProps, type DropdownSearch, type DropdownSection, type DropdownSeparator, type Filter, FilterBar, type FilterBarProps, Icon, KeyValueList, type KeyValueListProps, type KeyValueRow, Modal, type ModalProps, NumericValue, type NumericValueProps, PAGE_SIZES, Pagination, type PaginationProps, RowIdentity, type RowIdentityProps, type SegmentOption, Segmented, type SegmentedProps, Skeleton, type SkeletonProps, SkeletonTable, type SkeletonTableProps, Snippet, type SnippetProps, StatBand, type StatBandProps, type StatDelta, type StatFigure, type StatTone, type StatVariant, type TableSort, sortTableRows };
495
+ export { BackLink, type BackLinkOwnProps, type BackLinkProps, Badge, BusyRegion, type BusyRegionProps, Button, type ButtonProps, Card, type Column, type CommandGroup, type CommandItem, CommandPalette, type CommandPaletteProps, Confirm, type ConfirmProps, DEFAULT_PAGE_SIZE, DataTable, type DataTableProps, DeltaValue, type DeltaValueProps, Denied, type DeniedProps, Drawer, type DrawerProps, DrawerSection, type DrawerSectionProps, Dropdown, type DropdownBadge, type DropdownEntry, type DropdownItem, type DropdownProps, type DropdownRowProps, type DropdownSearch, type DropdownSection, type DropdownSeparator, type Filter, FilterBar, type FilterBarProps, Icon, KeyValueList, type KeyValueListProps, type KeyValueRow, Modal, type ModalProps, NumericValue, type NumericValueProps, PAGE_SIZES, Pagination, type PaginationProps, RowIdentity, type RowIdentityProps, type SegmentOption, Segmented, type SegmentedProps, Skeleton, type SkeletonProps, SkeletonTable, type SkeletonTableProps, Snippet, type SnippetProps, StatBand, type StatBandProps, type StatDelta, type StatFigure, type StatTone, type StatVariant, type TabItem, type TableSort, Tabs, type TabsProps, sortTableRows };
@@ -15,7 +15,7 @@ function Icon({ name }) {
15
15
  }
16
16
 
17
17
  // src/primitives/Button.tsx
18
- import { useLayoutEffect, useRef } from "react";
18
+ import { forwardRef, useImperativeHandle, useLayoutEffect, useRef } from "react";
19
19
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
20
20
  var announcers = /* @__PURE__ */ new WeakMap();
21
21
  function acquireAnnouncer(doc) {
@@ -48,7 +48,7 @@ function acquireAnnouncer(doc) {
48
48
  };
49
49
  }
50
50
  var cx = (...a) => a.filter(Boolean).join(" ");
51
- function Button({
51
+ var Button = forwardRef(function Button2({
52
52
  variant = "secondary",
53
53
  size = "md",
54
54
  icon: icon4,
@@ -66,8 +66,9 @@ function Button({
66
66
  onKeyUp,
67
67
  onKeyUpCapture,
68
68
  ...rest
69
- }) {
69
+ }, forwardedRef) {
70
70
  const buttonRef = useRef(null);
71
+ useImperativeHandle(forwardedRef, () => buttonRef.current, []);
71
72
  const labelRef = useRef(null);
72
73
  const announcer = useRef(null);
73
74
  const hasBeenBusy = useRef(false);
@@ -151,7 +152,7 @@ function Button({
151
152
  ]
152
153
  }
153
154
  );
154
- }
155
+ });
155
156
 
156
157
  // src/primitives/Badge.tsx
157
158
  import { jsx as jsx3 } from "react/jsx-runtime";
@@ -216,8 +217,11 @@ function StatBand({ stats, variant = "tiles", basis, label, id }) {
216
217
  ] });
217
218
  }
218
219
 
220
+ // src/Confirm.tsx
221
+ import { useRef as useRef4 } from "react";
222
+
219
223
  // src/Modal.tsx
220
- import { useRef as useRef3 } from "react";
224
+ import { useId as useId2, useRef as useRef3 } from "react";
221
225
  import { createPortal } from "react-dom";
222
226
 
223
227
  // src/dialog.ts
@@ -265,7 +269,7 @@ var stack = [];
265
269
  var leaving = /* @__PURE__ */ new Set();
266
270
  var marked = [];
267
271
  var listening = false;
268
- var firstIn = (entry) => (entry.body ? tabbablesIn(entry.body) : [])[0] || entry.panel;
272
+ var firstIn = (entry) => (entry.initialFocus && entry.panel.contains(entry.initialFocus) ? entry.initialFocus : null) || (entry.body ? tabbablesIn(entry.body) : [])[0] || entry.panel;
269
273
  function trapTab(panel, e) {
270
274
  const items = tabbablesIn(panel);
271
275
  if (items.length === 0) {
@@ -301,7 +305,7 @@ function sync() {
301
305
  const top = stack[stack.length - 1];
302
306
  for (let node = top?.root; node?.parentElement && node !== document.body; node = node.parentElement) {
303
307
  for (const sib of Array.from(node.parentElement.children)) {
304
- if (sib === node || leaving.has(sib)) continue;
308
+ if (sib === node || leaving.has(sib) || sib.matches('.ui-btn__status[role="status"]')) continue;
305
309
  marked.push([sib, sib.hasAttribute("inert")]);
306
310
  sib.setAttribute("inert", "");
307
311
  }
@@ -405,7 +409,7 @@ function usePresence(open, root, panel) {
405
409
  }, [open, present]);
406
410
  return { mounted: present, shown };
407
411
  }
408
- function useDialog(active, { root, panel, body }, onClose) {
412
+ function useDialog(active, { root, panel, body, initialFocus }, onClose) {
409
413
  const parent = useContext(DialogScope);
410
414
  const [scope] = useState(() => ({ parent }));
411
415
  const close = useRef2(onClose);
@@ -419,6 +423,7 @@ function useDialog(active, { root, panel, body }, onClose) {
419
423
  root: root.current,
420
424
  panel: panel.current,
421
425
  body: body.current,
426
+ initialFocus: initialFocus?.current ?? null,
422
427
  close: () => close.current(),
423
428
  opener: document.activeElement,
424
429
  resume: null
@@ -431,30 +436,76 @@ function useDialog(active, { root, panel, body }, onClose) {
431
436
 
432
437
  // src/Modal.tsx
433
438
  import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
434
- function Modal({ open, title, onClose, footer, children }) {
439
+ function Modal({ open, title, onClose, footer, children, initialFocusRef, role = "dialog" }) {
440
+ const id = useId2();
441
+ const titleId = `${id}-title`;
442
+ const bodyId = `${id}-body`;
435
443
  const root = useRef3(null);
436
444
  const panel = useRef3(null);
437
445
  const body = useRef3(null);
438
446
  const { mounted, shown } = usePresence(open, root, panel);
439
- const scope = useDialog(shown, { root, panel, body }, onClose);
447
+ const scope = useDialog(shown, { root, panel, body, initialFocus: initialFocusRef }, onClose);
440
448
  if (!mounted) return null;
441
449
  return createPortal(
442
- /* @__PURE__ */ jsx6(DialogScope.Provider, { value: scope, children: /* @__PURE__ */ jsx6("div", { className: shown ? "rx-scrim is-open" : "rx-scrim", ref: root, onMouseDown: dismissOnScrim(onClose), children: /* @__PURE__ */ jsxs4("div", { className: "rx-modal", role: "dialog", "aria-modal": "true", "aria-label": title, tabIndex: -1, ref: panel, children: [
443
- /* @__PURE__ */ jsxs4("div", { className: "rx-modal__head", children: [
444
- /* @__PURE__ */ jsx6("div", { className: "rx-modal__title", children: title }),
445
- /* @__PURE__ */ jsx6(Button, { variant: "ghost", size: "sm", iconOnly: true, icon: "x", "aria-label": "Close", onClick: onClose })
446
- ] }),
447
- /* @__PURE__ */ jsx6("div", { className: "rx-modal__body", ref: body, children }),
448
- footer && /* @__PURE__ */ jsx6("div", { className: "rx-modal__foot", children: footer })
449
- ] }) }) }),
450
+ /* @__PURE__ */ jsx6(DialogScope.Provider, { value: scope, children: /* @__PURE__ */ jsx6("div", { className: shown ? "rx-scrim is-open" : "rx-scrim", ref: root, onMouseDown: dismissOnScrim(onClose), children: /* @__PURE__ */ jsxs4(
451
+ "div",
452
+ {
453
+ className: "rx-modal",
454
+ role,
455
+ "aria-modal": "true",
456
+ "aria-labelledby": titleId,
457
+ "aria-describedby": role === "alertdialog" ? bodyId : void 0,
458
+ tabIndex: -1,
459
+ ref: panel,
460
+ children: [
461
+ /* @__PURE__ */ jsxs4("div", { className: "rx-modal__head", children: [
462
+ /* @__PURE__ */ jsx6("div", { className: "rx-modal__title", id: titleId, children: title }),
463
+ /* @__PURE__ */ jsx6(Button, { variant: "ghost", size: "sm", iconOnly: true, icon: "x", "aria-label": "Close", onClick: onClose })
464
+ ] }),
465
+ /* @__PURE__ */ jsx6("div", { className: "rx-modal__body", id: bodyId, ref: body, children }),
466
+ footer && /* @__PURE__ */ jsx6("div", { className: "rx-modal__foot", children: footer })
467
+ ]
468
+ }
469
+ ) }) }),
450
470
  document.body
451
471
  );
452
472
  }
453
473
 
474
+ // src/Confirm.tsx
475
+ import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
476
+ function Confirm({
477
+ open,
478
+ title,
479
+ body,
480
+ confirmLabel,
481
+ cancelLabel,
482
+ danger = false,
483
+ busy = false,
484
+ onConfirm,
485
+ onCancel
486
+ }) {
487
+ const safeAction = useRef4(null);
488
+ return /* @__PURE__ */ jsx7(
489
+ Modal,
490
+ {
491
+ open,
492
+ title,
493
+ onClose: onCancel,
494
+ role: "alertdialog",
495
+ initialFocusRef: safeAction,
496
+ footer: /* @__PURE__ */ jsxs5(Fragment2, { children: [
497
+ /* @__PURE__ */ jsx7(Button, { ref: safeAction, variant: "ghost", onClick: onCancel, children: cancelLabel }),
498
+ /* @__PURE__ */ jsx7(Button, { variant: danger ? "danger" : "primary", busy, onClick: onConfirm, children: confirmLabel })
499
+ ] }),
500
+ children: body
501
+ }
502
+ );
503
+ }
504
+
454
505
  // src/Drawer.tsx
455
- import { useId as useId2, useRef as useRef4 } from "react";
506
+ import { useId as useId3, useRef as useRef5 } from "react";
456
507
  import { createPortal as createPortal2 } from "react-dom";
457
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
508
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
458
509
  function Drawer({
459
510
  open,
460
511
  title,
@@ -465,18 +516,18 @@ function Drawer({
465
516
  children,
466
517
  closeLabel = "Close"
467
518
  }) {
468
- const root = useRef4(null);
469
- const panel = useRef4(null);
470
- const body = useRef4(null);
471
- const titleId = useId2();
519
+ const root = useRef5(null);
520
+ const panel = useRef5(null);
521
+ const body = useRef5(null);
522
+ const titleId = useId3();
472
523
  const { mounted, shown } = usePresence(open, root, panel);
473
524
  const scope = useDialog(shown, { root, panel, body }, onClose);
474
525
  if (!mounted) return null;
475
526
  const cls = ["ui-drawer", `ui-drawer--${side}`, `ui-drawer--${size}`, shown && "is-open"].filter(Boolean).join(" ");
476
527
  return createPortal2(
477
- /* @__PURE__ */ jsx7(DialogScope.Provider, { value: scope, children: /* @__PURE__ */ jsxs5("div", { className: cls, ref: root, children: [
478
- /* @__PURE__ */ jsx7("div", { className: "ui-drawer__scrim", onMouseDown: dismissOnScrim(onClose) }),
479
- /* @__PURE__ */ jsxs5(
528
+ /* @__PURE__ */ jsx8(DialogScope.Provider, { value: scope, children: /* @__PURE__ */ jsxs6("div", { className: cls, ref: root, children: [
529
+ /* @__PURE__ */ jsx8("div", { className: "ui-drawer__scrim", onMouseDown: dismissOnScrim(onClose) }),
530
+ /* @__PURE__ */ jsxs6(
480
531
  "aside",
481
532
  {
482
533
  className: "ui-drawer__panel",
@@ -486,12 +537,12 @@ function Drawer({
486
537
  tabIndex: -1,
487
538
  ref: panel,
488
539
  children: [
489
- /* @__PURE__ */ jsxs5("header", { className: "ui-drawer__header", children: [
490
- /* @__PURE__ */ jsx7("h2", { className: "ui-drawer__title", id: titleId, children: title }),
491
- /* @__PURE__ */ jsx7("button", { type: "button", className: "ui-drawer__close", "aria-label": closeLabel, onClick: onClose, children: /* @__PURE__ */ jsx7(Icon, { name: "x" }) })
540
+ /* @__PURE__ */ jsxs6("header", { className: "ui-drawer__header", children: [
541
+ /* @__PURE__ */ jsx8("h2", { className: "ui-drawer__title", id: titleId, children: title }),
542
+ /* @__PURE__ */ jsx8("button", { type: "button", className: "ui-drawer__close", "aria-label": closeLabel, onClick: onClose, children: /* @__PURE__ */ jsx8(Icon, { name: "x" }) })
492
543
  ] }),
493
- /* @__PURE__ */ jsx7("div", { className: "ui-drawer__body", ref: body, children }),
494
- footer && /* @__PURE__ */ jsx7("footer", { className: "ui-drawer__footer", children: footer })
544
+ /* @__PURE__ */ jsx8("div", { className: "ui-drawer__body", ref: body, children }),
545
+ footer && /* @__PURE__ */ jsx8("footer", { className: "ui-drawer__footer", children: footer })
495
546
  ]
496
547
  }
497
548
  )
@@ -501,12 +552,12 @@ function Drawer({
501
552
  }
502
553
 
503
554
  // src/CommandPalette.tsx
504
- import { useCallback, useEffect as useEffect2, useId as useId3, useMemo, useRef as useRef5, useState as useState2 } from "react";
555
+ import { useCallback, useEffect as useEffect2, useId as useId4, useMemo, useRef as useRef6, useState as useState2 } from "react";
505
556
  import { createPortal as createPortal3 } from "react-dom";
506
557
  import { rankGroups, icon as icon2 } from "@apliteni/apliteni-ui";
507
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
558
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
508
559
  var cx2 = (...a) => a.filter(Boolean).join(" ");
509
- var Glyph = ({ name, className }) => /* @__PURE__ */ jsx8("span", { className, "aria-hidden": "true", dangerouslySetInnerHTML: { __html: icon2(name) } });
560
+ var Glyph = ({ name, className }) => /* @__PURE__ */ jsx9("span", { className, "aria-hidden": "true", dangerouslySetInnerHTML: { __html: icon2(name) } });
510
561
  var keysOf = (shortcut) => shortcut == null ? [] : Array.isArray(shortcut) ? shortcut : [shortcut];
511
562
  function CommandPalette({
512
563
  open,
@@ -521,10 +572,10 @@ function CommandPalette({
521
572
  rank = true,
522
573
  onQueryChange
523
574
  }) {
524
- const uid = useId3().replace(/:/g, "");
525
- const root = useRef5(null);
526
- const panel = useRef5(null);
527
- const search = useRef5(null);
575
+ const uid = useId4().replace(/:/g, "");
576
+ const root = useRef6(null);
577
+ const panel = useRef6(null);
578
+ const search = useRef6(null);
528
579
  const [query, setQuery] = useState2("");
529
580
  const [at, setAt] = useState2(0);
530
581
  useEffect2(() => {
@@ -571,9 +622,9 @@ function CommandPalette({
571
622
  const listId = `${uid}-list`;
572
623
  let n = 0;
573
624
  return createPortal3(
574
- /* @__PURE__ */ jsx8(DialogScope.Provider, { value: scope, children: /* @__PURE__ */ jsxs6("div", { className: cx2("ui-cmdk", density === "roomy" && "ui-cmdk--roomy", "is-open"), ref: root, children: [
575
- /* @__PURE__ */ jsx8("div", { className: "ui-cmdk__scrim", onMouseDown: dismissOnScrim(onClose) }),
576
- /* @__PURE__ */ jsxs6(
625
+ /* @__PURE__ */ jsx9(DialogScope.Provider, { value: scope, children: /* @__PURE__ */ jsxs7("div", { className: cx2("ui-cmdk", density === "roomy" && "ui-cmdk--roomy", "is-open"), ref: root, children: [
626
+ /* @__PURE__ */ jsx9("div", { className: "ui-cmdk__scrim", onMouseDown: dismissOnScrim(onClose) }),
627
+ /* @__PURE__ */ jsxs7(
577
628
  "div",
578
629
  {
579
630
  className: "ui-cmdk__panel",
@@ -584,9 +635,9 @@ function CommandPalette({
584
635
  ref: panel,
585
636
  onKeyDown,
586
637
  children: [
587
- /* @__PURE__ */ jsxs6("div", { className: "ui-cmdk__search", ref: search, children: [
588
- /* @__PURE__ */ jsx8(Glyph, { name: "search", className: "ui-cmdk__search-ic" }),
589
- /* @__PURE__ */ jsx8(
638
+ /* @__PURE__ */ jsxs7("div", { className: "ui-cmdk__search", ref: search, children: [
639
+ /* @__PURE__ */ jsx9(Glyph, { name: "search", className: "ui-cmdk__search-ic" }),
640
+ /* @__PURE__ */ jsx9(
590
641
  "input",
591
642
  {
592
643
  className: "ui-cmdk__input",
@@ -608,19 +659,19 @@ function CommandPalette({
608
659
  }
609
660
  )
610
661
  ] }),
611
- /* @__PURE__ */ jsx8("div", { className: "ui-cmdk__list", id: listId, role: "listbox", "aria-label": `${label} results`, children: shown.map((group, gi) => /* @__PURE__ */ jsxs6(
662
+ /* @__PURE__ */ jsx9("div", { className: "ui-cmdk__list", id: listId, role: "listbox", "aria-label": `${label} results`, children: shown.map((group, gi) => /* @__PURE__ */ jsxs7(
612
663
  "div",
613
664
  {
614
665
  className: "ui-cmdk__group",
615
666
  role: "group",
616
667
  "aria-labelledby": group.label ? `${uid}-g${gi}` : void 0,
617
668
  children: [
618
- group.label && /* @__PURE__ */ jsx8("div", { className: "ui-cmdk__group-head", id: `${uid}-g${gi}`, children: group.label }),
669
+ group.label && /* @__PURE__ */ jsx9("div", { className: "ui-cmdk__group-head", id: `${uid}-g${gi}`, children: group.label }),
619
670
  group.items.map((item) => {
620
671
  const disabled = isDisabled(item);
621
672
  const id = `${uid}-o${n++}`;
622
673
  const on = item === active;
623
- return /* @__PURE__ */ jsxs6(
674
+ return /* @__PURE__ */ jsxs7(
624
675
  "div",
625
676
  {
626
677
  id,
@@ -640,13 +691,13 @@ function CommandPalette({
640
691
  },
641
692
  onClick: (e) => run(item, e.metaKey || e.ctrlKey),
642
693
  children: [
643
- item.icon && /* @__PURE__ */ jsx8(Glyph, { name: item.icon, className: "ui-cmdk__ic" }),
644
- /* @__PURE__ */ jsxs6("span", { className: "ui-cmdk__main", children: [
645
- /* @__PURE__ */ jsx8("span", { className: "ui-cmdk__label", children: item.label }),
646
- item.description && /* @__PURE__ */ jsx8("span", { className: "ui-cmdk__desc", children: item.description })
694
+ item.icon && /* @__PURE__ */ jsx9(Glyph, { name: item.icon, className: "ui-cmdk__ic" }),
695
+ /* @__PURE__ */ jsxs7("span", { className: "ui-cmdk__main", children: [
696
+ /* @__PURE__ */ jsx9("span", { className: "ui-cmdk__label", children: item.label }),
697
+ item.description && /* @__PURE__ */ jsx9("span", { className: "ui-cmdk__desc", children: item.description })
647
698
  ] }),
648
- item.badge && /* @__PURE__ */ jsx8("span", { className: "ui-cmdk__badge", children: item.badge }),
649
- keysOf(item.shortcut).length > 0 && /* @__PURE__ */ jsx8("span", { className: "ui-cmdk__keys", "aria-hidden": "true", children: keysOf(item.shortcut).map((k) => /* @__PURE__ */ jsx8("kbd", { className: "ui-cmdk__key", children: k }, k)) })
699
+ item.badge && /* @__PURE__ */ jsx9("span", { className: "ui-cmdk__badge", children: item.badge }),
700
+ keysOf(item.shortcut).length > 0 && /* @__PURE__ */ jsx9("span", { className: "ui-cmdk__keys", "aria-hidden": "true", children: keysOf(item.shortcut).map((k) => /* @__PURE__ */ jsx9("kbd", { className: "ui-cmdk__key", children: k }, k)) })
650
701
  ]
651
702
  },
652
703
  item.id
@@ -656,20 +707,20 @@ function CommandPalette({
656
707
  },
657
708
  group.label ?? `g${gi}`
658
709
  )) }),
659
- /* @__PURE__ */ jsx8("p", { className: "ui-cmdk__empty", hidden: countOf(shown) > 0, children: empty }),
660
- /* @__PURE__ */ jsx8("p", { className: "ui-sr", role: "status", "aria-live": "polite", children: countOf(shown) === 0 ? "No results" : `${countOf(shown)} result${countOf(shown) === 1 ? "" : "s"}` }),
661
- hint && /* @__PURE__ */ jsxs6("div", { className: "ui-cmdk__foot", "aria-hidden": "true", children: [
662
- /* @__PURE__ */ jsxs6("span", { children: [
663
- /* @__PURE__ */ jsx8("kbd", { className: "ui-cmdk__key", children: "\u2191" }),
664
- /* @__PURE__ */ jsx8("kbd", { className: "ui-cmdk__key", children: "\u2193" }),
710
+ /* @__PURE__ */ jsx9("p", { className: "ui-cmdk__empty", hidden: countOf(shown) > 0, children: empty }),
711
+ /* @__PURE__ */ jsx9("p", { className: "ui-sr", role: "status", "aria-live": "polite", children: countOf(shown) === 0 ? "No results" : `${countOf(shown)} result${countOf(shown) === 1 ? "" : "s"}` }),
712
+ hint && /* @__PURE__ */ jsxs7("div", { className: "ui-cmdk__foot", "aria-hidden": "true", children: [
713
+ /* @__PURE__ */ jsxs7("span", { children: [
714
+ /* @__PURE__ */ jsx9("kbd", { className: "ui-cmdk__key", children: "\u2191" }),
715
+ /* @__PURE__ */ jsx9("kbd", { className: "ui-cmdk__key", children: "\u2193" }),
665
716
  " move"
666
717
  ] }),
667
- /* @__PURE__ */ jsxs6("span", { children: [
668
- /* @__PURE__ */ jsx8("kbd", { className: "ui-cmdk__key", children: "\u21B5" }),
718
+ /* @__PURE__ */ jsxs7("span", { children: [
719
+ /* @__PURE__ */ jsx9("kbd", { className: "ui-cmdk__key", children: "\u21B5" }),
669
720
  " run"
670
721
  ] }),
671
- /* @__PURE__ */ jsxs6("span", { children: [
672
- /* @__PURE__ */ jsx8("kbd", { className: "ui-cmdk__key", children: "esc" }),
722
+ /* @__PURE__ */ jsxs7("span", { children: [
723
+ /* @__PURE__ */ jsx9("kbd", { className: "ui-cmdk__key", children: "esc" }),
673
724
  " close"
674
725
  ] })
675
726
  ] })
@@ -698,9 +749,9 @@ import { useMemo as useMemo2, useState as useState4 } from "react";
698
749
  import { DEFAULT_PAGE_SIZE as DEFAULT_PAGE_SIZE2 } from "@apliteni/apliteni-ui";
699
750
 
700
751
  // src/Pagination.tsx
701
- import { useEffect as useEffect3, useId as useId4, useRef as useRef6, useState as useState3 } from "react";
752
+ import { useEffect as useEffect3, useId as useId5, useRef as useRef7, useState as useState3 } from "react";
702
753
  import { DEFAULT_PAGE_SIZE } from "@apliteni/apliteni-ui";
703
- import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
754
+ import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
704
755
  var GHOST_SM = "ui-btn ui-btn--ghost ui-btn--sm";
705
756
  var VARIANTS = ["steps", "numbered", "jump"];
706
757
  var cx3 = (...a) => a.filter(Boolean).join(" ");
@@ -742,11 +793,11 @@ function Pagination({
742
793
  onPageChange,
743
794
  onPageSizeChange
744
795
  }) {
745
- const auto = useId4();
796
+ const auto = useId5();
746
797
  const [draft, setDraft] = useState3("");
747
798
  const [drafting, setDrafting] = useState3(false);
748
- const nav = useRef6(null);
749
- const pressed = useRef6(null);
799
+ const nav = useRef7(null);
800
+ const pressed = useRef7(null);
750
801
  const uid = id ?? auto;
751
802
  const kind = VARIANTS.includes(variant) ? variant : "steps";
752
803
  const size = sizeOf(pageSize, DEFAULT_PAGE_SIZE);
@@ -792,7 +843,7 @@ function Pagination({
792
843
  const step = (label_, target, disabled) => (
793
844
  // A control at an end is disabled and stays where it is: removing it slides
794
845
  // the next control under a pointer already travelling toward it.
795
- /* @__PURE__ */ jsx9(
846
+ /* @__PURE__ */ jsx10(
796
847
  "button",
797
848
  {
798
849
  type: "button",
@@ -831,14 +882,14 @@ function Pagination({
831
882
  if (single) {
832
883
  steps = null;
833
884
  } else if (!counted) {
834
- steps = /* @__PURE__ */ jsxs7("div", { className: "ui-pager__steps", children: [
885
+ steps = /* @__PURE__ */ jsxs8("div", { className: "ui-pager__steps", children: [
835
886
  step("Prev", Math.max(1, at - 1), atStart),
836
887
  step("Next", at + 1, !hasMore)
837
888
  ] });
838
889
  } else {
839
890
  let middle = null;
840
891
  if (kind === "numbered") {
841
- middle = slotsFor(at, last).map((n, i) => n == null ? /* @__PURE__ */ jsx9("span", { className: "ui-pager__gap", "aria-hidden": "true", children: "\u2026" }, `gap${i}`) : /* @__PURE__ */ jsx9(
892
+ middle = slotsFor(at, last).map((n, i) => n == null ? /* @__PURE__ */ jsx10("span", { className: "ui-pager__gap", "aria-hidden": "true", children: "\u2026" }, `gap${i}`) : /* @__PURE__ */ jsx10(
842
893
  "button",
843
894
  {
844
895
  type: "button",
@@ -853,9 +904,9 @@ function Pagination({
853
904
  n
854
905
  ));
855
906
  } else if (kind === "jump") {
856
- middle = /* @__PURE__ */ jsxs7("span", { className: "ui-pager__jump", children: [
857
- /* @__PURE__ */ jsx9("label", { htmlFor: `${uid}-jump`, children: "Page" }),
858
- /* @__PURE__ */ jsx9(
907
+ middle = /* @__PURE__ */ jsxs8("span", { className: "ui-pager__jump", children: [
908
+ /* @__PURE__ */ jsx10("label", { htmlFor: `${uid}-jump`, children: "Page" }),
909
+ /* @__PURE__ */ jsx10(
859
910
  "input",
860
911
  {
861
912
  className: "ui-input ui-pager__jump-input",
@@ -878,13 +929,13 @@ function Pagination({
878
929
  }
879
930
  }
880
931
  ),
881
- /* @__PURE__ */ jsxs7("span", { className: "ui-pager__jump-of", children: [
932
+ /* @__PURE__ */ jsxs8("span", { className: "ui-pager__jump-of", children: [
882
933
  "of ",
883
934
  fmt(last)
884
935
  ] })
885
936
  ] });
886
937
  }
887
- steps = /* @__PURE__ */ jsxs7("div", { className: "ui-pager__steps", children: [
938
+ steps = /* @__PURE__ */ jsxs8("div", { className: "ui-pager__steps", children: [
888
939
  ends ? step("First", 1, atStart) : null,
889
940
  step("Prev", Math.max(1, at - 1), atStart),
890
941
  middle,
@@ -892,7 +943,7 @@ function Pagination({
892
943
  ends ? step("Last", last, atEnd) : null
893
944
  ] });
894
945
  }
895
- return /* @__PURE__ */ jsxs7(
946
+ return /* @__PURE__ */ jsxs8(
896
947
  "nav",
897
948
  {
898
949
  ref: nav,
@@ -900,10 +951,10 @@ function Pagination({
900
951
  "aria-label": label,
901
952
  "aria-busy": loading ? true : void 0,
902
953
  children: [
903
- /* @__PURE__ */ jsx9("p", { className: "ui-pager__status", "aria-live": "polite", "aria-atomic": "true", children: status }),
904
- sizes.length ? /* @__PURE__ */ jsxs7("div", { className: "ui-pager__size", children: [
905
- /* @__PURE__ */ jsx9("label", { className: "ui-pager__size-label", htmlFor: `${uid}-size`, children: "Rows" }),
906
- /* @__PURE__ */ jsx9(
954
+ /* @__PURE__ */ jsx10("p", { className: "ui-pager__status", "aria-live": "polite", "aria-atomic": "true", children: status }),
955
+ sizes.length ? /* @__PURE__ */ jsxs8("div", { className: "ui-pager__size", children: [
956
+ /* @__PURE__ */ jsx10("label", { className: "ui-pager__size-label", htmlFor: `${uid}-size`, children: "Rows" }),
957
+ /* @__PURE__ */ jsx10(
907
958
  "select",
908
959
  {
909
960
  className: "ui-select ui-pager__size-select",
@@ -911,7 +962,7 @@ function Pagination({
911
962
  disabled: loading,
912
963
  value: size,
913
964
  onChange: (e) => onPageSizeChange?.(Number(e.target.value)),
914
- children: sizes.map((s) => /* @__PURE__ */ jsx9("option", { value: s, children: fmt(s) }, s))
965
+ children: sizes.map((s) => /* @__PURE__ */ jsx10("option", { value: s, children: fmt(s) }, s))
915
966
  }
916
967
  )
917
968
  ] }) : null,
@@ -922,7 +973,7 @@ function Pagination({
922
973
  }
923
974
 
924
975
  // src/DataTable.tsx
925
- import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
976
+ import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
926
977
  var NO_SORT = { key: void 0, dir: -1 };
927
978
  function sortTableRows(rows, sort) {
928
979
  if (sort.key === void 0) return [...rows];
@@ -989,7 +1040,7 @@ function DataTable({
989
1040
  onSortChange?.(next);
990
1041
  toFirstPage();
991
1042
  };
992
- const caret = (k) => /* @__PURE__ */ jsx10(
1043
+ const caret = (k) => /* @__PURE__ */ jsx11(
993
1044
  "svg",
994
1045
  {
995
1046
  className: "rx-caret",
@@ -1001,29 +1052,29 @@ function DataTable({
1001
1052
  strokeLinejoin: "round",
1002
1053
  "aria-hidden": "true",
1003
1054
  focusable: "false",
1004
- children: sort.key === k ? /* @__PURE__ */ jsx10("path", { d: "m8 10 4 4 4-4" }) : /* @__PURE__ */ jsxs8(Fragment2, { children: [
1005
- /* @__PURE__ */ jsx10("path", { d: "m8 9 4-4 4 4" }),
1006
- /* @__PURE__ */ jsx10("path", { d: "m8 15 4 4 4-4" })
1055
+ children: sort.key === k ? /* @__PURE__ */ jsx11("path", { d: "m8 10 4 4 4-4" }) : /* @__PURE__ */ jsxs9(Fragment3, { children: [
1056
+ /* @__PURE__ */ jsx11("path", { d: "m8 9 4-4 4 4" }),
1057
+ /* @__PURE__ */ jsx11("path", { d: "m8 15 4 4 4-4" })
1007
1058
  ] })
1008
1059
  }
1009
1060
  );
1010
1061
  const pageAllOn = selectable && slice.length > 0 && slice.every((r) => selected.has(r.name));
1011
- return /* @__PURE__ */ jsxs8(Fragment2, { children: [
1012
- /* @__PURE__ */ jsx10(
1062
+ return /* @__PURE__ */ jsxs9(Fragment3, { children: [
1063
+ /* @__PURE__ */ jsx11(
1013
1064
  "div",
1014
1065
  {
1015
1066
  className: stickyHeader || pinnedIdentity ? "ui-table-scroll" : void 0,
1016
1067
  role: stickyHeader || pinnedIdentity ? "region" : void 0,
1017
1068
  "aria-label": stickyHeader || pinnedIdentity ? scrollLabel : void 0,
1018
1069
  tabIndex: stickyHeader || pinnedIdentity ? 0 : void 0,
1019
- children: /* @__PURE__ */ jsxs8(
1070
+ children: /* @__PURE__ */ jsxs9(
1020
1071
  "table",
1021
1072
  {
1022
1073
  className: ["ui-table ui-table--hover", (density === "dense" || !density && dense) && "ui-table--dense", density === "compact" && "ui-table--compact", stickyHeader && "ui-table--sticky", pinnedIdentity && "ui-table--pinned"].filter(Boolean).join(" "),
1023
1074
  "aria-busy": loading || void 0,
1024
1075
  children: [
1025
- /* @__PURE__ */ jsx10("thead", { children: /* @__PURE__ */ jsxs8("tr", { children: [
1026
- selectable ? /* @__PURE__ */ jsx10("th", { scope: "col", className: "ui-table__selection", children: /* @__PURE__ */ jsx10(
1076
+ /* @__PURE__ */ jsx11("thead", { children: /* @__PURE__ */ jsxs9("tr", { children: [
1077
+ selectable ? /* @__PURE__ */ jsx11("th", { scope: "col", className: "ui-table__selection", children: /* @__PURE__ */ jsx11(
1027
1078
  "input",
1028
1079
  {
1029
1080
  type: "checkbox",
@@ -1036,13 +1087,13 @@ function DataTable({
1036
1087
  // The sort control is a real <button> inside the header cell. It used to be
1037
1088
  // role="button" ON the <th>, which threw away the columnheader role and put
1038
1089
  // aria-sort on a role that forbids it.
1039
- /* @__PURE__ */ jsx10(
1090
+ /* @__PURE__ */ jsx11(
1040
1091
  "th",
1041
1092
  {
1042
1093
  scope: "col",
1043
1094
  className: [pinnedIdentity && columnIndex === 0 && "ui-table__identity", c.num && "ui-table__num", c.sortable && "rx-sortable"].filter(Boolean).join(" "),
1044
1095
  "aria-sort": sort.key === c.key ? sort.dir === 1 ? "ascending" : "descending" : c.sortable && sortIsKnown ? "none" : void 0,
1045
- children: c.sortable ? /* @__PURE__ */ jsxs8("button", { type: "button", className: "rx-sort", onClick: () => onSort(c.key), children: [
1096
+ children: c.sortable ? /* @__PURE__ */ jsxs9("button", { type: "button", className: "rx-sort", onClick: () => onSort(c.key), children: [
1046
1097
  c.label,
1047
1098
  caret(c.key)
1048
1099
  ] }) : c.label
@@ -1051,10 +1102,10 @@ function DataTable({
1051
1102
  )
1052
1103
  ))
1053
1104
  ] }) }),
1054
- /* @__PURE__ */ jsxs8("tbody", { children: [
1055
- !slice.length && /* @__PURE__ */ jsx10("tr", { children: /* @__PURE__ */ jsx10("td", { colSpan: columns.length + (selectable ? 1 : 0), children: loading ? "Loading rows\u2026" : empty }) }),
1056
- slice.map((r) => /* @__PURE__ */ jsxs8("tr", { children: [
1057
- selectable ? /* @__PURE__ */ jsx10("td", { className: "ui-table__selection", children: /* @__PURE__ */ jsx10(
1105
+ /* @__PURE__ */ jsxs9("tbody", { children: [
1106
+ !slice.length && /* @__PURE__ */ jsx11("tr", { children: /* @__PURE__ */ jsx11("td", { colSpan: columns.length + (selectable ? 1 : 0), children: loading ? "Loading rows\u2026" : empty }) }),
1107
+ slice.map((r) => /* @__PURE__ */ jsxs9("tr", { children: [
1108
+ selectable ? /* @__PURE__ */ jsx11("td", { className: "ui-table__selection", children: /* @__PURE__ */ jsx11(
1058
1109
  "input",
1059
1110
  {
1060
1111
  type: "checkbox",
@@ -1063,7 +1114,7 @@ function DataTable({
1063
1114
  onChange: () => onToggle(r.name)
1064
1115
  }
1065
1116
  ) }) : null,
1066
- columns.map((c, columnIndex) => /* @__PURE__ */ jsx10("td", { className: [c.num && "ui-table__num", pinnedIdentity && columnIndex === 0 && "ui-table__identity"].filter(Boolean).join(" "), children: c.render ? c.render(r) : String(r[c.key]) }, c.key))
1117
+ columns.map((c, columnIndex) => /* @__PURE__ */ jsx11("td", { className: [c.num && "ui-table__num", pinnedIdentity && columnIndex === 0 && "ui-table__identity"].filter(Boolean).join(" "), children: c.render ? c.render(r) : String(r[c.key]) }, c.key))
1067
1118
  ] }, r.name))
1068
1119
  ] })
1069
1120
  ]
@@ -1071,7 +1122,7 @@ function DataTable({
1071
1122
  )
1072
1123
  }
1073
1124
  ),
1074
- pager ? /* @__PURE__ */ jsx10(
1125
+ pager ? /* @__PURE__ */ jsx11(
1075
1126
  Pagination,
1076
1127
  {
1077
1128
  page,
@@ -1096,7 +1147,7 @@ function DataTable({
1096
1147
  import { PAGE_SIZES as KIT_PAGE_SIZES, DEFAULT_PAGE_SIZE as KIT_DEFAULT_PAGE_SIZE } from "@apliteni/apliteni-ui";
1097
1148
 
1098
1149
  // src/Loading.tsx
1099
- import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
1150
+ import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
1100
1151
  var cx4 = (...a) => a.filter(Boolean).join(" ");
1101
1152
  function Skeleton({ lines = 3, width, height, radius, className }) {
1102
1153
  const widths = Array.isArray(lines) ? lines : null;
@@ -1106,19 +1157,19 @@ function Skeleton({ lines = 3, width, height, radius, className }) {
1106
1157
  if (!w && !height && !radius) return void 0;
1107
1158
  return { ...w && { width: w }, ...height && { height }, ...radius && { borderRadius: radius } };
1108
1159
  };
1109
- return /* @__PURE__ */ jsx11("div", { className: cx4("ui-skel", className), "aria-hidden": "true", children: Array.from({ length: n }, (_, i) => /* @__PURE__ */ jsx11("span", { className: "ui-skel__bar m-skeleton", style: styleFor(i) }, i)) });
1160
+ return /* @__PURE__ */ jsx12("div", { className: cx4("ui-skel", className), "aria-hidden": "true", children: Array.from({ length: n }, (_, i) => /* @__PURE__ */ jsx12("span", { className: "ui-skel__bar m-skeleton", style: styleFor(i) }, i)) });
1110
1161
  }
1111
1162
  function SkeletonTable({ rows = 5, cols = 4, head = true }) {
1112
- const cells = Array.from({ length: Math.max(1, cols) }, (_, i) => /* @__PURE__ */ jsx11("span", { className: "ui-skel__bar m-skeleton" }, i));
1113
- return /* @__PURE__ */ jsxs9(
1163
+ const cells = Array.from({ length: Math.max(1, cols) }, (_, i) => /* @__PURE__ */ jsx12("span", { className: "ui-skel__bar m-skeleton" }, i));
1164
+ return /* @__PURE__ */ jsxs10(
1114
1165
  "div",
1115
1166
  {
1116
1167
  className: "ui-skel ui-skel--table",
1117
1168
  style: { "--skel-cols": Math.max(1, cols) },
1118
1169
  "aria-hidden": "true",
1119
1170
  children: [
1120
- head && /* @__PURE__ */ jsx11("div", { className: "ui-skel__row ui-skel__row--head", children: cells }),
1121
- Array.from({ length: Math.max(1, rows) }, (_, i) => /* @__PURE__ */ jsx11("div", { className: "ui-skel__row", children: cells }, i))
1171
+ head && /* @__PURE__ */ jsx12("div", { className: "ui-skel__row ui-skel__row--head", children: cells }),
1172
+ Array.from({ length: Math.max(1, rows) }, (_, i) => /* @__PURE__ */ jsx12("div", { className: "ui-skel__row", children: cells }, i))
1122
1173
  ]
1123
1174
  }
1124
1175
  );
@@ -1131,7 +1182,7 @@ function BusyRegion({
1131
1182
  className,
1132
1183
  children
1133
1184
  }) {
1134
- return /* @__PURE__ */ jsxs9(
1185
+ return /* @__PURE__ */ jsxs10(
1135
1186
  "div",
1136
1187
  {
1137
1188
  className: cx4("ui-busy", className),
@@ -1139,8 +1190,8 @@ function BusyRegion({
1139
1190
  "aria-live": "polite",
1140
1191
  "aria-busy": busy,
1141
1192
  children: [
1142
- /* @__PURE__ */ jsx11("span", { className: "ui-sr", children: busy ? label : message }),
1143
- /* @__PURE__ */ jsx11("div", { className: "ui-busy__body", children: busy ? placeholder ?? /* @__PURE__ */ jsx11(Skeleton, { lines: 3 }) : children })
1193
+ /* @__PURE__ */ jsx12("span", { className: "ui-sr", children: busy ? label : message }),
1194
+ /* @__PURE__ */ jsx12("div", { className: "ui-busy__body", children: busy ? placeholder ?? /* @__PURE__ */ jsx12(Skeleton, { lines: 3 }) : children })
1144
1195
  ]
1145
1196
  }
1146
1197
  );
@@ -1153,32 +1204,32 @@ function Denied({
1153
1204
  className,
1154
1205
  children
1155
1206
  }) {
1156
- return /* @__PURE__ */ jsxs9("div", { className: cx4("ui-denied", className), children: [
1157
- /* @__PURE__ */ jsx11("div", { className: "ui-denied__seal", children: /* @__PURE__ */ jsx11(Icon, { name: icon4 }) }),
1158
- /* @__PURE__ */ jsx11("div", { className: "ui-denied__title", children: title }),
1159
- sub && /* @__PURE__ */ jsx11("div", { className: "ui-denied__sub", children: sub }),
1160
- need && /* @__PURE__ */ jsxs9("div", { className: "ui-denied__need", children: [
1207
+ return /* @__PURE__ */ jsxs10("div", { className: cx4("ui-denied", className), children: [
1208
+ /* @__PURE__ */ jsx12("div", { className: "ui-denied__seal", children: /* @__PURE__ */ jsx12(Icon, { name: icon4 }) }),
1209
+ /* @__PURE__ */ jsx12("div", { className: "ui-denied__title", children: title }),
1210
+ sub && /* @__PURE__ */ jsx12("div", { className: "ui-denied__sub", children: sub }),
1211
+ need && /* @__PURE__ */ jsxs10("div", { className: "ui-denied__need", children: [
1161
1212
  "Needs ",
1162
- /* @__PURE__ */ jsx11("code", { className: "ui-code", children: need })
1213
+ /* @__PURE__ */ jsx12("code", { className: "ui-code", children: need })
1163
1214
  ] }),
1164
- children && /* @__PURE__ */ jsx11("div", { className: "ui-denied__actions", children })
1215
+ children && /* @__PURE__ */ jsx12("div", { className: "ui-denied__actions", children })
1165
1216
  ] });
1166
1217
  }
1167
1218
 
1168
1219
  // src/Dropdown.tsx
1169
1220
  import {
1170
- Fragment as Fragment3,
1221
+ Fragment as Fragment4,
1171
1222
  useCallback as useCallback2,
1172
1223
  useEffect as useEffect4,
1173
- useId as useId5,
1174
- useRef as useRef7,
1224
+ useId as useId6,
1225
+ useRef as useRef8,
1175
1226
  useState as useState5
1176
1227
  } from "react";
1177
1228
  import { icon as icon3, dropdownMatch, dropdownFiltering } from "@apliteni/apliteni-ui";
1178
- import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
1229
+ import { Fragment as Fragment5, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
1179
1230
  var cx5 = (...a) => a.filter(Boolean).join(" ");
1180
1231
  var isRow = (it) => Boolean(it) && it !== "---" && !it.separator;
1181
- var Glyph2 = ({ name, className, hidden }) => /* @__PURE__ */ jsx12(
1232
+ var Glyph2 = ({ name, className, hidden }) => /* @__PURE__ */ jsx13(
1182
1233
  "span",
1183
1234
  {
1184
1235
  className,
@@ -1191,7 +1242,7 @@ function RowBadge({ badge }) {
1191
1242
  const given = typeof badge === "string" ? "" : badge.tone || "";
1192
1243
  let tone = given || (/^live$/i.test(String(text2)) ? "live" : "neutral");
1193
1244
  if (!given && tone === "neutral" && /^(?:off|unset|disabled|archive|archived)$/i.test(text2)) tone = "state";
1194
- return /* @__PURE__ */ jsx12("span", { className: `ui-dropdown__badge is-${tone}`, children: text2 });
1245
+ return /* @__PURE__ */ jsx13("span", { className: `ui-dropdown__badge is-${tone}`, children: text2 });
1195
1246
  }
1196
1247
  var keyOf = (it) => it.value != null ? `v:${it.value}` : `l:${it.label}`;
1197
1248
  var itemsIn = (panel) => Array.from(panel?.querySelectorAll("[data-dd-item]") ?? []).filter((el) => el.getAttribute("aria-disabled") !== "true" && !el.hidden);
@@ -1232,19 +1283,19 @@ function Dropdown({
1232
1283
  const [pick, setPick] = useState5(null);
1233
1284
  const [query, setQuery] = useState5(() => search && search !== true ? search.query || "" : "");
1234
1285
  const [activeKey, setActiveKey] = useState5(null);
1235
- const root = useRef7(null);
1236
- const panel = useRef7(null);
1237
- const trigger = useRef7(null);
1238
- const field = useRef7(null);
1239
- const landOn = useRef7(null);
1240
- const at = useRef7("");
1241
- const auto = useId5().replace(/:/g, "");
1286
+ const root = useRef8(null);
1287
+ const panel = useRef8(null);
1288
+ const trigger = useRef8(null);
1289
+ const field = useRef8(null);
1290
+ const landOn = useRef8(null);
1291
+ const at = useRef8("");
1292
+ const auto = useId6().replace(/:/g, "");
1242
1293
  const uid = id ?? auto;
1243
1294
  const setOpen = useCallback2((next) => {
1244
1295
  if (openProp === void 0) setSelfOpen(next);
1245
1296
  onOpenChange?.(next);
1246
1297
  }, [openProp, onOpenChange]);
1247
- const close = useRef7(setOpen);
1298
+ const close = useRef8(setOpen);
1248
1299
  useIsoLayoutEffect(() => {
1249
1300
  close.current = setOpen;
1250
1301
  });
@@ -1406,7 +1457,7 @@ function Dropdown({
1406
1457
  };
1407
1458
  function renderRow(entry, key) {
1408
1459
  if (!isRow(entry)) {
1409
- return /* @__PURE__ */ jsx12("div", { className: "ui-dropdown__sep", role: "separator", hidden: filtering || void 0 }, key);
1460
+ return /* @__PURE__ */ jsx13("div", { className: "ui-dropdown__sep", role: "separator", hidden: filtering || void 0 }, key);
1410
1461
  }
1411
1462
  const disabled = !!entry.disabled;
1412
1463
  const selected = selectedOf(entry);
@@ -1428,23 +1479,23 @@ function Dropdown({
1428
1479
  ...asLink ? { href: entry.href, ...entry.target ? { target: entry.target } : null } : null,
1429
1480
  ...sx ? { id: rowIds.get(entry), hidden: hiddenBy(entry) || void 0 } : null,
1430
1481
  onClick: (e) => choose(entry, e),
1431
- children: /* @__PURE__ */ jsxs10(Fragment4, { children: [
1432
- entry.icon && /* @__PURE__ */ jsx12(Glyph2, { name: entry.icon, className: "ui-dropdown__ic" }),
1433
- /* @__PURE__ */ jsxs10("span", { className: "ui-dropdown__main", children: [
1434
- /* @__PURE__ */ jsx12("span", { className: "ui-dropdown__label", children: entry.label }),
1435
- entry.description && /* @__PURE__ */ jsx12("span", { className: "ui-dropdown__desc", children: entry.description })
1482
+ children: /* @__PURE__ */ jsxs11(Fragment5, { children: [
1483
+ entry.icon && /* @__PURE__ */ jsx13(Glyph2, { name: entry.icon, className: "ui-dropdown__ic" }),
1484
+ /* @__PURE__ */ jsxs11("span", { className: "ui-dropdown__main", children: [
1485
+ /* @__PURE__ */ jsx13("span", { className: "ui-dropdown__label", children: entry.label }),
1486
+ entry.description && /* @__PURE__ */ jsx13("span", { className: "ui-dropdown__desc", children: entry.description })
1436
1487
  ] }),
1437
- entry.badge ? /* @__PURE__ */ jsx12(RowBadge, { badge: entry.badge }) : null,
1438
- asOption && /* @__PURE__ */ jsx12(Glyph2, { name: "check", className: "ui-dropdown__tick", hidden: true })
1488
+ entry.badge ? /* @__PURE__ */ jsx13(RowBadge, { badge: entry.badge }) : null,
1489
+ asOption && /* @__PURE__ */ jsx13(Glyph2, { name: "check", className: "ui-dropdown__tick", hidden: true })
1439
1490
  ] })
1440
1491
  };
1441
- if (row) return /* @__PURE__ */ jsx12(Fragment3, { children: row(entry, props) }, key);
1492
+ if (row) return /* @__PURE__ */ jsx13(Fragment4, { children: row(entry, props) }, key);
1442
1493
  const Tag = asLink ? "a" : "div";
1443
- return /* @__PURE__ */ jsx12(Tag, { ...props }, key);
1494
+ return /* @__PURE__ */ jsx13(Tag, { ...props }, key);
1444
1495
  }
1445
1496
  const body = sections?.length ? sections.map((section, si) => {
1446
1497
  const gone = filtering && !(section.items || []).some((it) => isRow(it) && !hiddenBy(it));
1447
- return /* @__PURE__ */ jsxs10(
1498
+ return /* @__PURE__ */ jsxs11(
1448
1499
  "div",
1449
1500
  {
1450
1501
  className: "ui-dropdown__section",
@@ -1452,7 +1503,7 @@ function Dropdown({
1452
1503
  "aria-label": section.label || void 0,
1453
1504
  hidden: gone || void 0,
1454
1505
  children: [
1455
- section.label && /* @__PURE__ */ jsx12("div", { className: "ui-dropdown__group", role: "presentation", children: section.label }),
1506
+ section.label && /* @__PURE__ */ jsx13("div", { className: "ui-dropdown__group", role: "presentation", children: section.label }),
1456
1507
  (section.items || []).map((entry, i) => renderRow(entry, `s${si}-${i}`))
1457
1508
  ]
1458
1509
  },
@@ -1460,12 +1511,12 @@ function Dropdown({
1460
1511
  );
1461
1512
  }) : (items || []).map((entry, i) => renderRow(entry, `i${i}`));
1462
1513
  const cap = scroll && scroll !== true ? { maxHeight: typeof scroll === "number" ? `${scroll}px` : scroll } : void 0;
1463
- const none = sx && filtering && !visible.length ? /* @__PURE__ */ jsxs10(Fragment4, { children: [
1464
- /* @__PURE__ */ jsx12("span", { className: "ui-dropdown__none-title", children: sx.empty.replace("{q}", () => query.trim()) }),
1465
- /* @__PURE__ */ jsx12("span", { className: "ui-dropdown__none-hint", children: sx.hint })
1514
+ const none = sx && filtering && !visible.length ? /* @__PURE__ */ jsxs11(Fragment5, { children: [
1515
+ /* @__PURE__ */ jsx13("span", { className: "ui-dropdown__none-title", children: sx.empty.replace("{q}", () => query.trim()) }),
1516
+ /* @__PURE__ */ jsx13("span", { className: "ui-dropdown__none-hint", children: sx.hint })
1466
1517
  ] }) : null;
1467
- return /* @__PURE__ */ jsxs10("div", { className: cx5("ui-dropdown", open && "open"), id, ref: root, onKeyDown, children: [
1468
- /* @__PURE__ */ jsxs10(
1518
+ return /* @__PURE__ */ jsxs11("div", { className: cx5("ui-dropdown", open && "open"), id, ref: root, onKeyDown, children: [
1519
+ /* @__PURE__ */ jsxs11(
1469
1520
  "button",
1470
1521
  {
1471
1522
  type: "button",
@@ -1480,15 +1531,15 @@ function Dropdown({
1480
1531
  setOpen(!open);
1481
1532
  },
1482
1533
  children: [
1483
- triggerContent != null ? triggerContent : /* @__PURE__ */ jsxs10(Fragment4, { children: [
1484
- label && /* @__PURE__ */ jsx12("span", { className: "ui-dropdown__pre", children: label }),
1485
- /* @__PURE__ */ jsx12("span", { className: "ui-dropdown__value", children: shown != null ? shown : placeholder })
1534
+ triggerContent != null ? triggerContent : /* @__PURE__ */ jsxs11(Fragment5, { children: [
1535
+ label && /* @__PURE__ */ jsx13("span", { className: "ui-dropdown__pre", children: label }),
1536
+ /* @__PURE__ */ jsx13("span", { className: "ui-dropdown__value", children: shown != null ? shown : placeholder })
1486
1537
  ] }),
1487
- chevron && /* @__PURE__ */ jsx12("span", { className: "ui-dropdown__chevron", "aria-hidden": "true" })
1538
+ chevron && /* @__PURE__ */ jsx13("span", { className: "ui-dropdown__chevron", "aria-hidden": "true" })
1488
1539
  ]
1489
1540
  }
1490
1541
  ),
1491
- /* @__PURE__ */ jsxs10(
1542
+ /* @__PURE__ */ jsxs11(
1492
1543
  "div",
1493
1544
  {
1494
1545
  className: cx5(
@@ -1508,10 +1559,10 @@ function Dropdown({
1508
1559
  onMouseMove,
1509
1560
  children: [
1510
1561
  header,
1511
- sx ? /* @__PURE__ */ jsxs10(Fragment4, { children: [
1512
- /* @__PURE__ */ jsxs10("div", { className: "ui-dropdown__search", children: [
1513
- /* @__PURE__ */ jsx12(Glyph2, { name: "search", className: "ui-dropdown__search-ic", hidden: true }),
1514
- /* @__PURE__ */ jsx12(
1562
+ sx ? /* @__PURE__ */ jsxs11(Fragment5, { children: [
1563
+ /* @__PURE__ */ jsxs11("div", { className: "ui-dropdown__search", children: [
1564
+ /* @__PURE__ */ jsx13(Glyph2, { name: "search", className: "ui-dropdown__search-ic", hidden: true }),
1565
+ /* @__PURE__ */ jsx13(
1515
1566
  "input",
1516
1567
  {
1517
1568
  className: "ui-dropdown__search-input",
@@ -1535,8 +1586,8 @@ function Dropdown({
1535
1586
  }
1536
1587
  )
1537
1588
  ] }),
1538
- /* @__PURE__ */ jsx12("div", { className: "ui-dropdown__list", role: "listbox", id: listId, "aria-label": name, style: cap, children: body }),
1539
- /* @__PURE__ */ jsx12(
1589
+ /* @__PURE__ */ jsx13("div", { className: "ui-dropdown__list", role: "listbox", id: listId, "aria-label": name, style: cap, children: body }),
1590
+ /* @__PURE__ */ jsx13(
1540
1591
  "div",
1541
1592
  {
1542
1593
  className: "ui-dropdown__none",
@@ -1561,7 +1612,7 @@ function strip(o) {
1561
1612
  }
1562
1613
 
1563
1614
  // src/BackLink.tsx
1564
- import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
1615
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
1565
1616
  var BARE = "Back";
1566
1617
  var SCRIPTED = /^javascript:/i;
1567
1618
  var LEADING = /^[\u0000-\u0020]+/;
@@ -1580,7 +1631,7 @@ function BackLink({
1580
1631
  const name = text(label).replace(SAID, "");
1581
1632
  const bare = !name || name.toLowerCase() === BARE.toLowerCase();
1582
1633
  const Tag = as ?? "a";
1583
- return /* @__PURE__ */ jsxs11(
1634
+ return /* @__PURE__ */ jsxs12(
1584
1635
  Tag,
1585
1636
  {
1586
1637
  className: ["ui-back", className].filter(Boolean).join(" "),
@@ -1588,8 +1639,8 @@ function BackLink({
1588
1639
  "aria-label": bare ? void 0 : `${BARE} to ${name}`,
1589
1640
  ...rest,
1590
1641
  children: [
1591
- /* @__PURE__ */ jsx13(Icon, { name: "chevronLeft" }),
1592
- /* @__PURE__ */ jsx13("span", { className: "ui-back__label", children: bare ? BARE : name })
1642
+ /* @__PURE__ */ jsx14(Icon, { name: "chevronLeft" }),
1643
+ /* @__PURE__ */ jsx14("span", { className: "ui-back__label", children: bare ? BARE : name })
1593
1644
  ]
1594
1645
  }
1595
1646
  );
@@ -1597,36 +1648,36 @@ function BackLink({
1597
1648
 
1598
1649
  // src/TableValues.tsx
1599
1650
  import { numericValue, deltaValue } from "@apliteni/apliteni-ui";
1600
- import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
1651
+ import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
1601
1652
  function NumericValue(props) {
1602
- return /* @__PURE__ */ jsx14("span", { dangerouslySetInnerHTML: { __html: numericValue(props) } });
1653
+ return /* @__PURE__ */ jsx15("span", { dangerouslySetInnerHTML: { __html: numericValue(props) } });
1603
1654
  }
1604
1655
  function DeltaValue(props) {
1605
- return /* @__PURE__ */ jsx14("span", { dangerouslySetInnerHTML: { __html: deltaValue(props) } });
1656
+ return /* @__PURE__ */ jsx15("span", { dangerouslySetInnerHTML: { __html: deltaValue(props) } });
1606
1657
  }
1607
1658
  function RowIdentity({ symbol, name, logo, href }) {
1608
1659
  const Tag = href ? "a" : "span";
1609
- return /* @__PURE__ */ jsxs12(Tag, { className: "ui-identity", href, children: [
1610
- /* @__PURE__ */ jsxs12("span", { className: "ui-identity__logo", "aria-hidden": "true", children: [
1611
- /* @__PURE__ */ jsx14("span", { children: symbol.slice(0, 1) }),
1612
- logo && /* @__PURE__ */ jsx14("img", { src: logo, alt: "", onLoad: (e) => {
1660
+ return /* @__PURE__ */ jsxs13(Tag, { className: "ui-identity", href, children: [
1661
+ /* @__PURE__ */ jsxs13("span", { className: "ui-identity__logo", "aria-hidden": "true", children: [
1662
+ /* @__PURE__ */ jsx15("span", { children: symbol.slice(0, 1) }),
1663
+ logo && /* @__PURE__ */ jsx15("img", { src: logo, alt: "", onLoad: (e) => {
1613
1664
  e.currentTarget.hidden = false;
1614
1665
  }, onError: (e) => {
1615
1666
  e.currentTarget.hidden = true;
1616
1667
  } })
1617
1668
  ] }),
1618
- /* @__PURE__ */ jsx14("span", { className: "ui-identity__symbol", children: symbol }),
1619
- /* @__PURE__ */ jsx14("span", { className: "ui-identity__name", children: name })
1669
+ /* @__PURE__ */ jsx15("span", { className: "ui-identity__symbol", children: symbol }),
1670
+ /* @__PURE__ */ jsx15("span", { className: "ui-identity__name", children: name })
1620
1671
  ] });
1621
1672
  }
1622
1673
 
1623
1674
  // src/Segmented.tsx
1624
1675
  import { segmentedNextIndex } from "@apliteni/apliteni-ui";
1625
- import { jsx as jsx15 } from "react/jsx-runtime";
1676
+ import { jsx as jsx16 } from "react/jsx-runtime";
1626
1677
  function Segmented({ options, value, onChange, label, appearance = "pill", disabled = false }) {
1627
1678
  const enabled = options.filter((o) => !o.disabled);
1628
1679
  const tabValue = enabled.some((o) => o.value === value) ? value : enabled[0]?.value;
1629
- return /* @__PURE__ */ jsx15("div", { className: `ui-seg${appearance === "underline" ? " ui-seg--underline" : ""}`, role: "toolbar", "aria-label": label, children: options.map((option) => /* @__PURE__ */ jsx15(
1680
+ return /* @__PURE__ */ jsx16("div", { className: `ui-seg${appearance === "underline" ? " ui-seg--underline" : ""}`, role: "toolbar", "aria-label": label, children: options.map((option) => /* @__PURE__ */ jsx16(
1630
1681
  "button",
1631
1682
  {
1632
1683
  type: "button",
@@ -1651,15 +1702,15 @@ function Segmented({ options, value, onChange, label, appearance = "pill", disab
1651
1702
  }
1652
1703
 
1653
1704
  // src/FilterBar.tsx
1654
- import { useLayoutEffect as useLayoutEffect3, useRef as useRef8 } from "react";
1705
+ import { useLayoutEffect as useLayoutEffect3, useRef as useRef9 } from "react";
1655
1706
  import { filterBar, initFilterBar } from "@apliteni/apliteni-ui";
1656
- import { jsx as jsx16 } from "react/jsx-runtime";
1707
+ import { jsx as jsx17 } from "react/jsx-runtime";
1657
1708
  function FilterBar(props) {
1658
- const host = useRef8(null);
1659
- const latest = useRef8(props);
1709
+ const host = useRef9(null);
1710
+ const latest = useRef9(props);
1660
1711
  latest.current = props;
1661
- const controller = useRef8(null);
1662
- const initial = useRef8({ __html: filterBar(props) });
1712
+ const controller = useRef9(null);
1713
+ const initial = useRef9({ __html: filterBar(props) });
1663
1714
  useLayoutEffect3(() => {
1664
1715
  const el = host.current;
1665
1716
  controller.current = initFilterBar(el, latest.current);
@@ -1682,40 +1733,40 @@ function FilterBar(props) {
1682
1733
  useLayoutEffect3(() => {
1683
1734
  controller.current?.update(props);
1684
1735
  }, [props.filters, props.label, props.clearLabel, props.disabled, props.busy]);
1685
- return /* @__PURE__ */ jsx16("div", { ref: host, dangerouslySetInnerHTML: initial.current });
1736
+ return /* @__PURE__ */ jsx17("div", { ref: host, dangerouslySetInnerHTML: initial.current });
1686
1737
  }
1687
1738
 
1688
1739
  // src/KeyValueList.tsx
1689
- import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
1740
+ import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
1690
1741
  function detail({ value, redacted }) {
1691
- if (redacted) return /* @__PURE__ */ jsxs13("span", { className: "ui-kv__hidden", children: [
1692
- /* @__PURE__ */ jsx17(Icon, { name: "eyeOff" }),
1742
+ if (redacted) return /* @__PURE__ */ jsxs14("span", { className: "ui-kv__hidden", children: [
1743
+ /* @__PURE__ */ jsx18(Icon, { name: "eyeOff" }),
1693
1744
  "Hidden"
1694
1745
  ] });
1695
1746
  if (value == null) return "\u2014";
1696
1747
  return typeof value === "boolean" ? String(value) : value;
1697
1748
  }
1698
1749
  function KeyValueList({ rows, columns = 1, className, ...rest }) {
1699
- return /* @__PURE__ */ jsx17("dl", { ...rest, className: ["ui-drawer__rows", "ui-kv", columns === 2 && "ui-kv--two-columns", className].filter(Boolean).join(" "), children: rows.map((row, index) => /* @__PURE__ */ jsxs13("div", { className: "ui-drawer__row", children: [
1700
- /* @__PURE__ */ jsx17("dt", { children: row.label }),
1701
- /* @__PURE__ */ jsx17("dd", { children: detail(row) })
1750
+ return /* @__PURE__ */ jsx18("dl", { ...rest, className: ["ui-drawer__rows", "ui-kv", columns === 2 && "ui-kv--two-columns", className].filter(Boolean).join(" "), children: rows.map((row, index) => /* @__PURE__ */ jsxs14("div", { className: "ui-drawer__row", children: [
1751
+ /* @__PURE__ */ jsx18("dt", { children: row.label }),
1752
+ /* @__PURE__ */ jsx18("dd", { children: detail(row) })
1702
1753
  ] }, index)) });
1703
1754
  }
1704
1755
  function DrawerSection({ title, headingLevel = 3, className, children, ...rest }) {
1705
1756
  const Heading = `h${headingLevel}`;
1706
- return /* @__PURE__ */ jsxs13("section", { ...rest, className: ["ui-drawer__section", className].filter(Boolean).join(" "), children: [
1707
- title != null && /* @__PURE__ */ jsx17(Heading, { className: "ui-drawer__section-title", children: title }),
1757
+ return /* @__PURE__ */ jsxs14("section", { ...rest, className: ["ui-drawer__section", className].filter(Boolean).join(" "), children: [
1758
+ title != null && /* @__PURE__ */ jsx18(Heading, { className: "ui-drawer__section-title", children: title }),
1708
1759
  children
1709
1760
  ] });
1710
1761
  }
1711
1762
 
1712
1763
  // src/Snippet.tsx
1713
- import { useEffect as useEffect5, useRef as useRef9, useState as useState6 } from "react";
1714
- import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
1764
+ import { useEffect as useEffect5, useRef as useRef10, useState as useState6 } from "react";
1765
+ import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
1715
1766
  function Snippet({ label = "shell", code = "", reveal = false, copyLabel = "Copy" }) {
1716
1767
  const [status, setStatus] = useState6("idle");
1717
- const request = useRef9(0);
1718
- const timer = useRef9(void 0);
1768
+ const request = useRef10(0);
1769
+ const timer = useRef10(void 0);
1719
1770
  useEffect5(() => {
1720
1771
  setStatus("idle");
1721
1772
  return () => {
@@ -1736,15 +1787,92 @@ function Snippet({ label = "shell", code = "", reveal = false, copyLabel = "Copy
1736
1787
  if (current === request.current) setStatus("failed");
1737
1788
  }
1738
1789
  }
1739
- return /* @__PURE__ */ jsxs14("div", { className: reveal ? "ui-snippet ui-snippet--reveal" : "ui-snippet", children: [
1740
- /* @__PURE__ */ jsxs14("div", { className: "ui-snippet__bar", children: [
1741
- /* @__PURE__ */ jsx18("span", { children: label }),
1742
- /* @__PURE__ */ jsxs14("button", { type: "button", className: "ui-snippet__copy", "aria-live": "polite", "aria-atomic": "true", onClick: copy, children: [
1743
- /* @__PURE__ */ jsx18(Icon, { name: status === "copied" ? "check" : "copy" }),
1790
+ return /* @__PURE__ */ jsxs15("div", { className: reveal ? "ui-snippet ui-snippet--reveal" : "ui-snippet", children: [
1791
+ /* @__PURE__ */ jsxs15("div", { className: "ui-snippet__bar", children: [
1792
+ /* @__PURE__ */ jsx19("span", { children: label }),
1793
+ /* @__PURE__ */ jsxs15("button", { type: "button", className: "ui-snippet__copy", "aria-live": "polite", "aria-atomic": "true", onClick: copy, children: [
1794
+ /* @__PURE__ */ jsx19(Icon, { name: status === "copied" ? "check" : "copy" }),
1744
1795
  status === "copied" ? "Copied" : status === "failed" ? "Copy failed" : copyLabel
1745
1796
  ] })
1746
1797
  ] }),
1747
- /* @__PURE__ */ jsx18("pre", { children: code })
1798
+ /* @__PURE__ */ jsx19("pre", { children: code })
1799
+ ] });
1800
+ }
1801
+
1802
+ // src/Tabs.tsx
1803
+ import { useEffect as useEffect6, useId as useId7, useRef as useRef11 } from "react";
1804
+ import { playEntrance } from "@apliteni/apliteni-ui/motion";
1805
+ import { Fragment as Fragment6, jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
1806
+ function Tabs({ items, value, onChange, label }) {
1807
+ const id = useId7();
1808
+ const previous = useRef11(value);
1809
+ const activePanel = useRef11(null);
1810
+ const buttons = useRef11([]);
1811
+ useEffect6(() => {
1812
+ if (previous.current !== value) playEntrance(activePanel.current);
1813
+ previous.current = value;
1814
+ }, [value]);
1815
+ return /* @__PURE__ */ jsxs16("div", { className: "ui-tabs", children: [
1816
+ /* @__PURE__ */ jsx20("div", { className: "ui-tabs__list", role: "tablist", "aria-label": label, children: items.map((item, i) => /* @__PURE__ */ jsxs16(
1817
+ "button",
1818
+ {
1819
+ type: "button",
1820
+ role: "tab",
1821
+ ref: (el) => {
1822
+ buttons.current[i] = el;
1823
+ },
1824
+ className: `ui-tabs__tab${item.value === value ? " is-active" : ""}`,
1825
+ id: `${id}-tab-${i}`,
1826
+ "aria-controls": `${id}-panel-${i}`,
1827
+ "aria-selected": item.value === value,
1828
+ tabIndex: item.value === value ? 0 : -1,
1829
+ onClick: () => onChange(item.value),
1830
+ onKeyDown: (event) => {
1831
+ let next;
1832
+ switch (event.key) {
1833
+ case "ArrowRight":
1834
+ next = (i + 1) % items.length;
1835
+ break;
1836
+ case "ArrowLeft":
1837
+ next = (i - 1 + items.length) % items.length;
1838
+ break;
1839
+ case "Home":
1840
+ next = 0;
1841
+ break;
1842
+ case "End":
1843
+ next = items.length - 1;
1844
+ break;
1845
+ default:
1846
+ return;
1847
+ }
1848
+ event.preventDefault();
1849
+ buttons.current[next]?.focus();
1850
+ onChange(items[next].value);
1851
+ },
1852
+ children: [
1853
+ item.label,
1854
+ item.count != null && /* @__PURE__ */ jsxs16(Fragment6, { children: [
1855
+ " ",
1856
+ item.count
1857
+ ] })
1858
+ ]
1859
+ },
1860
+ item.value
1861
+ )) }),
1862
+ /* @__PURE__ */ jsx20("div", { className: "ui-tabs__panels", children: items.map((item, i) => /* @__PURE__ */ jsx20(
1863
+ "div",
1864
+ {
1865
+ className: "ui-tabs__panel",
1866
+ role: "tabpanel",
1867
+ ref: item.value === value ? activePanel : void 0,
1868
+ id: `${id}-panel-${i}`,
1869
+ "aria-labelledby": `${id}-tab-${i}`,
1870
+ tabIndex: 0,
1871
+ hidden: item.value !== value,
1872
+ children: item.value === value ? item.panel : null
1873
+ },
1874
+ item.value
1875
+ )) })
1748
1876
  ] });
1749
1877
  }
1750
1878
 
@@ -1758,6 +1886,7 @@ export {
1758
1886
  Button,
1759
1887
  Card,
1760
1888
  CommandPalette,
1889
+ Confirm,
1761
1890
  DEFAULT_PAGE_SIZE3 as DEFAULT_PAGE_SIZE,
1762
1891
  DataTable,
1763
1892
  DeltaValue,
@@ -1778,5 +1907,6 @@ export {
1778
1907
  SkeletonTable,
1779
1908
  Snippet,
1780
1909
  StatBand,
1910
+ Tabs,
1781
1911
  sortTableRows
1782
1912
  };
@@ -65,7 +65,7 @@
65
65
  }
66
66
 
67
67
  .ui-btn--danger { color: var(--text); }
68
- .ui-btn--danger:hover {
68
+ .ui-btn--danger:hover, .ui-btn--danger:focus-visible {
69
69
  color: var(--pink);
70
70
  border-color: var(--pink);
71
71
  background: color-mix(in srgb, var(--pink) 10%, transparent); /* ring-gap: inherit — control paint; its focus indicator uses the containing surface. */