@devslab/dds-react 0.28.0 → 0.29.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/README.ko.md CHANGED
@@ -80,3 +80,22 @@ Input/InputGroup은 검색 전용이 아닌 일반 입력 기반이며 라벨
80
80
 
81
81
  상세 import: `@devslab/dds-react/input`, `/combobox`, `/select-picker`, `/dropdown-menu`, `/popover`, `/calendar`, `/date-picker`, `/date-range-picker`, `/month-picker`. 기존 루트 import와 `styles.css`는 유지합니다. [공통 사용 가이드](https://github.com/devslab-kr/dds/blob/main/docs/components-input-choice-calendar.ko.md)를 참고하세요.
82
82
  상세 import: `@devslab/dds-react/input`, `/combobox`, `/select-picker`, `/dropdown-menu`, `/popover`, `/calendar`, `/date-picker`, `/time-picker`, `/date-range-picker`, `/month-picker`, `/segmented-control`, `/number-input`. 기존 루트 import와 `styles.css`는 유지합니다. [공통 사용 가이드](https://github.com/devslab-kr/dds/blob/main/docs/components-input-choice-calendar.ko.md)를 참고하세요.
83
+
84
+ ## 선택형 콘솔 메뉴 그룹
85
+
86
+ 기존 그룹은 계속 펼쳐집니다. 고유한 `id`와 `collapsible: true`를 지정한 그룹에만
87
+ 접기·펼치기 버튼을 제공합니다. 항목의 `icon`은 장식용이며 이름은 `label`로 제공합니다.
88
+ `expandedGroups`와 `onExpandedGroupsChange`로 앱에서 상태를 제어합니다.
89
+ 외부 상태를 생략하면 내부 상태를 사용합니다. `defaultExpandedGroups`가 초기값이며,
90
+ 빈 배열은 모두 접기, 초기값 생략은 활성 항목을 포함한 그룹만 펼치기입니다.
91
+ 옵션이 없는 그룹은 항상 펼쳐지고 여러 그룹을 동시에 열 수 있습니다.
92
+ ID 생략 시 `group-<index>`를 사용하므로 순서 변경·상태 보관에는 안정적인 고유 ID를 쓰세요.
93
+ 페이지 이동 시 그룹 열기와 세션 보관은 앱에서 처리합니다. 저장소는 hydration 이후 읽고
94
+ 서버와 최초 클라이언트 상태를 일치시키세요. DDS는 저장소에 접근하거나 제어 상태를
95
+ 임의로 덮어쓰지 않습니다. 데스크톱·모바일 모두 Enter/Space 조작과
96
+ `aria-expanded`, `aria-controls`를 지원합니다.
97
+
98
+
99
+ ## 공통 업무 화면
100
+
101
+ Layout·LeftNav·TopNav는 공통 간격과 타이포 규격을 사용합니다. [조립 방법과 수치](../../docs/layouts.ko.md)를 참고하세요.
package/README.md CHANGED
@@ -114,3 +114,33 @@ Input/InputGroup are general-purpose native inputs, not search-only, with label
114
114
 
115
115
  Use explicit subpaths `@devslab/dds-react/input`, `/combobox`, `/select-picker`, `/dropdown-menu`, `/popover`, `/calendar`, `/date-picker`, `/date-range-picker`, `/month-picker`, or the existing root exports. Keep importing `styles.css` once. See the [common usage guide](https://github.com/devslab-kr/dds/blob/main/docs/components-input-choice-calendar.md).
116
116
  Use explicit subpaths `@devslab/dds-react/input`, `/combobox`, `/select-picker`, `/dropdown-menu`, `/popover`, `/calendar`, `/date-picker`, `/time-picker`, `/date-range-picker`, `/month-picker`, `/segmented-control`, `/number-input`, or the existing root exports. Keep importing `styles.css` once. See the [common usage guide](https://github.com/devslab-kr/dds/blob/main/docs/components-input-choice-calendar.md).
117
+
118
+ ## Optional console navigation groups
119
+
120
+ `ConsoleShell` keeps legacy groups expanded. Set a unique, stable `id` and
121
+ `collapsible: true` on a group to opt into disclosure buttons. An item's optional
122
+ `icon` is decorative; keep its text `label`.
123
+
124
+ ```tsx
125
+ <ConsoleShell {...shellProps}
126
+ nav={[{ id: "settings", label: "Settings", collapsible: true,
127
+ items: [{ id: "policies", href: "/policies", label: "Policies", icon: <Icon name="check" /> }] }]}
128
+ expandedGroups={expandedGroups}
129
+ onExpandedGroupsChange={setExpandedGroups}
130
+ />
131
+ ```
132
+
133
+ Omit `expandedGroups` for internal state. `defaultExpandedGroups` supplies its
134
+ initial value; `[]` starts all collapsible groups closed. With neither prop, only
135
+ groups containing the active item start open. Other groups always stay open.
136
+ Multiple groups may be expanded. Missing IDs fall back to `group-<index>`; prefer
137
+ stable unique IDs for persistence or reordering. The app owns route-change
138
+ expansion and persistence. Read browser storage after hydration, keeping server
139
+ and initial client state equal. DDS never accesses storage or overwrites a
140
+ controlled selection. Enter/Space and `aria-expanded`/`aria-controls` work in both
141
+ the desktop rail and mobile drawer.
142
+
143
+
144
+ ## Shared application layouts
145
+
146
+ Layout, LeftNav and TopNav use the common geometry and typography rules. See [composition and exact dimensions](../../docs/layouts.md).
@@ -1,15 +1,6 @@
1
- import { type HTMLAttributes, type ReactNode } from "react";
2
- export interface ConsoleNavItem {
3
- id: string;
4
- href: string;
5
- label: string;
6
- badge?: number;
7
- active?: boolean;
8
- }
9
- export interface ConsoleNavGroup {
10
- label: string;
11
- items: readonly ConsoleNavItem[];
12
- }
1
+ import type { HTMLAttributes, ReactNode } from "react";
2
+ import { type ConsoleNavGroup } from "./left-nav";
3
+ export type { ConsoleNavItem, ConsoleNavGroup } from "./left-nav";
13
4
  export interface ConsoleShellLabels {
14
5
  skip: string;
15
6
  menuOpen: string;
@@ -34,7 +25,12 @@ export interface ConsoleShellProps extends Omit<HTMLAttributes<HTMLDivElement>,
34
25
  label: string;
35
26
  value: string;
36
27
  }[];
37
- nav: readonly ConsoleNavGroup[];
28
+ nav?: readonly ConsoleNavGroup[];
29
+ /** Supply a standalone LeftNav or custom navigation. */
30
+ navigation?: ReactNode;
31
+ expandedGroups?: readonly string[];
32
+ defaultExpandedGroups?: readonly string[];
33
+ onExpandedGroupsChange?: (groupIds: string[]) => void;
38
34
  labels: ConsoleShellLabels;
39
35
  header: ConsoleHeader;
40
36
  foot?: ReactNode;
@@ -1 +1 @@
1
- {"version":3,"file":"console-shell.d.ts","sourceRoot":"","sources":["../src/console-shell.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,cAAc,EACnB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AACD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,cAAc,EAAE,CAAC;CAClC;AACD,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AACD,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;AACD,MAAM,WAAW,iBACf,SAAQ,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IACpE,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,OAAO,CAAC,EAAE,SAAS;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACtD,GAAG,EAAE,SAAS,eAAe,EAAE,CAAC;IAChC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,QAAQ,EAAE,SAAS,CAAC;CACrB;AASD,eAAO,MAAM,YAAY,8GA8IxB,CAAC"}
1
+ {"version":3,"file":"console-shell.d.ts","sourceRoot":"","sources":["../src/console-shell.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvD,OAAO,EAAW,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAC3D,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClE,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AACD,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;AACD,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAC7C,cAAc,CAAC,cAAc,CAAC,EAC9B,UAAU,GAAG,SAAS,CACvB;IACC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,OAAO,CAAC,EAAE,SAAS;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACtD,GAAG,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACjC,wDAAwD;IACxD,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,qBAAqB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,sBAAsB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACtD,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,QAAQ,EAAE,SAAS,CAAC;CACrB;AACD,eAAO,MAAM,YAAY,8GA8ExB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -4,6 +4,9 @@ export * from "./overlays";
4
4
  export * from "./icon";
5
5
  export * from "./toast";
6
6
  export * from "./console-shell";
7
+ export { LeftNav, type LeftNavProps } from "./left-nav";
8
+ export * from "./layout";
9
+ export * from "./top-nav";
7
10
  export { Dialog as ArkDialog } from "@ark-ui/react/dialog";
8
11
  export { Tabs as ArkTabs } from "@ark-ui/react/tabs";
9
12
  export { Tooltip as ArkTooltip } from "@ark-ui/react/tooltip";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,IAAI,IAAI,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,UAAU,IAAI,aAAa,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,QAAQ,IAAI,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,KAAK,IAAI,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,KAAK,IAAI,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAExD,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,UAAU,IAAI,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAExE,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AAEjC,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AACpF,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AACxD,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,IAAI,IAAI,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,UAAU,IAAI,aAAa,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,QAAQ,IAAI,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,KAAK,IAAI,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,KAAK,IAAI,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAExD,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,UAAU,IAAI,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAExE,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AAEjC,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AACpF,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC"}
package/dist/index.js CHANGED
@@ -10,41 +10,41 @@ import { Popover as g } from "./popover.js";
10
10
  import { Calendar as _ } from "./calendar.js";
11
11
  import { t as v } from "./time-picker-BNmQMQdq.js";
12
12
  import { SegmentedControl as y, validateSegmentedItems as b } from "./segmented-control.js";
13
- import { NumberInput as x, normalizeNumberText as S, numberInputMessages as ee } from "./number-input.js";
14
- import { createContext as C, forwardRef as w, useCallback as T, useContext as E, useEffect as D, useId as O, useMemo as k, useRef as A, useState as j } from "react";
15
- import { Field as M } from "@ark-ui/react/field";
13
+ import { NumberInput as x, normalizeNumberText as S, numberInputMessages as C } from "./number-input.js";
14
+ import { createContext as w, forwardRef as T, useCallback as E, useContext as D, useEffect as O, useId as k, useMemo as A, useRef as j, useState as M } from "react";
15
+ import { Field as ee } from "@ark-ui/react/field";
16
16
  import { Checkbox as N } from "@ark-ui/react/checkbox";
17
17
  import { Switch as P } from "@ark-ui/react/switch";
18
18
  import { Fragment as F, jsx as I, jsxs as L } from "react/jsx-runtime";
19
19
  import { Tabs as R, Tabs as z, useTabsContext as B } from "@ark-ui/react/tabs";
20
- import { RadioGroup as V, RadioGroup as H, useRadioGroupContext as U } from "@ark-ui/react/radio-group";
21
- import { Dialog as W, Dialog as G } from "@ark-ui/react/dialog";
22
- import { Tooltip as K, Tooltip as q } from "@ark-ui/react/tooltip";
23
- import { Portal as J } from "@ark-ui/react/portal";
24
- import { directionPolicy as Y, icons as X } from "@devslab/dds-icons";
25
- import { Toast as Z, Toast as Q, Toaster as te, createToaster as ne } from "@ark-ui/react/toast";
26
- import { DatePicker as re } from "@ark-ui/react/date-picker";
20
+ import { RadioGroup as te, RadioGroup as V, useRadioGroupContext as ne } from "@ark-ui/react/radio-group";
21
+ import { Dialog as re, Dialog as H } from "@ark-ui/react/dialog";
22
+ import { Tooltip as U, Tooltip as W } from "@ark-ui/react/tooltip";
23
+ import { Portal as G } from "@ark-ui/react/portal";
24
+ import { directionPolicy as K, icons as q } from "@devslab/dds-icons";
25
+ import { Toast as J, Toast as Y, Toaster as ie, createToaster as ae } from "@ark-ui/react/toast";
26
+ import { DatePicker as oe } from "@ark-ui/react/date-picker";
27
27
  //#region src/selection.tsx
28
- var ie = w(function({ onValueChange: e, unstyled: n, className: r, ...i }, a) {
28
+ var se = T(function({ onValueChange: e, unstyled: n, className: r, ...i }, a) {
29
29
  return /* @__PURE__ */ I(z.Root, {
30
30
  ...i,
31
31
  ref: a,
32
32
  onValueChange: (t) => e?.(t.value),
33
33
  className: t(!n && "dds-tabs-root", r)
34
34
  });
35
- }), ae = w(function({ unstyled: e, className: n, ...r }, i) {
35
+ }), ce = T(function({ unstyled: e, className: n, ...r }, i) {
36
36
  return /* @__PURE__ */ I(z.List, {
37
37
  ...r,
38
38
  ref: i,
39
39
  className: t(!e && "dds-tabs", n)
40
40
  });
41
- }), oe = w(function({ unstyled: e, className: n, ...r }, i) {
41
+ }), le = T(function({ unstyled: e, className: n, ...r }, i) {
42
42
  return /* @__PURE__ */ I(z.Trigger, {
43
43
  ...r,
44
44
  ref: i,
45
45
  className: t(!e && "dds-tab", n)
46
46
  });
47
- }), se = w(function({ value: e, style: t, ...n }, r) {
47
+ }), ue = T(function({ value: e, style: t, ...n }, r) {
48
48
  let i = B().value !== e;
49
49
  return /* @__PURE__ */ I(z.Content, {
50
50
  ...n,
@@ -57,8 +57,8 @@ var ie = w(function({ onValueChange: e, unstyled: n, className: r, ...i }, a) {
57
57
  } : t
58
58
  });
59
59
  });
60
- function ce({ option: e }) {
61
- let t = U(), { style: n, defaultChecked: r, ...i } = t.getItemHiddenInputProps(e);
60
+ function de({ option: e }) {
61
+ let t = ne(), { style: n, defaultChecked: r, ...i } = t.getItemHiddenInputProps(e);
62
62
  return /* @__PURE__ */ I("input", {
63
63
  ...i,
64
64
  checked: t.value === e.value,
@@ -66,8 +66,8 @@ function ce({ option: e }) {
66
66
  className: "dds-check__input"
67
67
  });
68
68
  }
69
- var le = w(function({ options: e, label: n, onValueChange: r, className: i, children: a, ...o }, s) {
70
- return /* @__PURE__ */ L(H.Root, {
69
+ var fe = T(function({ options: e, label: n, onValueChange: r, className: i, children: a, ...o }, s) {
70
+ return /* @__PURE__ */ L(V.Root, {
71
71
  ...o,
72
72
  ref: s,
73
73
  onValueChange: (e) => {
@@ -75,26 +75,26 @@ var le = w(function({ options: e, label: n, onValueChange: r, className: i, chil
75
75
  },
76
76
  className: t("dds-radio-group", i),
77
77
  children: [
78
- /* @__PURE__ */ I(H.Label, {
78
+ /* @__PURE__ */ I(V.Label, {
79
79
  className: "dds-field__label",
80
80
  children: n
81
81
  }),
82
- e.map((e) => /* @__PURE__ */ L(H.Item, {
82
+ e.map((e) => /* @__PURE__ */ L(V.Item, {
83
83
  value: e.value,
84
84
  disabled: e.disabled,
85
85
  className: "dds-check",
86
- children: [/* @__PURE__ */ I(ce, { option: e }), /* @__PURE__ */ I(H.ItemText, { children: e.label })]
86
+ children: [/* @__PURE__ */ I(de, { option: e }), /* @__PURE__ */ I(V.ItemText, { children: e.label })]
87
87
  }, e.value)),
88
88
  a
89
89
  ]
90
90
  });
91
- }), ue = w(function({ title: e, description: n, children: r, actions: i, onOpenChange: a, closeOnOutside: o, portal: s = !0, className: c, overlayClassName: l, contentProps: u, initialFocus: d, finalFocus: f, frame: p, unstyled: m, ...h }, g) {
91
+ }), pe = T(function({ title: e, description: n, children: r, actions: i, onOpenChange: a, closeOnOutside: o, portal: s = !0, className: c, overlayClassName: l, contentProps: u, initialFocus: d, finalFocus: f, frame: p, unstyled: m, ...h }, g) {
92
92
  let _ = {
93
- title: /* @__PURE__ */ I(G.Title, {
93
+ title: /* @__PURE__ */ I(H.Title, {
94
94
  className: m ? void 0 : "dds-dialog__title",
95
95
  children: e
96
96
  }),
97
- description: n && /* @__PURE__ */ I(G.Description, {
97
+ description: n && /* @__PURE__ */ I(H.Description, {
98
98
  className: m ? void 0 : "dds-dialog__body",
99
99
  children: n
100
100
  }),
@@ -103,9 +103,9 @@ var le = w(function({ options: e, label: n, onValueChange: r, className: i, chil
103
103
  className: m ? void 0 : "dds-dialog__actions",
104
104
  children: i
105
105
  })
106
- }, v = /* @__PURE__ */ I(G.Positioner, {
106
+ }, v = /* @__PURE__ */ I(H.Positioner, {
107
107
  className: t(!m && "dds-dialog-overlay", l),
108
- children: /* @__PURE__ */ I(G.Content, {
108
+ children: /* @__PURE__ */ I(H.Content, {
109
109
  ...u,
110
110
  ref: g,
111
111
  "aria-describedby": n ? u?.["aria-describedby"] : void 0,
@@ -118,7 +118,7 @@ var le = w(function({ options: e, label: n, onValueChange: r, className: i, chil
118
118
  ] })
119
119
  })
120
120
  });
121
- return /* @__PURE__ */ I(G.Root, {
121
+ return /* @__PURE__ */ I(H.Root, {
122
122
  ...h,
123
123
  onOpenChange: (e) => a?.(e.open),
124
124
  closeOnInteractOutside: o ?? h.closeOnInteractOutside,
@@ -126,21 +126,21 @@ var le = w(function({ options: e, label: n, onValueChange: r, className: i, chil
126
126
  finalFocusEl: f ? () => f() ?? null : h.finalFocusEl,
127
127
  lazyMount: !0,
128
128
  unmountOnExit: !0,
129
- children: s ? /* @__PURE__ */ I(J, { children: v }) : v
129
+ children: s ? /* @__PURE__ */ I(G, { children: v }) : v
130
130
  });
131
131
  });
132
- function de({ content: e, children: n, onOpenChange: r, className: i, contentProps: a, ...o }) {
133
- return /* @__PURE__ */ I(q.Root, {
132
+ function me({ content: e, children: n, onOpenChange: r, className: i, contentProps: a, ...o }) {
133
+ return /* @__PURE__ */ I(W.Root, {
134
134
  openDelay: 0,
135
135
  closeDelay: 0,
136
136
  ...o,
137
137
  onOpenChange: (e) => r?.(e.open),
138
138
  children: /* @__PURE__ */ L("span", {
139
139
  className: t("dds-tooltip", i),
140
- children: [typeof n == "function" ? /* @__PURE__ */ I(q.Context, { children: (e) => n(e.getTriggerProps()) }) : /* @__PURE__ */ I(q.Trigger, {
140
+ children: [typeof n == "function" ? /* @__PURE__ */ I(W.Context, { children: (e) => n(e.getTriggerProps()) }) : /* @__PURE__ */ I(W.Trigger, {
141
141
  asChild: !0,
142
142
  children: n
143
- }), /* @__PURE__ */ I(J, { children: /* @__PURE__ */ I(q.Positioner, { children: /* @__PURE__ */ I(q.Content, {
143
+ }), /* @__PURE__ */ I(G, { children: /* @__PURE__ */ I(W.Positioner, { children: /* @__PURE__ */ I(W.Content, {
144
144
  ...a,
145
145
  className: t("dds-tooltip__bubble", a?.className),
146
146
  children: e
@@ -150,8 +150,8 @@ function de({ content: e, children: n, onOpenChange: r, className: i, contentPro
150
150
  }
151
151
  //#endregion
152
152
  //#region src/icon.tsx
153
- var fe = w(function({ name: e, label: n, size: r = 24, directional: i, className: a, ...o }, s) {
154
- let c = X[e];
153
+ var he = T(function({ name: e, label: n, size: r = 24, directional: i, className: a, ...o }, s) {
154
+ let c = q[e];
155
155
  return /* @__PURE__ */ L("svg", {
156
156
  ...o,
157
157
  ref: s,
@@ -166,19 +166,19 @@ var fe = w(function({ name: e, label: n, size: r = 24, directional: i, className
166
166
  role: n ? "img" : void 0,
167
167
  "aria-label": n,
168
168
  "aria-hidden": !n || void 0,
169
- className: t((i ?? Y.mirrorInRtl.includes(e)) && Y.cssClass, a),
169
+ className: t((i ?? K.mirrorInRtl.includes(e)) && K.cssClass, a),
170
170
  children: [n && /* @__PURE__ */ I("title", { children: n }), /* @__PURE__ */ I("g", { dangerouslySetInnerHTML: { __html: c.body } })]
171
171
  });
172
- }), $ = C(null);
173
- function pe({ children: e, defaultDuration: n = 5e3, dismissLabel: r, regionLabel: i, className: a }) {
174
- let o = O(), s = A(0), c = k(() => ne({
172
+ }), X = w(null);
173
+ function ge({ children: e, defaultDuration: n = 5e3, dismissLabel: r, regionLabel: i, className: a }) {
174
+ let o = k(), s = j(0), c = A(() => ae({
175
175
  placement: "bottom-end",
176
176
  overlap: !1,
177
177
  gap: 8,
178
178
  offsets: "var(--dds-space-16)",
179
179
  removeDelay: 0,
180
180
  hotkey: ["DDS_NO_HOTKEY"]
181
- }), []), l = k(() => ({
181
+ }), []), l = A(() => ({
182
182
  show(e) {
183
183
  let t = `dds-toast-${o}-${++s.current}`, r = e.duration ?? n;
184
184
  return c.create({
@@ -199,9 +199,9 @@ function pe({ children: e, defaultDuration: n = 5e3, dismissLabel: r, regionLabe
199
199
  o,
200
200
  n
201
201
  ]);
202
- return D(() => () => c.remove(), [c]), /* @__PURE__ */ L($.Provider, {
202
+ return O(() => () => c.remove(), [c]), /* @__PURE__ */ L(X.Provider, {
203
203
  value: l,
204
- children: [e, /* @__PURE__ */ I(te, {
204
+ children: [e, /* @__PURE__ */ I(ie, {
205
205
  toaster: c,
206
206
  label: i ?? "",
207
207
  "aria-label": i ?? "",
@@ -209,10 +209,10 @@ function pe({ children: e, defaultDuration: n = 5e3, dismissLabel: r, regionLabe
209
209
  className: t("dds-toast-region", a),
210
210
  children: (e) => {
211
211
  let n = e.meta?.dds;
212
- return /* @__PURE__ */ L(Z.Root, {
212
+ return /* @__PURE__ */ L(J.Root, {
213
213
  className: t("dds-toast", `dds-toast--${n.tone ?? "info"}`),
214
214
  role: n.tone === "danger" ? "alert" : "status",
215
- children: [/* @__PURE__ */ I(Z.Description, { children: e.description }), r && /* @__PURE__ */ I(Z.CloseTrigger, {
215
+ children: [/* @__PURE__ */ I(J.Description, { children: e.description }), r && /* @__PURE__ */ I(J.CloseTrigger, {
216
216
  className: "dds-iconbtn dds-iconbtn--sm",
217
217
  "aria-label": typeof r == "function" ? r(n) : r,
218
218
  children: "×"
@@ -222,126 +222,267 @@ function pe({ children: e, defaultDuration: n = 5e3, dismissLabel: r, regionLabe
222
222
  })]
223
223
  });
224
224
  }
225
- function me() {
226
- let e = E($);
225
+ function _e() {
226
+ let e = D(X);
227
227
  if (!e) throw Error("useToast must be called inside <ToastProvider>");
228
228
  return e;
229
229
  }
230
230
  //#endregion
231
- //#region src/console-shell.tsx
232
- function he(e, t) {
233
- return t.active ?? (t.href.split("/").filter(Boolean).length <= 1 ? e === t.href : e === t.href || e.startsWith(`${t.href}/`));
234
- }
235
- var ge = w(function({ surface: e, activePath: n, brand: r, context: i, nav: a, labels: o, header: s, foot: c, children: l, className: u, ...d }, f) {
236
- let [p, m] = j(!1), [h, g] = j(!1), _ = O(), v = `dds-console-rail-${_}`, y = `dds-console-main-${_}`;
237
- return D(() => {
238
- g(!0);
239
- let e = (e) => {
240
- e.key === "Escape" && m(!1);
231
+ //#region src/layout.tsx
232
+ var Z = T(function({ navigationPosition: e = "left", contentWidth: n = "workspace", labels: r, header: i, navigation: a, railStart: o, railEnd: s, footer: c, children: l, surface: u, className: d, ...f }, p) {
233
+ let m = k(), h = `dds-console-rail-${m}`, g = `dds-console-main-${m}`, [_, v] = M(!1), [y, b] = M(!1), x = j(null), S = j(null);
234
+ function C() {
235
+ v(!1), x.current?.focus();
236
+ }
237
+ return O(() => {
238
+ if (b(!0), typeof window.matchMedia != "function") return;
239
+ let e = window.matchMedia("(max-width: 56.25rem)"), t = () => {
240
+ e.matches || v(!1);
241
241
  };
242
- return document.addEventListener("keydown", e), () => document.removeEventListener("keydown", e);
243
- }, []), /* @__PURE__ */ L("div", {
244
- ...d,
245
- ref: f,
246
- className: t("dds-console-shell", u),
247
- "data-surface": e,
248
- "data-hydrated": h ? "true" : void 0,
242
+ return e.addEventListener("change", t), () => e.removeEventListener("change", t);
243
+ }, []), O(() => {
244
+ if (!_) return;
245
+ let e = () => [x.current, ...Array.from(S.current?.querySelectorAll("a[href],button,summary,input,select,textarea,[tabindex=\"0\"]") ?? [])].filter((e) => !!e && !e.closest("[hidden]") && e.getClientRects().length > 0 && getComputedStyle(e).visibility !== "hidden" && !Array.from(S.current?.querySelectorAll("details:not([open])") ?? []).some((t) => t.contains(e) && !t.querySelector("summary")?.contains(e)) && !e.hasAttribute("disabled"));
246
+ e()[1]?.focus();
247
+ function t(t) {
248
+ if (t.key === "Escape" && (t.preventDefault(), C()), t.key === "Tab") {
249
+ let n = e(), r = n[0], i = n.at(-1);
250
+ t.shiftKey && document.activeElement === r ? (t.preventDefault(), i?.focus()) : !t.shiftKey && document.activeElement === i && (t.preventDefault(), r?.focus());
251
+ }
252
+ }
253
+ return document.addEventListener("keydown", t), () => {
254
+ document.removeEventListener("keydown", t);
255
+ };
256
+ }, [_]), /* @__PURE__ */ L("div", {
257
+ ...f,
258
+ ref: p,
259
+ className: t("dds-console-shell dds-layout", d),
260
+ "data-navigation-position": e,
261
+ "data-surface": u,
262
+ "data-hydrated": y ? "true" : void 0,
249
263
  children: [
250
264
  /* @__PURE__ */ I("a", {
251
265
  className: "dds-console-skip dds-visually-hidden",
252
- href: `#${y}`,
253
- children: o.skip
266
+ href: `#${g}`,
267
+ children: r.skip
254
268
  }),
255
269
  /* @__PURE__ */ L("button", {
270
+ ref: x,
256
271
  className: "dds-console-rail__toggle",
257
272
  type: "button",
258
273
  "data-action": "toggle-rail",
259
- "aria-controls": v,
260
- "aria-expanded": p,
261
- onClick: () => m(!p),
274
+ "aria-controls": h,
275
+ "aria-expanded": _,
276
+ onClick: () => _ ? C() : v(!0),
262
277
  children: [/* @__PURE__ */ I("span", { "aria-hidden": !0 }), /* @__PURE__ */ I("span", {
263
278
  className: "dds-visually-hidden",
264
- children: p ? o.menuClose : o.menuOpen
279
+ children: _ ? r.menuClose : r.menuOpen
265
280
  })]
266
281
  }),
267
282
  /* @__PURE__ */ I("div", {
268
283
  className: "dds-console-rail__scrim",
269
- "data-open": String(p),
270
- onClick: () => m(!1)
284
+ "data-open": String(_),
285
+ onClick: C
271
286
  }),
272
287
  /* @__PURE__ */ L("aside", {
273
- id: v,
274
- className: "dds-console-rail",
275
- "data-open": String(p),
288
+ ref: S,
289
+ id: h,
290
+ className: "dds-console-rail dds-layout__navigation",
291
+ "data-open": String(_),
292
+ onClick: (e) => {
293
+ _ && e.target instanceof Element && e.target.closest("a[href]") && C();
294
+ },
276
295
  children: [
277
- /* @__PURE__ */ L("a", {
278
- className: "dds-console-rail__brand",
279
- href: r.href,
280
- children: [/* @__PURE__ */ I("img", {
281
- src: r.mark,
282
- alt: "",
283
- width: 20,
284
- height: 20
285
- }), /* @__PURE__ */ I("strong", { children: r.name })]
286
- }),
287
- i && i.length > 0 && /* @__PURE__ */ I("dl", {
288
- className: "dds-console-rail__context",
289
- children: i.map((e, t) => /* @__PURE__ */ L("div", { children: [/* @__PURE__ */ I("dt", { children: e.label }), /* @__PURE__ */ I("dd", { children: e.value })] }, t))
290
- }),
291
- /* @__PURE__ */ I("nav", {
292
- className: "dds-console-rail__nav",
293
- "aria-label": o.nav,
294
- children: a.map((t, r) => /* @__PURE__ */ L("section", {
295
- className: "dds-console-rail__group",
296
- "aria-labelledby": `${_}-group-${r}`,
297
- children: [/* @__PURE__ */ I("h2", {
298
- id: `${_}-group-${r}`,
299
- className: "dds-console-rail__group-label",
300
- children: t.label
301
- }), /* @__PURE__ */ I("ul", { children: t.items.map((t) => /* @__PURE__ */ I("li", { children: /* @__PURE__ */ L("a", {
302
- className: "dds-console-rail__item",
303
- "data-nav": `${e}.${t.id}`,
304
- href: t.href,
305
- "aria-current": he(n, t) ? "page" : void 0,
306
- onClick: () => m(!1),
307
- children: [/* @__PURE__ */ I("span", { children: t.label }), t.badge !== void 0 && t.badge > 0 && /* @__PURE__ */ I("span", {
308
- className: "dds-console-rail__badge",
309
- "aria-label": o.badge.replace("{count}", () => String(t.badge)),
310
- children: t.badge
311
- })]
312
- }) }, t.id)) })]
313
- }, r))
314
- }),
315
- c && /* @__PURE__ */ I("div", {
316
- className: "dds-console-rail__foot",
317
- children: c
318
- })
296
+ o,
297
+ a,
298
+ s
319
299
  ]
320
300
  }),
321
- /* @__PURE__ */ L("main", {
322
- id: y,
323
- className: "dds-console-main",
301
+ /* @__PURE__ */ I("main", {
302
+ id: g,
303
+ className: "dds-console-main dds-layout__main",
324
304
  tabIndex: -1,
325
- children: [/* @__PURE__ */ L("header", {
326
- className: "dds-console-page-header",
327
- children: [/* @__PURE__ */ L("div", {
328
- className: "dds-console-page-header__text",
329
- children: [s.eyebrow && /* @__PURE__ */ I("p", {
330
- className: "dds-console-page-eyebrow",
331
- children: s.eyebrow
332
- }), /* @__PURE__ */ I("h1", { children: s.title })]
333
- }), s.actions && /* @__PURE__ */ I("div", {
334
- className: "dds-console-page-header__actions",
335
- children: s.actions
336
- })]
337
- }), l]
305
+ children: /* @__PURE__ */ L("div", {
306
+ className: "dds-layout__content",
307
+ "data-width": n,
308
+ children: [
309
+ i != null && /* @__PURE__ */ I("header", {
310
+ className: "dds-layout__header",
311
+ children: i
312
+ }),
313
+ l,
314
+ c != null && /* @__PURE__ */ I("footer", {
315
+ className: "dds-layout__footer",
316
+ children: c
317
+ })
318
+ ]
319
+ })
338
320
  })
339
321
  ]
340
322
  });
341
323
  });
342
324
  //#endregion
325
+ //#region src/left-nav.tsx
326
+ function Q(e, t) {
327
+ return t.active ?? (t.href.split("/").filter(Boolean).length <= 1 ? e === t.href : e === t.href || e.startsWith(`${t.href}/`));
328
+ }
329
+ function $({ surface: e, activePath: t, nav: n, labels: r, expandedGroups: i, defaultExpandedGroups: a, onExpandedGroupsChange: o, onNavigate: s }) {
330
+ let c = k(), [l, u] = M(() => a ?? n.flatMap((e, n) => e.collapsible && e.items.some((e) => Q(t, e)) ? [e.id ?? `group-${n}`] : [])), d = i ?? l;
331
+ function f(e) {
332
+ let t = d.includes(e) ? d.filter((t) => t !== e) : [...d, e];
333
+ i === void 0 && u(t), o?.(t);
334
+ }
335
+ return /* @__PURE__ */ I("nav", {
336
+ className: "dds-console-rail__nav dds-left-nav",
337
+ "aria-label": r.nav,
338
+ children: n.map((n, i) => /* @__PURE__ */ L("section", {
339
+ "data-collapsible": n.collapsible ? "true" : void 0,
340
+ className: "dds-console-rail__group",
341
+ "aria-labelledby": `${c}-group-${i}`,
342
+ children: [/* @__PURE__ */ I("h2", {
343
+ id: `${c}-group-${i}`,
344
+ className: "dds-console-rail__group-label",
345
+ children: n.collapsible ? /* @__PURE__ */ L("button", {
346
+ type: "button",
347
+ className: "dds-console-rail__group-toggle",
348
+ "aria-expanded": d.includes(n.id ?? `group-${i}`),
349
+ "aria-controls": `${c}-group-items-${i}`,
350
+ onClick: () => f(n.id ?? `group-${i}`),
351
+ children: [/* @__PURE__ */ I("span", { children: n.label }), /* @__PURE__ */ I("span", {
352
+ className: "dds-console-rail__chevron",
353
+ "aria-hidden": "true"
354
+ })]
355
+ }) : n.label
356
+ }), /* @__PURE__ */ I("ul", {
357
+ id: `${c}-group-items-${i}`,
358
+ hidden: n.collapsible && !d.includes(n.id ?? `group-${i}`),
359
+ children: n.items.map((n) => /* @__PURE__ */ I("li", { children: /* @__PURE__ */ L("a", {
360
+ className: "dds-console-rail__item",
361
+ "data-nav": `${e}.${n.id}`,
362
+ href: n.href,
363
+ "aria-current": Q(t, n) ? "page" : void 0,
364
+ onClick: s,
365
+ children: [n.icon == null ? /* @__PURE__ */ I("span", { children: n.label }) : /* @__PURE__ */ L("span", {
366
+ className: "dds-console-rail__item-content",
367
+ children: [/* @__PURE__ */ I("span", {
368
+ className: "dds-console-rail__item-icon",
369
+ "aria-hidden": "true",
370
+ children: n.icon
371
+ }), /* @__PURE__ */ I("span", { children: n.label })]
372
+ }), n.badge !== void 0 && n.badge > 0 && /* @__PURE__ */ I("span", {
373
+ className: "dds-console-rail__badge",
374
+ "aria-label": r.badge.replace("{count}", () => String(n.badge)),
375
+ children: n.badge
376
+ })]
377
+ }) }, n.id))
378
+ })]
379
+ }, n.id ?? i))
380
+ });
381
+ }
382
+ //#endregion
383
+ //#region src/console-shell.tsx
384
+ var ve = T(function({ surface: e, activePath: t, brand: n, context: r, nav: i = [], navigation: a, expandedGroups: o, defaultExpandedGroups: s, onExpandedGroupsChange: c, labels: l, header: u, foot: d, children: f, ...p }, m) {
385
+ return /* @__PURE__ */ I(Z, {
386
+ ...p,
387
+ ref: m,
388
+ surface: e,
389
+ labels: l,
390
+ railStart: /* @__PURE__ */ L(F, { children: [/* @__PURE__ */ L("a", {
391
+ className: "dds-console-rail__brand",
392
+ href: n.href,
393
+ children: [/* @__PURE__ */ I("img", {
394
+ src: n.mark,
395
+ alt: "",
396
+ width: 20,
397
+ height: 20
398
+ }), /* @__PURE__ */ I("strong", { children: n.name })]
399
+ }), r && r.length > 0 && /* @__PURE__ */ I("dl", {
400
+ className: "dds-console-rail__context",
401
+ children: r.map((e, t) => /* @__PURE__ */ L("div", { children: [/* @__PURE__ */ I("dt", { children: e.label }), /* @__PURE__ */ I("dd", { children: e.value })] }, t))
402
+ })] }),
403
+ navigation: a ?? /* @__PURE__ */ I($, {
404
+ surface: e,
405
+ activePath: t,
406
+ nav: i,
407
+ labels: l,
408
+ expandedGroups: o,
409
+ defaultExpandedGroups: s,
410
+ onExpandedGroupsChange: c
411
+ }),
412
+ railEnd: d && /* @__PURE__ */ I("div", {
413
+ className: "dds-console-rail__foot",
414
+ children: d
415
+ }),
416
+ header: /* @__PURE__ */ L("div", {
417
+ className: "dds-console-page-header",
418
+ children: [/* @__PURE__ */ L("div", {
419
+ className: "dds-console-page-header__text",
420
+ children: [u.eyebrow && /* @__PURE__ */ I("p", {
421
+ className: "dds-console-page-eyebrow",
422
+ children: u.eyebrow
423
+ }), /* @__PURE__ */ I("h1", { children: u.title })]
424
+ }), u.actions && /* @__PURE__ */ I("div", {
425
+ className: "dds-console-page-header__actions",
426
+ children: u.actions
427
+ })]
428
+ }),
429
+ children: f
430
+ });
431
+ });
432
+ //#endregion
433
+ //#region src/top-nav.tsx
434
+ function ye({ surface: e, activePath: t, nav: n, labels: r, onNavigate: i }) {
435
+ let a = j(null);
436
+ return O(() => {
437
+ function e(e) {
438
+ a.current?.contains(e.target) || a.current?.querySelectorAll("details[open]").forEach((e) => e.removeAttribute("open"));
439
+ }
440
+ return document.addEventListener("pointerdown", e), () => document.removeEventListener("pointerdown", e);
441
+ }, []), /* @__PURE__ */ I("nav", {
442
+ ref: a,
443
+ className: "dds-top-nav",
444
+ "aria-label": r.nav,
445
+ onKeyDown: (e) => {
446
+ if (e.key !== "Escape") return;
447
+ let t = e.target.closest("details");
448
+ t?.open && (e.preventDefault(), e.stopPropagation(), t.open = !1, t.querySelector("summary")?.focus());
449
+ },
450
+ children: n.map((n, a) => /* @__PURE__ */ L("details", {
451
+ className: "dds-top-nav__group",
452
+ children: [/* @__PURE__ */ I("summary", {
453
+ className: "dds-top-nav__trigger",
454
+ children: n.label
455
+ }), /* @__PURE__ */ I("ul", {
456
+ className: "dds-top-nav__items",
457
+ children: n.items.map((n) => /* @__PURE__ */ I("li", { children: /* @__PURE__ */ L("a", {
458
+ className: "dds-top-nav__item",
459
+ "data-nav": `${e}.${n.id}`,
460
+ href: n.href,
461
+ "aria-current": n.active ?? (t === n.href || n.href.split("/").filter(Boolean).length > 1 && t.startsWith(`${n.href}/`)) ? "page" : void 0,
462
+ onClick: (e) => {
463
+ e.currentTarget.closest("details")?.removeAttribute("open"), i?.();
464
+ },
465
+ children: [
466
+ n.icon != null && /* @__PURE__ */ I("span", {
467
+ className: "dds-top-nav__item-icon",
468
+ "aria-hidden": "true",
469
+ children: n.icon
470
+ }),
471
+ /* @__PURE__ */ I("span", { children: n.label }),
472
+ n.badge != null && n.badge > 0 && /* @__PURE__ */ I("span", {
473
+ className: "dds-console-rail__badge",
474
+ "aria-label": r.badge.replace("{count}", () => String(n.badge)),
475
+ children: n.badge
476
+ })
477
+ ]
478
+ }) }, n.id))
479
+ })]
480
+ }, n.id ?? a))
481
+ });
482
+ }
483
+ //#endregion
343
484
  //#region src/status-pill.tsx
344
- function _e(e) {
485
+ function be(e) {
345
486
  let t = new Set(e.openDomains ?? []);
346
487
  return function(n) {
347
488
  let r = e.tones[n.domain]?.[n.value], i = e.label(n.domain, n.value, n.locale);
@@ -362,12 +503,12 @@ function _e(e) {
362
503
  }
363
504
  //#endregion
364
505
  //#region src/pending-action.ts
365
- function ve() {
366
- let [e, t] = j(null), n = A(null);
367
- D(() => () => {
506
+ function xe() {
507
+ let [e, t] = M(null), n = j(null);
508
+ O(() => () => {
368
509
  n.current?.abort(), n.current = null;
369
510
  }, []);
370
- let r = T(async (e, r, i) => {
511
+ let r = E(async (e, r, i) => {
371
512
  if (n.current && !i?.replace) return;
372
513
  n.current?.abort();
373
514
  let a = new AbortController();
@@ -377,10 +518,10 @@ function ve() {
377
518
  } finally {
378
519
  n.current === a && (n.current = null, t(null));
379
520
  }
380
- }, []), i = T(() => {
521
+ }, []), i = E(() => {
381
522
  n.current?.abort(), n.current = null, t(null);
382
523
  }, []);
383
- return k(() => ({
524
+ return A(() => ({
384
525
  current: e,
385
526
  busy: e !== null,
386
527
  is: (t) => e === t,
@@ -393,6 +534,6 @@ function ve() {
393
534
  ]);
394
535
  }
395
536
  //#endregion
396
- export { N as ArkCheckbox, re as ArkDatePicker, W as ArkDialog, M as ArkField, V as ArkRadioGroup, P as ArkSwitch, R as ArkTabs, Q as ArkToast, K as ArkTooltip, s as Button, _ as Calendar, r as Checkbox, p as Combobox, ge as ConsoleShell, c as DatePicker, l as DateRangePicker, ue as Dialog, h as DropdownMenu, a as Field, fe as Icon, n as IconButton, d as Input, f as InputGroup, u as MonthPicker, x as NumberInput, g as Popover, e as Radio, le as RadioGroup, y as SegmentedControl, i as Select, m as SelectPicker, o as Switch, oe as Tab, ae as TabList, se as TabPanel, ie as Tabs, v as TimePicker, pe as ToastProvider, de as Tooltip, t as classes, _e as createStatusPill, S as normalizeNumberText, ee as numberInputMessages, ve as usePendingAction, me as useToast, b as validateSegmentedItems };
537
+ export { N as ArkCheckbox, oe as ArkDatePicker, re as ArkDialog, ee as ArkField, te as ArkRadioGroup, P as ArkSwitch, R as ArkTabs, Y as ArkToast, U as ArkTooltip, s as Button, _ as Calendar, r as Checkbox, p as Combobox, ve as ConsoleShell, c as DatePicker, l as DateRangePicker, pe as Dialog, h as DropdownMenu, a as Field, he as Icon, n as IconButton, d as Input, f as InputGroup, Z as Layout, $ as LeftNav, u as MonthPicker, x as NumberInput, g as Popover, e as Radio, fe as RadioGroup, y as SegmentedControl, i as Select, m as SelectPicker, o as Switch, le as Tab, ce as TabList, ue as TabPanel, se as Tabs, v as TimePicker, ge as ToastProvider, me as Tooltip, ye as TopNav, t as classes, be as createStatusPill, S as normalizeNumberText, C as numberInputMessages, xe as usePendingAction, _e as useToast, b as validateSegmentedItems };
397
538
 
398
539
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/selection.tsx","../src/overlays.tsx","../src/icon.tsx","../src/toast.tsx","../src/console-shell.tsx","../src/status-pill.tsx","../src/pending-action.ts"],"sourcesContent":["import { forwardRef, type ComponentProps, type ReactNode } from \"react\";\nimport { Tabs as ArkTabs, useTabsContext } from \"@ark-ui/react/tabs\";\nimport {\n RadioGroup as ArkRadioGroup,\n useRadioGroupContext,\n} from \"@ark-ui/react/radio-group\";\nimport { classes } from \"./controls\";\nexport interface TabsProps\n extends Omit<ComponentProps<typeof ArkTabs.Root>, \"onValueChange\"> {\n onValueChange?: (value: string) => void;\n unstyled?: boolean;\n}\nexport const Tabs = forwardRef<HTMLDivElement, TabsProps>(function Tabs(\n { onValueChange, unstyled, className, ...rest },\n ref\n) {\n return (\n <ArkTabs.Root\n {...rest}\n ref={ref}\n onValueChange={(details) => onValueChange?.(details.value)}\n className={classes(!unstyled && \"dds-tabs-root\", className)}\n />\n );\n});\nexport type TabProps = ComponentProps<typeof ArkTabs.Trigger> & {\n unstyled?: boolean;\n};\nexport type TabPanelProps = ComponentProps<typeof ArkTabs.Content>;\nexport const TabList = forwardRef<\n HTMLDivElement,\n ComponentProps<typeof ArkTabs.List> & { unstyled?: boolean }\n>(function TabList({ unstyled, className, ...rest }, ref) {\n return (\n <ArkTabs.List\n {...rest}\n ref={ref}\n className={classes(!unstyled && \"dds-tabs\", className)}\n />\n );\n});\nexport const Tab = forwardRef<HTMLButtonElement, TabProps>(function Tab(\n { unstyled, className, ...rest },\n ref\n) {\n return (\n <ArkTabs.Trigger\n {...rest}\n ref={ref}\n className={classes(!unstyled && \"dds-tab\", className)}\n />\n );\n});\nexport const TabPanel = forwardRef<HTMLDivElement, TabPanelProps>(\n function TabPanel({ value, style, ...rest }, ref) {\n const tabs = useTabsContext();\n const inactive = tabs.value !== value;\n return (\n <ArkTabs.Content\n {...rest}\n value={value}\n ref={ref}\n hidden={inactive}\n style={inactive ? { ...style, display: \"none\" } : style}\n />\n );\n }\n);\nfunction VisibleRadioInput({ option }: { option: RadioOption }) {\n const group = useRadioGroupContext();\n // Ark owns selection and roving focus; DDS displays the native radio.\n const {\n style: _,\n defaultChecked: __,\n ...inputProps\n } = group.getItemHiddenInputProps(option);\n return (\n <input\n {...inputProps}\n checked={group.value === option.value}\n onChange={() => {}}\n className=\"dds-check__input\"\n />\n );\n}\nexport interface RadioOption {\n value: string;\n label: ReactNode;\n disabled?: boolean;\n}\nexport interface RadioGroupProps\n extends Omit<\n ComponentProps<typeof ArkRadioGroup.Root>,\n \"onValueChange\" | \"children\"\n > {\n options: readonly RadioOption[];\n label: ReactNode;\n onValueChange?: (value: string) => void;\n children?: ReactNode;\n}\nexport const RadioGroup = forwardRef<HTMLDivElement, RadioGroupProps>(\n function RadioGroup(\n { options, label, onValueChange, className, children, ...rest },\n ref\n ) {\n return (\n <ArkRadioGroup.Root\n {...rest}\n ref={ref}\n onValueChange={(details) => {\n if (details.value !== null) onValueChange?.(details.value);\n }}\n className={classes(\"dds-radio-group\", className)}\n >\n <ArkRadioGroup.Label className=\"dds-field__label\">\n {label}\n </ArkRadioGroup.Label>\n {options.map((option) => (\n <ArkRadioGroup.Item\n key={option.value}\n value={option.value}\n disabled={option.disabled}\n className=\"dds-check\"\n >\n <VisibleRadioInput option={option} />\n <ArkRadioGroup.ItemText>{option.label}</ArkRadioGroup.ItemText>\n </ArkRadioGroup.Item>\n ))}\n {children}\n </ArkRadioGroup.Root>\n );\n }\n);\n","import {\n forwardRef,\n type ComponentProps,\n type ButtonHTMLAttributes,\n type ReactNode,\n} from \"react\";\nimport { Dialog as ArkDialog } from \"@ark-ui/react/dialog\";\nimport { Tooltip as ArkTooltip } from \"@ark-ui/react/tooltip\";\nimport { Portal } from \"@ark-ui/react/portal\";\nimport { classes } from \"./controls\";\nexport interface DialogFrameParts {\n title: ReactNode;\n description: ReactNode;\n children: ReactNode;\n actions: ReactNode;\n}\nexport interface DialogProps\n extends Omit<\n ComponentProps<typeof ArkDialog.Root>,\n \"children\" | \"onOpenChange\"\n > {\n title: ReactNode;\n description?: ReactNode;\n children: ReactNode;\n actions?: ReactNode;\n onOpenChange?: (open: boolean) => void;\n closeOnOutside?: boolean;\n portal?: boolean;\n className?: string;\n overlayClassName?: string;\n contentProps?: ComponentProps<typeof ArkDialog.Content>;\n initialFocus?: () => HTMLElement | null | undefined;\n finalFocus?: () => HTMLElement | null | undefined;\n frame?: (parts: DialogFrameParts) => ReactNode;\n unstyled?: boolean;\n}\nexport const Dialog = forwardRef<HTMLDivElement, DialogProps>(function Dialog(\n {\n title,\n description,\n children,\n actions,\n onOpenChange,\n closeOnOutside,\n portal = true,\n className,\n overlayClassName,\n contentProps,\n initialFocus,\n finalFocus,\n frame,\n unstyled,\n ...rest\n },\n ref\n) {\n const parts: DialogFrameParts = {\n title: (\n <ArkDialog.Title className={unstyled ? undefined : \"dds-dialog__title\"}>\n {title}\n </ArkDialog.Title>\n ),\n description: description && (\n <ArkDialog.Description\n className={unstyled ? undefined : \"dds-dialog__body\"}\n >\n {description}\n </ArkDialog.Description>\n ),\n children,\n actions: actions && (\n <div className={unstyled ? undefined : \"dds-dialog__actions\"}>\n {actions}\n </div>\n ),\n };\n const content = (\n <ArkDialog.Positioner\n className={classes(!unstyled && \"dds-dialog-overlay\", overlayClassName)}\n >\n <ArkDialog.Content\n {...contentProps}\n ref={ref}\n aria-describedby={\n description ? contentProps?.[\"aria-describedby\"] : undefined\n }\n className={classes(\n !unstyled && \"dds-dialog\",\n className,\n contentProps?.className\n )}\n >\n {frame ? (\n frame(parts)\n ) : (\n <>\n {parts.title}\n {parts.description}\n {children}\n {parts.actions}\n </>\n )}\n </ArkDialog.Content>\n </ArkDialog.Positioner>\n );\n return (\n <ArkDialog.Root\n {...rest}\n onOpenChange={(details) => onOpenChange?.(details.open)}\n closeOnInteractOutside={closeOnOutside ?? rest.closeOnInteractOutside}\n initialFocusEl={\n initialFocus ? () => initialFocus() ?? null : rest.initialFocusEl\n }\n finalFocusEl={finalFocus ? () => finalFocus() ?? null : rest.finalFocusEl}\n lazyMount\n unmountOnExit\n >\n {portal ? <Portal>{content}</Portal> : content}\n </ArkDialog.Root>\n );\n});\nexport type TooltipTriggerProps = ButtonHTMLAttributes<HTMLButtonElement>;\nexport interface TooltipProps\n extends Omit<\n ComponentProps<typeof ArkTooltip.Root>,\n \"children\" | \"onOpenChange\"\n > {\n content: ReactNode;\n children: ReactNode | ((props: TooltipTriggerProps) => ReactNode);\n onOpenChange?: (open: boolean) => void;\n className?: string;\n contentProps?: ComponentProps<typeof ArkTooltip.Content>;\n}\nexport function Tooltip({\n content,\n children,\n onOpenChange,\n className,\n contentProps,\n ...rest\n}: TooltipProps) {\n return (\n <ArkTooltip.Root\n openDelay={0}\n closeDelay={0}\n {...rest}\n onOpenChange={(details) => onOpenChange?.(details.open)}\n >\n <span className={classes(\"dds-tooltip\", className)}>\n {typeof children === \"function\" ? (\n <ArkTooltip.Context>\n {(api) => children(api.getTriggerProps())}\n </ArkTooltip.Context>\n ) : (\n <ArkTooltip.Trigger asChild>{children}</ArkTooltip.Trigger>\n )}\n <Portal>\n <ArkTooltip.Positioner>\n <ArkTooltip.Content\n {...contentProps}\n className={classes(\n \"dds-tooltip__bubble\",\n contentProps?.className\n )}\n >\n {content}\n </ArkTooltip.Content>\n </ArkTooltip.Positioner>\n </Portal>\n </span>\n </ArkTooltip.Root>\n );\n}\n","import { forwardRef, type SVGProps } from \"react\";\nimport { icons, directionPolicy, type DdsIconName } from \"@devslab/dds-icons\";\nimport { classes } from \"./controls\";\nexport interface IconProps\n extends Omit<SVGProps<SVGSVGElement>, \"name\" | \"children\"> {\n name: DdsIconName;\n label?: string;\n size?: number | string;\n directional?: boolean;\n}\nexport const Icon = forwardRef<SVGSVGElement, IconProps>(function Icon(\n { name, label, size = 24, directional, className, ...rest },\n ref\n) {\n const icon = icons[name];\n return (\n <svg\n {...rest}\n ref={ref}\n viewBox={icon.viewBox}\n width={size}\n height={size}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={icon.strokeWidth}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n role={label ? \"img\" : undefined}\n aria-label={label}\n aria-hidden={label ? undefined : true}\n className={classes(\n (directional ?? directionPolicy.mirrorInRtl.includes(name)) &&\n directionPolicy.cssClass,\n className\n )}\n >\n {label && <title>{label}</title>}\n <g dangerouslySetInnerHTML={{ __html: icon.body }} />\n </svg>\n );\n});\n","import {\n createContext,\n useContext,\n useEffect,\n useId,\n useMemo,\n useRef,\n type ReactNode,\n} from \"react\";\nimport { Toast as ArkToast, Toaster, createToaster } from \"@ark-ui/react/toast\";\nimport { classes } from \"./controls\";\nexport type ToastTone = \"success\" | \"warning\" | \"danger\" | \"info\";\nexport interface ToastInput {\n message: ReactNode;\n tone?: ToastTone;\n duration?: number;\n}\nexport interface ToastRecord extends ToastInput {\n id: string;\n}\nexport interface ToastApi {\n show: (toast: ToastInput) => string;\n dismiss: (id: string) => void;\n clear: () => void;\n}\nexport interface ToastProviderProps {\n children: ReactNode;\n defaultDuration?: number;\n dismissLabel?: string | ((toast: ToastRecord) => string);\n regionLabel?: string;\n className?: string;\n}\nconst ToastContext = createContext<ToastApi | null>(null);\nexport function ToastProvider({\n children,\n defaultDuration = 5000,\n dismissLabel,\n regionLabel,\n className,\n}: ToastProviderProps) {\n const prefix = useId();\n const sequence = useRef(0);\n const toaster = useMemo(\n () =>\n createToaster({\n placement: \"bottom-end\",\n overlap: false,\n gap: 8,\n offsets: \"var(--dds-space-16)\",\n removeDelay: 0,\n hotkey: [\"DDS_NO_HOTKEY\"],\n }),\n []\n );\n const api = useMemo<ToastApi>(() => {\n return {\n show(input) {\n const id = `dds-toast-${prefix}-${++sequence.current}`;\n const duration = input.duration ?? defaultDuration;\n toaster.create({\n id,\n description: input.message,\n type: input.tone === \"danger\" ? \"error\" : input.tone ?? \"info\",\n duration: duration > 0 ? duration : Infinity,\n meta: { dds: { ...input, id } },\n });\n return id;\n },\n dismiss: (id) => toaster.remove(id),\n clear: () => toaster.remove(),\n };\n }, [toaster, prefix, defaultDuration]);\n useEffect(() => () => toaster.remove(), [toaster]);\n return (\n <ToastContext.Provider value={api}>\n {children}\n <Toaster\n toaster={toaster}\n label={regionLabel ?? \"\"}\n aria-label={regionLabel ?? \"\"}\n role={regionLabel ? \"region\" : \"presentation\"}\n className={classes(\"dds-toast-region\", className)}\n >\n {(toast) => {\n const record = toast.meta?.dds as ToastRecord;\n return (\n <ArkToast.Root\n className={classes(\n \"dds-toast\",\n `dds-toast--${record.tone ?? \"info\"}`\n )}\n role={record.tone === \"danger\" ? \"alert\" : \"status\"}\n >\n <ArkToast.Description>{toast.description}</ArkToast.Description>\n {dismissLabel && (\n <ArkToast.CloseTrigger\n className=\"dds-iconbtn dds-iconbtn--sm\"\n aria-label={\n typeof dismissLabel === \"function\"\n ? dismissLabel(record)\n : dismissLabel\n }\n >\n ×\n </ArkToast.CloseTrigger>\n )}\n </ArkToast.Root>\n );\n }}\n </Toaster>\n </ToastContext.Provider>\n );\n}\nexport function useToast(): ToastApi {\n const api = useContext(ToastContext);\n if (!api) throw new Error(\"useToast must be called inside <ToastProvider>\");\n return api;\n}\n","import {\n forwardRef,\n useEffect,\n useId,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\nimport { classes } from \"./controls\";\nexport interface ConsoleNavItem {\n id: string;\n href: string;\n label: string;\n badge?: number;\n active?: boolean;\n}\nexport interface ConsoleNavGroup {\n label: string;\n items: readonly ConsoleNavItem[];\n}\nexport interface ConsoleShellLabels {\n skip: string;\n menuOpen: string;\n menuClose: string;\n nav: string;\n badge: string;\n}\nexport interface ConsoleHeader {\n eyebrow?: string;\n title: string;\n actions?: ReactNode;\n}\nexport interface ConsoleShellProps\n extends Omit<HTMLAttributes<HTMLDivElement>, \"children\" | \"context\"> {\n surface: string;\n activePath: string;\n brand: { href: string; name: string; mark: string };\n context?: readonly { label: string; value: string }[];\n nav: readonly ConsoleNavGroup[];\n labels: ConsoleShellLabels;\n header: ConsoleHeader;\n foot?: ReactNode;\n children: ReactNode;\n}\nfunction isActive(path: string, item: ConsoleNavItem) {\n return (\n item.active ??\n (item.href.split(\"/\").filter(Boolean).length <= 1\n ? path === item.href\n : path === item.href || path.startsWith(`${item.href}/`))\n );\n}\nexport const ConsoleShell = forwardRef<HTMLDivElement, ConsoleShellProps>(\n function ConsoleShell(\n {\n surface,\n activePath,\n brand,\n context,\n nav,\n labels,\n header,\n foot,\n children,\n className,\n ...rest\n },\n ref\n ) {\n const [open, setOpen] = useState(false);\n const [hydrated, setHydrated] = useState(false);\n const id = useId();\n const railId = `dds-console-rail-${id}`;\n const mainId = `dds-console-main-${id}`;\n useEffect(() => {\n setHydrated(true);\n const onKey = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") setOpen(false);\n };\n document.addEventListener(\"keydown\", onKey);\n return () => document.removeEventListener(\"keydown\", onKey);\n }, []);\n return (\n <div\n {...rest}\n ref={ref}\n className={classes(\"dds-console-shell\", className)}\n data-surface={surface}\n data-hydrated={hydrated ? \"true\" : undefined}\n >\n <a className=\"dds-console-skip dds-visually-hidden\" href={`#${mainId}`}>\n {labels.skip}\n </a>\n <button\n className=\"dds-console-rail__toggle\"\n type=\"button\"\n data-action=\"toggle-rail\"\n aria-controls={railId}\n aria-expanded={open}\n onClick={() => setOpen(!open)}\n >\n <span aria-hidden />\n <span className=\"dds-visually-hidden\">\n {open ? labels.menuClose : labels.menuOpen}\n </span>\n </button>\n <div\n className=\"dds-console-rail__scrim\"\n data-open={String(open)}\n onClick={() => setOpen(false)}\n />\n <aside\n id={railId}\n className=\"dds-console-rail\"\n data-open={String(open)}\n >\n <a className=\"dds-console-rail__brand\" href={brand.href}>\n <img src={brand.mark} alt=\"\" width={20} height={20} />\n <strong>{brand.name}</strong>\n </a>\n {context && context.length > 0 && (\n <dl className=\"dds-console-rail__context\">\n {context.map((row, index) => (\n <div key={index}>\n <dt>{row.label}</dt>\n <dd>{row.value}</dd>\n </div>\n ))}\n </dl>\n )}\n <nav className=\"dds-console-rail__nav\" aria-label={labels.nav}>\n {nav.map((group, index) => (\n <section\n key={index}\n className=\"dds-console-rail__group\"\n aria-labelledby={`${id}-group-${index}`}\n >\n <h2\n id={`${id}-group-${index}`}\n className=\"dds-console-rail__group-label\"\n >\n {group.label}\n </h2>\n <ul>\n {group.items.map((item) => (\n <li key={item.id}>\n <a\n className=\"dds-console-rail__item\"\n data-nav={`${surface}.${item.id}`}\n href={item.href}\n aria-current={\n isActive(activePath, item) ? \"page\" : undefined\n }\n onClick={() => setOpen(false)}\n >\n <span>{item.label}</span>\n {item.badge !== undefined && item.badge > 0 && (\n <span\n className=\"dds-console-rail__badge\"\n aria-label={labels.badge.replace(\"{count}\", () =>\n String(item.badge)\n )}\n >\n {item.badge}\n </span>\n )}\n </a>\n </li>\n ))}\n </ul>\n </section>\n ))}\n </nav>\n {foot && <div className=\"dds-console-rail__foot\">{foot}</div>}\n </aside>\n <main id={mainId} className=\"dds-console-main\" tabIndex={-1}>\n <header className=\"dds-console-page-header\">\n <div className=\"dds-console-page-header__text\">\n {header.eyebrow && (\n <p className=\"dds-console-page-eyebrow\">{header.eyebrow}</p>\n )}\n <h1>{header.title}</h1>\n </div>\n {header.actions && (\n <div className=\"dds-console-page-header__actions\">\n {header.actions}\n </div>\n )}\n </header>\n {children}\n </main>\n </div>\n );\n }\n);\n","export type StatusTone = \"success\" | \"warning\" | \"danger\" | \"info\" | \"brand\" | \"neutral\";\nexport function createStatusPill<D extends string>(config:{\n tones:Record<D,Record<string,StatusTone>>;\n label:(domain:D,value:string,locale:string)=>string|undefined;\n openDomains?:readonly NoInfer<D>[];\n}){\n const open=new Set<string>(config.openDomains??[]);\n return function StatusPill(props:{domain:D;value:string;locale:string}){\n const tone=config.tones[props.domain]?.[props.value];\n const label=config.label(props.domain,props.value,props.locale);\n if(!tone||!label){\n if(open.has(props.domain))return <code data-status={`${props.domain}.${props.value}`}>{props.value}</code>;\n throw new Error(!tone?`StatusPill: no tone for ${props.domain}.${props.value}`:`StatusPill: no label for ${props.domain}.${props.value}`);\n }\n return <span className={tone==='neutral'?'dds-badge':`dds-badge dds-badge--${tone}`} data-status={`${props.domain}.${props.value}`} data-tone={tone}>{label}</span>;\n };\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n\n/** Options for one `run` call. */\nexport interface PendingActionRunOptions {\n /**\n * Start even while another action runs: that one is aborted and this one takes its place, so the\n * latest request wins (a list reload after typing, paging or sorting). Without it a second start\n * while one runs is ignored, which is what a button wants.\n */\n replace?: boolean;\n}\n\n/**\n * Which of a screen's actions is running. A screen with several buttons gives each one its own\n * key, so only the button that started the work shows progress, while every other control can\n * still be locked through `busy`. One shared flag for all the buttons spins every one of them.\n * The same contract as `createPendingAction` in `@devslab/dds-solid`, with values for accessors.\n */\nexport interface PendingAction<K extends string = string> {\n /** The key of the action now running, or null. */\n readonly current: K | null;\n /** True while any action runs: lock the other controls with it. */\n readonly busy: boolean;\n /** True while `key` is the running action: give that control its progress state. */\n is(key: K): boolean;\n /**\n * Runs `task` as `key` and clears the state when it settles, whether it resolves or throws (the\n * error reaches the caller). While another action runs it does nothing and resolves to undefined,\n * unless `replace` is set. The task receives a signal that aborts when this run stops counting:\n * `reset()`, a run that replaced it, or the component unmounting. Check `signal.aborted` after\n * each await before touching state, or pass the signal to `fetch`.\n */\n run<T>(key: K, task: (signal: AbortSignal) => T | Promise<T>, options?: PendingActionRunOptions): Promise<T | undefined>;\n /** Stops tracking the running action and aborts its signal, for example when the screen's data was replaced. */\n reset(): void;\n}\n\n/** Tracks the running action of a component. */\nexport function usePendingAction<K extends string = string>(): PendingAction<K> {\n const [current, setCurrent] = useState<K | null>(null);\n // State lands on the next render; the ref answers a second click in the same event loop turn.\n const active = useRef<AbortController | null>(null);\n useEffect(() => () => {\n active.current?.abort();\n active.current = null;\n }, []);\n const run = useCallback(async <T,>(\n key: K,\n task: (signal: AbortSignal) => T | Promise<T>,\n options?: PendingActionRunOptions,\n ): Promise<T | undefined> => {\n if (active.current && !options?.replace) return undefined;\n active.current?.abort();\n const controller = new AbortController();\n active.current = controller;\n setCurrent(key);\n try {\n return await task(controller.signal);\n } finally {\n if (active.current === controller) {\n active.current = null;\n setCurrent(null);\n }\n }\n }, []);\n const reset = useCallback(() => {\n active.current?.abort();\n active.current = null;\n setCurrent(null);\n }, []);\n return useMemo(() => ({\n current,\n busy: current !== null,\n is: (key: K) => current === key,\n run,\n reset,\n }), [current, run, reset]);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/selection.tsx","../src/overlays.tsx","../src/icon.tsx","../src/toast.tsx","../src/layout.tsx","../src/left-nav.tsx","../src/console-shell.tsx","../src/top-nav.tsx","../src/status-pill.tsx","../src/pending-action.ts"],"sourcesContent":["import { forwardRef, type ComponentProps, type ReactNode } from \"react\";\nimport { Tabs as ArkTabs, useTabsContext } from \"@ark-ui/react/tabs\";\nimport {\n RadioGroup as ArkRadioGroup,\n useRadioGroupContext,\n} from \"@ark-ui/react/radio-group\";\nimport { classes } from \"./controls\";\nexport interface TabsProps\n extends Omit<ComponentProps<typeof ArkTabs.Root>, \"onValueChange\"> {\n onValueChange?: (value: string) => void;\n unstyled?: boolean;\n}\nexport const Tabs = forwardRef<HTMLDivElement, TabsProps>(function Tabs(\n { onValueChange, unstyled, className, ...rest },\n ref\n) {\n return (\n <ArkTabs.Root\n {...rest}\n ref={ref}\n onValueChange={(details) => onValueChange?.(details.value)}\n className={classes(!unstyled && \"dds-tabs-root\", className)}\n />\n );\n});\nexport type TabProps = ComponentProps<typeof ArkTabs.Trigger> & {\n unstyled?: boolean;\n};\nexport type TabPanelProps = ComponentProps<typeof ArkTabs.Content>;\nexport const TabList = forwardRef<\n HTMLDivElement,\n ComponentProps<typeof ArkTabs.List> & { unstyled?: boolean }\n>(function TabList({ unstyled, className, ...rest }, ref) {\n return (\n <ArkTabs.List\n {...rest}\n ref={ref}\n className={classes(!unstyled && \"dds-tabs\", className)}\n />\n );\n});\nexport const Tab = forwardRef<HTMLButtonElement, TabProps>(function Tab(\n { unstyled, className, ...rest },\n ref\n) {\n return (\n <ArkTabs.Trigger\n {...rest}\n ref={ref}\n className={classes(!unstyled && \"dds-tab\", className)}\n />\n );\n});\nexport const TabPanel = forwardRef<HTMLDivElement, TabPanelProps>(\n function TabPanel({ value, style, ...rest }, ref) {\n const tabs = useTabsContext();\n const inactive = tabs.value !== value;\n return (\n <ArkTabs.Content\n {...rest}\n value={value}\n ref={ref}\n hidden={inactive}\n style={inactive ? { ...style, display: \"none\" } : style}\n />\n );\n }\n);\nfunction VisibleRadioInput({ option }: { option: RadioOption }) {\n const group = useRadioGroupContext();\n // Ark owns selection and roving focus; DDS displays the native radio.\n const {\n style: _,\n defaultChecked: __,\n ...inputProps\n } = group.getItemHiddenInputProps(option);\n return (\n <input\n {...inputProps}\n checked={group.value === option.value}\n onChange={() => {}}\n className=\"dds-check__input\"\n />\n );\n}\nexport interface RadioOption {\n value: string;\n label: ReactNode;\n disabled?: boolean;\n}\nexport interface RadioGroupProps\n extends Omit<\n ComponentProps<typeof ArkRadioGroup.Root>,\n \"onValueChange\" | \"children\"\n > {\n options: readonly RadioOption[];\n label: ReactNode;\n onValueChange?: (value: string) => void;\n children?: ReactNode;\n}\nexport const RadioGroup = forwardRef<HTMLDivElement, RadioGroupProps>(\n function RadioGroup(\n { options, label, onValueChange, className, children, ...rest },\n ref\n ) {\n return (\n <ArkRadioGroup.Root\n {...rest}\n ref={ref}\n onValueChange={(details) => {\n if (details.value !== null) onValueChange?.(details.value);\n }}\n className={classes(\"dds-radio-group\", className)}\n >\n <ArkRadioGroup.Label className=\"dds-field__label\">\n {label}\n </ArkRadioGroup.Label>\n {options.map((option) => (\n <ArkRadioGroup.Item\n key={option.value}\n value={option.value}\n disabled={option.disabled}\n className=\"dds-check\"\n >\n <VisibleRadioInput option={option} />\n <ArkRadioGroup.ItemText>{option.label}</ArkRadioGroup.ItemText>\n </ArkRadioGroup.Item>\n ))}\n {children}\n </ArkRadioGroup.Root>\n );\n }\n);\n","import {\n forwardRef,\n type ComponentProps,\n type ButtonHTMLAttributes,\n type ReactNode,\n} from \"react\";\nimport { Dialog as ArkDialog } from \"@ark-ui/react/dialog\";\nimport { Tooltip as ArkTooltip } from \"@ark-ui/react/tooltip\";\nimport { Portal } from \"@ark-ui/react/portal\";\nimport { classes } from \"./controls\";\nexport interface DialogFrameParts {\n title: ReactNode;\n description: ReactNode;\n children: ReactNode;\n actions: ReactNode;\n}\nexport interface DialogProps\n extends Omit<\n ComponentProps<typeof ArkDialog.Root>,\n \"children\" | \"onOpenChange\"\n > {\n title: ReactNode;\n description?: ReactNode;\n children: ReactNode;\n actions?: ReactNode;\n onOpenChange?: (open: boolean) => void;\n closeOnOutside?: boolean;\n portal?: boolean;\n className?: string;\n overlayClassName?: string;\n contentProps?: ComponentProps<typeof ArkDialog.Content>;\n initialFocus?: () => HTMLElement | null | undefined;\n finalFocus?: () => HTMLElement | null | undefined;\n frame?: (parts: DialogFrameParts) => ReactNode;\n unstyled?: boolean;\n}\nexport const Dialog = forwardRef<HTMLDivElement, DialogProps>(function Dialog(\n {\n title,\n description,\n children,\n actions,\n onOpenChange,\n closeOnOutside,\n portal = true,\n className,\n overlayClassName,\n contentProps,\n initialFocus,\n finalFocus,\n frame,\n unstyled,\n ...rest\n },\n ref\n) {\n const parts: DialogFrameParts = {\n title: (\n <ArkDialog.Title className={unstyled ? undefined : \"dds-dialog__title\"}>\n {title}\n </ArkDialog.Title>\n ),\n description: description && (\n <ArkDialog.Description\n className={unstyled ? undefined : \"dds-dialog__body\"}\n >\n {description}\n </ArkDialog.Description>\n ),\n children,\n actions: actions && (\n <div className={unstyled ? undefined : \"dds-dialog__actions\"}>\n {actions}\n </div>\n ),\n };\n const content = (\n <ArkDialog.Positioner\n className={classes(!unstyled && \"dds-dialog-overlay\", overlayClassName)}\n >\n <ArkDialog.Content\n {...contentProps}\n ref={ref}\n aria-describedby={\n description ? contentProps?.[\"aria-describedby\"] : undefined\n }\n className={classes(\n !unstyled && \"dds-dialog\",\n className,\n contentProps?.className\n )}\n >\n {frame ? (\n frame(parts)\n ) : (\n <>\n {parts.title}\n {parts.description}\n {children}\n {parts.actions}\n </>\n )}\n </ArkDialog.Content>\n </ArkDialog.Positioner>\n );\n return (\n <ArkDialog.Root\n {...rest}\n onOpenChange={(details) => onOpenChange?.(details.open)}\n closeOnInteractOutside={closeOnOutside ?? rest.closeOnInteractOutside}\n initialFocusEl={\n initialFocus ? () => initialFocus() ?? null : rest.initialFocusEl\n }\n finalFocusEl={finalFocus ? () => finalFocus() ?? null : rest.finalFocusEl}\n lazyMount\n unmountOnExit\n >\n {portal ? <Portal>{content}</Portal> : content}\n </ArkDialog.Root>\n );\n});\nexport type TooltipTriggerProps = ButtonHTMLAttributes<HTMLButtonElement>;\nexport interface TooltipProps\n extends Omit<\n ComponentProps<typeof ArkTooltip.Root>,\n \"children\" | \"onOpenChange\"\n > {\n content: ReactNode;\n children: ReactNode | ((props: TooltipTriggerProps) => ReactNode);\n onOpenChange?: (open: boolean) => void;\n className?: string;\n contentProps?: ComponentProps<typeof ArkTooltip.Content>;\n}\nexport function Tooltip({\n content,\n children,\n onOpenChange,\n className,\n contentProps,\n ...rest\n}: TooltipProps) {\n return (\n <ArkTooltip.Root\n openDelay={0}\n closeDelay={0}\n {...rest}\n onOpenChange={(details) => onOpenChange?.(details.open)}\n >\n <span className={classes(\"dds-tooltip\", className)}>\n {typeof children === \"function\" ? (\n <ArkTooltip.Context>\n {(api) => children(api.getTriggerProps())}\n </ArkTooltip.Context>\n ) : (\n <ArkTooltip.Trigger asChild>{children}</ArkTooltip.Trigger>\n )}\n <Portal>\n <ArkTooltip.Positioner>\n <ArkTooltip.Content\n {...contentProps}\n className={classes(\n \"dds-tooltip__bubble\",\n contentProps?.className\n )}\n >\n {content}\n </ArkTooltip.Content>\n </ArkTooltip.Positioner>\n </Portal>\n </span>\n </ArkTooltip.Root>\n );\n}\n","import { forwardRef, type SVGProps } from \"react\";\nimport { icons, directionPolicy, type DdsIconName } from \"@devslab/dds-icons\";\nimport { classes } from \"./controls\";\nexport interface IconProps\n extends Omit<SVGProps<SVGSVGElement>, \"name\" | \"children\"> {\n name: DdsIconName;\n label?: string;\n size?: number | string;\n directional?: boolean;\n}\nexport const Icon = forwardRef<SVGSVGElement, IconProps>(function Icon(\n { name, label, size = 24, directional, className, ...rest },\n ref\n) {\n const icon = icons[name];\n return (\n <svg\n {...rest}\n ref={ref}\n viewBox={icon.viewBox}\n width={size}\n height={size}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={icon.strokeWidth}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n role={label ? \"img\" : undefined}\n aria-label={label}\n aria-hidden={label ? undefined : true}\n className={classes(\n (directional ?? directionPolicy.mirrorInRtl.includes(name)) &&\n directionPolicy.cssClass,\n className\n )}\n >\n {label && <title>{label}</title>}\n <g dangerouslySetInnerHTML={{ __html: icon.body }} />\n </svg>\n );\n});\n","import {\n createContext,\n useContext,\n useEffect,\n useId,\n useMemo,\n useRef,\n type ReactNode,\n} from \"react\";\nimport { Toast as ArkToast, Toaster, createToaster } from \"@ark-ui/react/toast\";\nimport { classes } from \"./controls\";\nexport type ToastTone = \"success\" | \"warning\" | \"danger\" | \"info\";\nexport interface ToastInput {\n message: ReactNode;\n tone?: ToastTone;\n duration?: number;\n}\nexport interface ToastRecord extends ToastInput {\n id: string;\n}\nexport interface ToastApi {\n show: (toast: ToastInput) => string;\n dismiss: (id: string) => void;\n clear: () => void;\n}\nexport interface ToastProviderProps {\n children: ReactNode;\n defaultDuration?: number;\n dismissLabel?: string | ((toast: ToastRecord) => string);\n regionLabel?: string;\n className?: string;\n}\nconst ToastContext = createContext<ToastApi | null>(null);\nexport function ToastProvider({\n children,\n defaultDuration = 5000,\n dismissLabel,\n regionLabel,\n className,\n}: ToastProviderProps) {\n const prefix = useId();\n const sequence = useRef(0);\n const toaster = useMemo(\n () =>\n createToaster({\n placement: \"bottom-end\",\n overlap: false,\n gap: 8,\n offsets: \"var(--dds-space-16)\",\n removeDelay: 0,\n hotkey: [\"DDS_NO_HOTKEY\"],\n }),\n []\n );\n const api = useMemo<ToastApi>(() => {\n return {\n show(input) {\n const id = `dds-toast-${prefix}-${++sequence.current}`;\n const duration = input.duration ?? defaultDuration;\n toaster.create({\n id,\n description: input.message,\n type: input.tone === \"danger\" ? \"error\" : input.tone ?? \"info\",\n duration: duration > 0 ? duration : Infinity,\n meta: { dds: { ...input, id } },\n });\n return id;\n },\n dismiss: (id) => toaster.remove(id),\n clear: () => toaster.remove(),\n };\n }, [toaster, prefix, defaultDuration]);\n useEffect(() => () => toaster.remove(), [toaster]);\n return (\n <ToastContext.Provider value={api}>\n {children}\n <Toaster\n toaster={toaster}\n label={regionLabel ?? \"\"}\n aria-label={regionLabel ?? \"\"}\n role={regionLabel ? \"region\" : \"presentation\"}\n className={classes(\"dds-toast-region\", className)}\n >\n {(toast) => {\n const record = toast.meta?.dds as ToastRecord;\n return (\n <ArkToast.Root\n className={classes(\n \"dds-toast\",\n `dds-toast--${record.tone ?? \"info\"}`\n )}\n role={record.tone === \"danger\" ? \"alert\" : \"status\"}\n >\n <ArkToast.Description>{toast.description}</ArkToast.Description>\n {dismissLabel && (\n <ArkToast.CloseTrigger\n className=\"dds-iconbtn dds-iconbtn--sm\"\n aria-label={\n typeof dismissLabel === \"function\"\n ? dismissLabel(record)\n : dismissLabel\n }\n >\n ×\n </ArkToast.CloseTrigger>\n )}\n </ArkToast.Root>\n );\n }}\n </Toaster>\n </ToastContext.Provider>\n );\n}\nexport function useToast(): ToastApi {\n const api = useContext(ToastContext);\n if (!api) throw new Error(\"useToast must be called inside <ToastProvider>\");\n return api;\n}\n","import {\n forwardRef,\n useEffect,\n useId,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\nimport { classes } from \"./controls\";\nexport interface LayoutProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n \"children\"\n> {\n navigationPosition?: \"left\" | \"top\";\n contentWidth?: \"workspace\" | \"form\" | \"settings\" | \"full\";\n labels: { skip: string; menuOpen: string; menuClose: string };\n header?: ReactNode;\n navigation?: ReactNode;\n railStart?: ReactNode;\n railEnd?: ReactNode;\n footer?: ReactNode;\n children: ReactNode;\n surface?: string;\n}\nexport const Layout = forwardRef<HTMLDivElement, LayoutProps>(function Layout(\n {\n navigationPosition = \"left\",\n contentWidth = \"workspace\",\n labels,\n header,\n navigation,\n railStart,\n railEnd,\n footer,\n children,\n surface,\n className,\n ...rest\n },\n ref,\n) {\n const id = useId(),\n railId = `dds-console-rail-${id}`,\n mainId = `dds-console-main-${id}`;\n const [open, setOpen] = useState(false),\n [hydrated, setHydrated] = useState(false);\n const toggle = useRef<HTMLButtonElement>(null),\n rail = useRef<HTMLElement>(null);\n function close() {\n setOpen(false);\n toggle.current?.focus();\n }\n useEffect(() => {\n setHydrated(true);\n if (typeof window.matchMedia !== \"function\") return;\n const media = window.matchMedia(\"(max-width: 56.25rem)\");\n const resize = () => {\n if (!media.matches) setOpen(false);\n };\n media.addEventListener(\"change\", resize);\n return () => media.removeEventListener(\"change\", resize);\n }, []);\n useEffect(() => {\n if (!open) return;\n const focusable = () =>\n [\n toggle.current,\n ...Array.from(\n rail.current?.querySelectorAll<HTMLElement>(\n 'a[href],button,summary,input,select,textarea,[tabindex=\"0\"]',\n ) ?? [],\n ),\n ].filter(\n (el): el is HTMLElement =>\n !!el &&\n !el.closest(\"[hidden]\") &&\n el.getClientRects().length > 0 &&\n getComputedStyle(el).visibility !== \"hidden\" &&\n !Array.from(\n rail.current?.querySelectorAll(\"details:not([open])\") ?? [],\n ).some(\n (details) =>\n details.contains(el) &&\n !details.querySelector(\"summary\")?.contains(el),\n ) &&\n !el.hasAttribute(\"disabled\"),\n );\n focusable()[1]?.focus();\n function key(event: KeyboardEvent) {\n if (event.key === \"Escape\") {\n event.preventDefault();\n close();\n }\n if (event.key === \"Tab\") {\n const items = focusable(),\n first = items[0],\n last = items.at(-1);\n if (event.shiftKey && document.activeElement === first) {\n event.preventDefault();\n last?.focus();\n } else if (!event.shiftKey && document.activeElement === last) {\n event.preventDefault();\n first?.focus();\n }\n }\n }\n document.addEventListener(\"keydown\", key);\n return () => {\n document.removeEventListener(\"keydown\", key);\n };\n }, [open]);\n return (\n <div\n {...rest}\n ref={ref}\n className={classes(\"dds-console-shell dds-layout\", className)}\n data-navigation-position={navigationPosition}\n data-surface={surface}\n data-hydrated={hydrated ? \"true\" : undefined}\n >\n <a className=\"dds-console-skip dds-visually-hidden\" href={`#${mainId}`}>\n {labels.skip}\n </a>\n <button\n ref={toggle}\n className=\"dds-console-rail__toggle\"\n type=\"button\"\n data-action=\"toggle-rail\"\n aria-controls={railId}\n aria-expanded={open}\n onClick={() => (open ? close() : setOpen(true))}\n >\n <span aria-hidden />\n <span className=\"dds-visually-hidden\">\n {open ? labels.menuClose : labels.menuOpen}\n </span>\n </button>\n <div\n className=\"dds-console-rail__scrim\"\n data-open={String(open)}\n onClick={close}\n />\n <aside\n ref={rail}\n id={railId}\n className=\"dds-console-rail dds-layout__navigation\"\n data-open={String(open)}\n onClick={(event) => {\n if (\n open &&\n event.target instanceof Element &&\n event.target.closest(\"a[href]\")\n )\n close();\n }}\n >\n {railStart}\n {navigation}\n {railEnd}\n </aside>\n <main\n id={mainId}\n className=\"dds-console-main dds-layout__main\"\n tabIndex={-1}\n >\n <div className=\"dds-layout__content\" data-width={contentWidth}>\n {header != null && (\n <header className=\"dds-layout__header\">{header}</header>\n )}\n {children}\n {footer != null && (\n <footer className=\"dds-layout__footer\">{footer}</footer>\n )}\n </div>\n </main>\n </div>\n );\n});\n","import { useId, useState, type ReactNode } from \"react\";\nexport interface ConsoleNavItem {\n id: string;\n href: string;\n label: string;\n /** Decorative icon; the label supplies the accessible name. */\n icon?: ReactNode;\n badge?: number;\n active?: boolean;\n}\nexport interface ConsoleNavGroup {\n /** Stable key for expansion state. Falls back to the group index. */\n id?: string;\n /** Opt in to a disclosure button; legacy groups remain expanded. */\n collapsible?: boolean;\n label: string;\n items: readonly ConsoleNavItem[];\n}\nexport interface LeftNavProps {\n surface: string;\n activePath: string;\n nav: readonly ConsoleNavGroup[];\n labels: { nav: string; badge: string };\n expandedGroups?: readonly string[];\n defaultExpandedGroups?: readonly string[];\n onExpandedGroupsChange?: (groupIds: string[]) => void;\n onNavigate?: () => void;\n}\nfunction isActive(path: string, item: ConsoleNavItem) {\n return (\n item.active ??\n (item.href.split(\"/\").filter(Boolean).length <= 1\n ? path === item.href\n : path === item.href || path.startsWith(`${item.href}/`))\n );\n}\nexport function LeftNav({\n surface,\n activePath,\n nav,\n labels,\n expandedGroups,\n defaultExpandedGroups,\n onExpandedGroupsChange,\n onNavigate,\n}: LeftNavProps) {\n const id = useId();\n const [internalExpandedGroups, setInternalExpandedGroups] = useState<\n readonly string[]\n >(\n () =>\n defaultExpandedGroups ??\n nav.flatMap((group, index) =>\n group.collapsible &&\n group.items.some((item) => isActive(activePath, item))\n ? [group.id ?? `group-${index}`]\n : [],\n ),\n );\n const expanded = expandedGroups ?? internalExpandedGroups;\n function toggleGroup(groupId: string) {\n const next = expanded.includes(groupId)\n ? expanded.filter((value) => value !== groupId)\n : [...expanded, groupId];\n if (expandedGroups === undefined) setInternalExpandedGroups(next);\n onExpandedGroupsChange?.(next);\n }\n return (\n <nav className=\"dds-console-rail__nav dds-left-nav\" aria-label={labels.nav}>\n {nav.map((group, index) => (\n <section\n key={group.id ?? index}\n data-collapsible={group.collapsible ? \"true\" : undefined}\n className=\"dds-console-rail__group\"\n aria-labelledby={`${id}-group-${index}`}\n >\n <h2\n id={`${id}-group-${index}`}\n className=\"dds-console-rail__group-label\"\n >\n {group.collapsible ? (\n <button\n type=\"button\"\n className=\"dds-console-rail__group-toggle\"\n aria-expanded={expanded.includes(group.id ?? `group-${index}`)}\n aria-controls={`${id}-group-items-${index}`}\n onClick={() => toggleGroup(group.id ?? `group-${index}`)}\n >\n <span>{group.label}</span>\n <span\n className=\"dds-console-rail__chevron\"\n aria-hidden=\"true\"\n />\n </button>\n ) : (\n group.label\n )}\n </h2>\n <ul\n id={`${id}-group-items-${index}`}\n hidden={\n group.collapsible &&\n !expanded.includes(group.id ?? `group-${index}`)\n }\n >\n {group.items.map((item) => (\n <li key={item.id}>\n <a\n className=\"dds-console-rail__item\"\n data-nav={`${surface}.${item.id}`}\n href={item.href}\n aria-current={isActive(activePath, item) ? \"page\" : undefined}\n onClick={onNavigate}\n >\n {item.icon != null ? (\n <span className=\"dds-console-rail__item-content\">\n <span\n className=\"dds-console-rail__item-icon\"\n aria-hidden=\"true\"\n >\n {item.icon}\n </span>\n <span>{item.label}</span>\n </span>\n ) : (\n <span>{item.label}</span>\n )}\n {item.badge !== undefined && item.badge > 0 && (\n <span\n className=\"dds-console-rail__badge\"\n aria-label={labels.badge.replace(\"{count}\", () =>\n String(item.badge),\n )}\n >\n {item.badge}\n </span>\n )}\n </a>\n </li>\n ))}\n </ul>\n </section>\n ))}\n </nav>\n );\n}\n","import { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { Layout } from \"./layout\";\nimport { LeftNav, type ConsoleNavGroup } from \"./left-nav\";\nexport type { ConsoleNavItem, ConsoleNavGroup } from \"./left-nav\";\nexport interface ConsoleShellLabels {\n skip: string;\n menuOpen: string;\n menuClose: string;\n nav: string;\n badge: string;\n}\nexport interface ConsoleHeader {\n eyebrow?: string;\n title: string;\n actions?: ReactNode;\n}\nexport interface ConsoleShellProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n \"children\" | \"context\"\n> {\n surface: string;\n activePath: string;\n brand: { href: string; name: string; mark: string };\n context?: readonly { label: string; value: string }[];\n nav?: readonly ConsoleNavGroup[];\n /** Supply a standalone LeftNav or custom navigation. */\n navigation?: ReactNode;\n expandedGroups?: readonly string[];\n defaultExpandedGroups?: readonly string[];\n onExpandedGroupsChange?: (groupIds: string[]) => void;\n labels: ConsoleShellLabels;\n header: ConsoleHeader;\n foot?: ReactNode;\n children: ReactNode;\n}\nexport const ConsoleShell = forwardRef<HTMLDivElement, ConsoleShellProps>(\n function ConsoleShell(\n {\n surface,\n activePath,\n brand,\n context,\n nav = [],\n navigation,\n expandedGroups,\n defaultExpandedGroups,\n onExpandedGroupsChange,\n labels,\n header,\n foot,\n children,\n ...rest\n },\n ref,\n ) {\n return (\n <Layout\n {...rest}\n ref={ref}\n surface={surface}\n labels={labels}\n railStart={\n <>\n <a className=\"dds-console-rail__brand\" href={brand.href}>\n <img src={brand.mark} alt=\"\" width={20} height={20} />\n <strong>{brand.name}</strong>\n </a>\n {context && context.length > 0 && (\n <dl className=\"dds-console-rail__context\">\n {context.map((row, index) => (\n <div key={index}>\n <dt>{row.label}</dt>\n <dd>{row.value}</dd>\n </div>\n ))}\n </dl>\n )}\n </>\n }\n navigation={\n navigation ?? (\n <LeftNav\n surface={surface}\n activePath={activePath}\n nav={nav}\n labels={labels}\n expandedGroups={expandedGroups}\n defaultExpandedGroups={defaultExpandedGroups}\n onExpandedGroupsChange={onExpandedGroupsChange}\n />\n )\n }\n railEnd={foot && <div className=\"dds-console-rail__foot\">{foot}</div>}\n header={\n <div className=\"dds-console-page-header\">\n <div className=\"dds-console-page-header__text\">\n {header.eyebrow && (\n <p className=\"dds-console-page-eyebrow\">{header.eyebrow}</p>\n )}\n <h1>{header.title}</h1>\n </div>\n {header.actions && (\n <div className=\"dds-console-page-header__actions\">\n {header.actions}\n </div>\n )}\n </div>\n }\n >\n {children}\n </Layout>\n );\n },\n);\n","import { useEffect, useRef } from \"react\";\nimport type { LeftNavProps } from \"./left-nav\";\nexport type TopNavProps = Pick<\n LeftNavProps,\n \"surface\" | \"activePath\" | \"nav\" | \"labels\" | \"onNavigate\"\n>;\nexport function TopNav({\n surface,\n activePath,\n nav,\n labels,\n onNavigate,\n}: TopNavProps) {\n const root = useRef<HTMLElement>(null);\n useEffect(() => {\n function outside(event: PointerEvent) {\n if (!root.current?.contains(event.target as Node))\n root.current\n ?.querySelectorAll(\"details[open]\")\n .forEach((el) => el.removeAttribute(\"open\"));\n }\n document.addEventListener(\"pointerdown\", outside);\n return () => document.removeEventListener(\"pointerdown\", outside);\n }, []);\n return (\n <nav\n ref={root}\n className=\"dds-top-nav\"\n aria-label={labels.nav}\n onKeyDown={(event) => {\n if (event.key !== \"Escape\") return;\n const details = (event.target as Element).closest(\"details\");\n if (details?.open) {\n event.preventDefault();\n event.stopPropagation();\n details.open = false;\n details.querySelector(\"summary\")?.focus();\n }\n }}\n >\n {nav.map((group, index) => (\n <details key={group.id ?? index} className=\"dds-top-nav__group\">\n <summary className=\"dds-top-nav__trigger\">{group.label}</summary>\n <ul className=\"dds-top-nav__items\">\n {group.items.map((item) => (\n <li key={item.id}>\n <a\n className=\"dds-top-nav__item\"\n data-nav={`${surface}.${item.id}`}\n href={item.href}\n aria-current={\n (item.active ??\n (activePath === item.href ||\n (item.href.split(\"/\").filter(Boolean).length > 1 &&\n activePath.startsWith(`${item.href}/`))))\n ? \"page\"\n : undefined\n }\n onClick={(event) => {\n event.currentTarget\n .closest(\"details\")\n ?.removeAttribute(\"open\");\n onNavigate?.();\n }}\n >\n {item.icon != null && (\n <span className=\"dds-top-nav__item-icon\" aria-hidden=\"true\">\n {item.icon}\n </span>\n )}\n <span>{item.label}</span>\n {item.badge != null && item.badge > 0 && (\n <span\n className=\"dds-console-rail__badge\"\n aria-label={labels.badge.replace(\"{count}\", () =>\n String(item.badge),\n )}\n >\n {item.badge}\n </span>\n )}\n </a>\n </li>\n ))}\n </ul>\n </details>\n ))}\n </nav>\n );\n}\n","export type StatusTone = \"success\" | \"warning\" | \"danger\" | \"info\" | \"brand\" | \"neutral\";\nexport function createStatusPill<D extends string>(config:{\n tones:Record<D,Record<string,StatusTone>>;\n label:(domain:D,value:string,locale:string)=>string|undefined;\n openDomains?:readonly NoInfer<D>[];\n}){\n const open=new Set<string>(config.openDomains??[]);\n return function StatusPill(props:{domain:D;value:string;locale:string}){\n const tone=config.tones[props.domain]?.[props.value];\n const label=config.label(props.domain,props.value,props.locale);\n if(!tone||!label){\n if(open.has(props.domain))return <code data-status={`${props.domain}.${props.value}`}>{props.value}</code>;\n throw new Error(!tone?`StatusPill: no tone for ${props.domain}.${props.value}`:`StatusPill: no label for ${props.domain}.${props.value}`);\n }\n return <span className={tone==='neutral'?'dds-badge':`dds-badge dds-badge--${tone}`} data-status={`${props.domain}.${props.value}`} data-tone={tone}>{label}</span>;\n };\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n\n/** Options for one `run` call. */\nexport interface PendingActionRunOptions {\n /**\n * Start even while another action runs: that one is aborted and this one takes its place, so the\n * latest request wins (a list reload after typing, paging or sorting). Without it a second start\n * while one runs is ignored, which is what a button wants.\n */\n replace?: boolean;\n}\n\n/**\n * Which of a screen's actions is running. A screen with several buttons gives each one its own\n * key, so only the button that started the work shows progress, while every other control can\n * still be locked through `busy`. One shared flag for all the buttons spins every one of them.\n * The same contract as `createPendingAction` in `@devslab/dds-solid`, with values for accessors.\n */\nexport interface PendingAction<K extends string = string> {\n /** The key of the action now running, or null. */\n readonly current: K | null;\n /** True while any action runs: lock the other controls with it. */\n readonly busy: boolean;\n /** True while `key` is the running action: give that control its progress state. */\n is(key: K): boolean;\n /**\n * Runs `task` as `key` and clears the state when it settles, whether it resolves or throws (the\n * error reaches the caller). While another action runs it does nothing and resolves to undefined,\n * unless `replace` is set. The task receives a signal that aborts when this run stops counting:\n * `reset()`, a run that replaced it, or the component unmounting. Check `signal.aborted` after\n * each await before touching state, or pass the signal to `fetch`.\n */\n run<T>(key: K, task: (signal: AbortSignal) => T | Promise<T>, options?: PendingActionRunOptions): Promise<T | undefined>;\n /** Stops tracking the running action and aborts its signal, for example when the screen's data was replaced. */\n reset(): void;\n}\n\n/** Tracks the running action of a component. */\nexport function usePendingAction<K extends string = string>(): PendingAction<K> {\n const [current, setCurrent] = useState<K | null>(null);\n // State lands on the next render; the ref answers a second click in the same event loop turn.\n const active = useRef<AbortController | null>(null);\n useEffect(() => () => {\n active.current?.abort();\n active.current = null;\n }, []);\n const run = useCallback(async <T,>(\n key: K,\n task: (signal: AbortSignal) => T | Promise<T>,\n options?: PendingActionRunOptions,\n ): Promise<T | undefined> => {\n if (active.current && !options?.replace) return undefined;\n active.current?.abort();\n const controller = new AbortController();\n active.current = controller;\n setCurrent(key);\n try {\n return await task(controller.signal);\n } finally {\n if (active.current === controller) {\n active.current = null;\n setCurrent(null);\n }\n }\n }, []);\n const reset = useCallback(() => {\n active.current?.abort();\n active.current = null;\n setCurrent(null);\n }, []);\n return useMemo(() => ({\n current,\n busy: current !== null,\n is: (key: K) => current === key,\n run,\n reset,\n }), [current, run, reset]);\n}\n"],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+ export interface LayoutProps extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
3
+ navigationPosition?: "left" | "top";
4
+ contentWidth?: "workspace" | "form" | "settings" | "full";
5
+ labels: {
6
+ skip: string;
7
+ menuOpen: string;
8
+ menuClose: string;
9
+ };
10
+ header?: ReactNode;
11
+ navigation?: ReactNode;
12
+ railStart?: ReactNode;
13
+ railEnd?: ReactNode;
14
+ footer?: ReactNode;
15
+ children: ReactNode;
16
+ surface?: string;
17
+ }
18
+ export declare const Layout: import("react").ForwardRefExoticComponent<LayoutProps & import("react").RefAttributes<HTMLDivElement>>;
19
+ //# sourceMappingURL=layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../src/layout.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,cAAc,EACnB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,MAAM,WAAW,WAAY,SAAQ,IAAI,CACvC,cAAc,CAAC,cAAc,CAAC,EAC9B,UAAU,CACX;IACC,kBAAkB,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACpC,YAAY,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;IAC1D,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9D,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AACD,eAAO,MAAM,MAAM,wGAyJjB,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { type ReactNode } from "react";
2
+ export interface ConsoleNavItem {
3
+ id: string;
4
+ href: string;
5
+ label: string;
6
+ /** Decorative icon; the label supplies the accessible name. */
7
+ icon?: ReactNode;
8
+ badge?: number;
9
+ active?: boolean;
10
+ }
11
+ export interface ConsoleNavGroup {
12
+ /** Stable key for expansion state. Falls back to the group index. */
13
+ id?: string;
14
+ /** Opt in to a disclosure button; legacy groups remain expanded. */
15
+ collapsible?: boolean;
16
+ label: string;
17
+ items: readonly ConsoleNavItem[];
18
+ }
19
+ export interface LeftNavProps {
20
+ surface: string;
21
+ activePath: string;
22
+ nav: readonly ConsoleNavGroup[];
23
+ labels: {
24
+ nav: string;
25
+ badge: string;
26
+ };
27
+ expandedGroups?: readonly string[];
28
+ defaultExpandedGroups?: readonly string[];
29
+ onExpandedGroupsChange?: (groupIds: string[]) => void;
30
+ onNavigate?: () => void;
31
+ }
32
+ export declare function LeftNav({ surface, activePath, nav, labels, expandedGroups, defaultExpandedGroups, onExpandedGroupsChange, onNavigate, }: LeftNavProps): import("react").JSX.Element;
33
+ //# sourceMappingURL=left-nav.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"left-nav.d.ts","sourceRoot":"","sources":["../src/left-nav.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACxD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AACD,MAAM,WAAW,eAAe;IAC9B,qEAAqE;IACrE,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,oEAAoE;IACpE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,cAAc,EAAE,CAAC;CAClC;AACD,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,SAAS,eAAe,EAAE,CAAC;IAChC,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACvC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,qBAAqB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,sBAAsB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACtD,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB;AASD,wBAAgB,OAAO,CAAC,EACtB,OAAO,EACP,UAAU,EACV,GAAG,EACH,MAAM,EACN,cAAc,EACd,qBAAqB,EACrB,sBAAsB,EACtB,UAAU,GACX,EAAE,YAAY,+BAoGd"}
@@ -0,0 +1,4 @@
1
+ import type { LeftNavProps } from "./left-nav";
2
+ export type TopNavProps = Pick<LeftNavProps, "surface" | "activePath" | "nav" | "labels" | "onNavigate">;
3
+ export declare function TopNav({ surface, activePath, nav, labels, onNavigate, }: TopNavProps): import("react").JSX.Element;
4
+ //# sourceMappingURL=top-nav.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"top-nav.d.ts","sourceRoot":"","sources":["../src/top-nav.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,MAAM,MAAM,WAAW,GAAG,IAAI,CAC5B,YAAY,EACZ,SAAS,GAAG,YAAY,GAAG,KAAK,GAAG,QAAQ,GAAG,YAAY,CAC3D,CAAC;AACF,wBAAgB,MAAM,CAAC,EACrB,OAAO,EACP,UAAU,EACV,GAAG,EACH,MAAM,EACN,UAAU,GACX,EAAE,WAAW,+BA6Eb"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devslab/dds-react",
3
- "version": "0.28.0",
3
+ "version": "0.29.0",
4
4
  "description": "Accessible React primitives for the DevsLab Design System",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -99,9 +99,9 @@
99
99
  },
100
100
  "dependencies": {
101
101
  "@ark-ui/react": "5.39.3",
102
- "@devslab/dds-css": "0.28.0",
103
- "@devslab/dds-icons": "0.28.0",
104
- "@devslab/dds-tokens": "0.28.0",
102
+ "@devslab/dds-css": "0.29.0",
103
+ "@devslab/dds-icons": "0.29.0",
104
+ "@devslab/dds-tokens": "0.29.0",
105
105
  "@tanstack/react-virtual": "3.14.21"
106
106
  },
107
107
  "peerDependencies": {