@devslab/dds-react 0.29.1 → 0.30.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 +23 -1
- package/README.md +23 -1
- package/dist/index.js +157 -68
- package/dist/index.js.map +1 -1
- package/dist/toast.d.ts +21 -3
- package/dist/toast.d.ts.map +1 -1
- package/package.json +4 -4
package/README.ko.md
CHANGED
|
@@ -21,7 +21,29 @@ React DOM 속성(`className`, `htmlFor`, `onChange`)과 객체/콜백 ref를 사
|
|
|
21
21
|
|
|
22
22
|
Dialog는 기본적으로 portal을 사용하며 Ark가 중첩 모달, 포커스 복원, Escape, 스크롤 잠금을 관리합니다. `portal={false}`로 SSR 열린 콘텐츠를 인라인 렌더링할 수 있습니다. `contentProps`, `actions`, `frame`, `initialFocus`, `finalFocus`, `unstyled`와 Ark root 옵션을 제공합니다. Solid의 커스텀 additionalFocusContainers는 모방하지 않습니다. 고급 구성은 ArkDialog/ArkTabs/ArkTooltip/ArkRadioGroup/ArkCheckbox/ArkSwitch/ArkField/ArkToast 네임스페이스를 사용하세요.
|
|
23
23
|
|
|
24
|
-
Tooltip은 하나의 포커스 가능한 요소 또는 trigger props를 받는 render 함수를 사용합니다. ToastProvider의 regionLabel/dismissLabel은 호출자가 지정합니다. dismissLabel이 없으면 닫기 버튼이 없습니다. useToast는 show/dismiss/clear를 반환하며 duration 0은 유지됩니다. 언마운트 때 알림을 정리합니다.
|
|
24
|
+
Tooltip은 하나의 포커스 가능한 요소 또는 trigger props를 받는 render 함수를 사용합니다. ToastProvider의 regionLabel/dismissLabel은 호출자가 지정합니다. dismissLabel이 없으면 닫기 버튼이 없습니다. useToast는 show/loading/update/promise/dismiss/clear를 반환하며 duration 0은 유지됩니다. 언마운트 때 알림을 정리합니다. React·Solid·Vue의 동일한 계약은 [Toast 가이드](../../docs/toast.ko.md)를 참고하세요.
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
const toast = useToast(); // ToastProvider 내부
|
|
28
|
+
const id = toast.loading({ message: "저장 중" });
|
|
29
|
+
toast.update(id, { message: "저장 완료", tone: "success" });
|
|
30
|
+
|
|
31
|
+
const pending = toast.promise(() => save(), {
|
|
32
|
+
loading: { message: "저장 중" },
|
|
33
|
+
success: { message: "저장 완료", action: { label: "결과 보기", onClick: openResult } },
|
|
34
|
+
error: { message: "저장에 실패했습니다" },
|
|
35
|
+
});
|
|
36
|
+
const result = await pending; // 원래 결과 또는 원래 rejection
|
|
37
|
+
// 작업 중 pending.id를 update/dismiss에 전달할 수도 있습니다.
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`action: { label, onClick }`으로 버튼을 추가하고 `update`의 `action: null`로
|
|
41
|
+
제거합니다. 누르면 알림을 먼저 닫고 콜백을 실행합니다. loading은 유지되며,
|
|
42
|
+
update에서 완료 tone을 지정하면 일반 만료 시간이 시작됩니다. 수동 갱신·닫기·
|
|
43
|
+
clear·언마운트 후에는 늦은 Promise 완료가 해당 알림을 덮거나 재생성하지
|
|
44
|
+
않습니다. 문구 함수가 예외를 던지면 아직 유효한 알림만 닫고 작업의 원래
|
|
45
|
+
결과·오류는 보존합니다. 자동 재시도·요청 취소는 하지 않으며 작업의 rejection은
|
|
46
|
+
호출자가 처리합니다.
|
|
25
47
|
|
|
26
48
|
ConsoleShell은 brand/nav/header/labels/foot을 받으며 인스턴스별 고유 ID를 사용합니다. 브라우저 전역 없이 import와 SSR이 가능하고, React useId로 hydration 연결을 유지합니다. Solid accessor/ref/render 방식 대신 React JSX/ref와 Ark asChild 요소 구성을 사용합니다. AG Grid는 별도 패키지 `@devslab/dds-table-react`입니다.
|
|
27
49
|
|
package/README.md
CHANGED
|
@@ -25,7 +25,29 @@ Native DOM attributes use React spelling (`className`, `htmlFor`, `onChange`). D
|
|
|
25
25
|
|
|
26
26
|
Tabs extends Ark root options, with `onValueChange(string)`; parts accept normal Ark DOM props including `asChild`. Dialog accepts Ark root options with `onOpenChange(boolean)`, `closeOnOutside`, `initialFocus`, `finalFocus`, `contentProps`, `actions`, `frame(parts)` and `unstyled`. Dialog portals by default; use `portal={false}` for inline markup, including open SSR content. Ark owns nested modal isolation, focus, Escape handling and scroll locking. Additional focus containers from the Solid package are not emulated; use Ark `persistentElements` and `modal`/`trapFocus` according to application needs.
|
|
27
27
|
|
|
28
|
-
Tooltip accepts one element child (Ark `asChild`) or a render function receiving native button trigger props. Use a focusable trigger and preserve the supplied events. `ToastProvider` accepts optional caller `regionLabel` and `dismissLabel` (string or record-to-string function); without `dismissLabel` it renders no close button. `useToast()` returns `show
|
|
28
|
+
Tooltip accepts one element child (Ark `asChild`) or a render function receiving native button trigger props. Use a focusable trigger and preserve the supplied events. `ToastProvider` accepts optional caller `regionLabel` and `dismissLabel` (string or record-to-string function); without `dismissLabel` it renders no close button. `useToast()` returns `show`, `loading`, `update`, `promise`, `dismiss`, and `clear`; duration 0 persists. Providers clear their notifications on unmount. The [Toast guide](../../docs/toast.md) covers the identical React/Solid/Vue contract.
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
const toast = useToast(); // inside ToastProvider
|
|
32
|
+
const id = toast.loading({ message: "Saving…" });
|
|
33
|
+
toast.update(id, { message: "Saved", tone: "success" });
|
|
34
|
+
|
|
35
|
+
const pending = toast.promise(() => save(), {
|
|
36
|
+
loading: { message: "Saving…" },
|
|
37
|
+
success: { message: "Saved", action: { label: "View result", onClick: openResult } },
|
|
38
|
+
error: { message: "Save failed" },
|
|
39
|
+
});
|
|
40
|
+
const result = await pending; // original result, or original rejection
|
|
41
|
+
// pending.id can also be passed to update/dismiss while the operation runs.
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`action: { label, onClick }` adds a button and `action: null` removes it through
|
|
45
|
+
`update`. Activation dismisses before invoking the callback. Loading persists;
|
|
46
|
+
set a terminal tone with `update` to start normal expiry. Manual update,
|
|
47
|
+
dismissal, clear or provider unmount prevents a pending promise from overwriting
|
|
48
|
+
or recreating that notification. Message-factory exceptions dismiss the
|
|
49
|
+
still-current notice without changing the task result/error. No retry or request
|
|
50
|
+
cancellation is performed; callers still handle rejected operations.
|
|
29
51
|
|
|
30
52
|
Advanced compositional parts are exported as `ArkDialog`, `ArkTabs`, `ArkTooltip`, `ArkRadioGroup`, `ArkCheckbox`, `ArkSwitch`, `ArkField`, and `ArkToast`. They are the pinned upstream Ark namespaces, useful inside convenience component children or for application-owned composition.
|
|
31
53
|
|
package/dist/index.js
CHANGED
|
@@ -11,42 +11,42 @@ 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
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,
|
|
15
|
-
import { Field as
|
|
16
|
-
import { Checkbox as
|
|
17
|
-
import { Switch as
|
|
14
|
+
import { createContext as w, forwardRef as T, useCallback as E, useContext as D, useEffect as O, useId as k, useInsertionEffect as A, useMemo as j, useRef as M, useState as N } from "react";
|
|
15
|
+
import { Field as P } from "@ark-ui/react/field";
|
|
16
|
+
import { Checkbox as ee } from "@ark-ui/react/checkbox";
|
|
17
|
+
import { Switch as te } from "@ark-ui/react/switch";
|
|
18
18
|
import { Fragment as F, jsx as I, jsxs as L } from "react/jsx-runtime";
|
|
19
|
-
import { Tabs as
|
|
20
|
-
import { RadioGroup as
|
|
21
|
-
import { Dialog as
|
|
19
|
+
import { Tabs as ne, Tabs as R, useTabsContext as z } from "@ark-ui/react/tabs";
|
|
20
|
+
import { RadioGroup as B, RadioGroup as V, useRadioGroupContext as re } from "@ark-ui/react/radio-group";
|
|
21
|
+
import { Dialog as ie, Dialog as H } from "@ark-ui/react/dialog";
|
|
22
22
|
import { Tooltip as U, Tooltip as W } from "@ark-ui/react/tooltip";
|
|
23
23
|
import { Portal as G } from "@ark-ui/react/portal";
|
|
24
24
|
import { directionPolicy as K, icons as q } from "@devslab/dds-icons";
|
|
25
|
-
import { Toast as J, Toast as
|
|
26
|
-
import { DatePicker as
|
|
25
|
+
import { Toast as J, Toast as ae, Toaster as oe, createToaster as Y } from "@ark-ui/react/toast";
|
|
26
|
+
import { DatePicker as se } from "@ark-ui/react/date-picker";
|
|
27
27
|
//#region src/selection.tsx
|
|
28
|
-
var
|
|
29
|
-
return /* @__PURE__ */ I(
|
|
28
|
+
var ce = T(function({ onValueChange: e, unstyled: n, className: r, ...i }, a) {
|
|
29
|
+
return /* @__PURE__ */ I(R.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
|
-
}),
|
|
36
|
-
return /* @__PURE__ */ I(
|
|
35
|
+
}), le = T(function({ unstyled: e, className: n, ...r }, i) {
|
|
36
|
+
return /* @__PURE__ */ I(R.List, {
|
|
37
37
|
...r,
|
|
38
38
|
ref: i,
|
|
39
39
|
className: t(!e && "dds-tabs", n)
|
|
40
40
|
});
|
|
41
|
-
}),
|
|
42
|
-
return /* @__PURE__ */ I(
|
|
41
|
+
}), ue = T(function({ unstyled: e, className: n, ...r }, i) {
|
|
42
|
+
return /* @__PURE__ */ I(R.Trigger, {
|
|
43
43
|
...r,
|
|
44
44
|
ref: i,
|
|
45
45
|
className: t(!e && "dds-tab", n)
|
|
46
46
|
});
|
|
47
|
-
}),
|
|
48
|
-
let i =
|
|
49
|
-
return /* @__PURE__ */ I(
|
|
47
|
+
}), de = T(function({ value: e, style: t, ...n }, r) {
|
|
48
|
+
let i = z().value !== e;
|
|
49
|
+
return /* @__PURE__ */ I(R.Content, {
|
|
50
50
|
...n,
|
|
51
51
|
value: e,
|
|
52
52
|
ref: r,
|
|
@@ -57,8 +57,8 @@ var se = T(function({ onValueChange: e, unstyled: n, className: r, ...i }, a) {
|
|
|
57
57
|
} : t
|
|
58
58
|
});
|
|
59
59
|
});
|
|
60
|
-
function
|
|
61
|
-
let t =
|
|
60
|
+
function fe({ option: e }) {
|
|
61
|
+
let t = re(), { 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,7 +66,7 @@ function de({ option: e }) {
|
|
|
66
66
|
className: "dds-check__input"
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
|
-
var
|
|
69
|
+
var pe = T(function({ options: e, label: n, onValueChange: r, className: i, children: a, ...o }, s) {
|
|
70
70
|
return /* @__PURE__ */ L(V.Root, {
|
|
71
71
|
...o,
|
|
72
72
|
ref: s,
|
|
@@ -83,12 +83,12 @@ var fe = T(function({ options: e, label: n, onValueChange: r, className: i, chil
|
|
|
83
83
|
value: e.value,
|
|
84
84
|
disabled: e.disabled,
|
|
85
85
|
className: "dds-check",
|
|
86
|
-
children: [/* @__PURE__ */ I(
|
|
86
|
+
children: [/* @__PURE__ */ I(fe, { option: e }), /* @__PURE__ */ I(V.ItemText, { children: e.label })]
|
|
87
87
|
}, e.value)),
|
|
88
88
|
a
|
|
89
89
|
]
|
|
90
90
|
});
|
|
91
|
-
}),
|
|
91
|
+
}), me = 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
93
|
title: /* @__PURE__ */ I(H.Title, {
|
|
94
94
|
className: m ? void 0 : "dds-dialog__title",
|
|
@@ -129,7 +129,7 @@ var fe = T(function({ options: e, label: n, onValueChange: r, className: i, chil
|
|
|
129
129
|
children: s ? /* @__PURE__ */ I(G, { children: v }) : v
|
|
130
130
|
});
|
|
131
131
|
});
|
|
132
|
-
function
|
|
132
|
+
function he({ content: e, children: n, onOpenChange: r, className: i, contentProps: a, ...o }) {
|
|
133
133
|
return /* @__PURE__ */ I(W.Root, {
|
|
134
134
|
openDelay: 0,
|
|
135
135
|
closeDelay: 0,
|
|
@@ -150,7 +150,7 @@ function me({ content: e, children: n, onOpenChange: r, className: i, contentPro
|
|
|
150
150
|
}
|
|
151
151
|
//#endregion
|
|
152
152
|
//#region src/icon.tsx
|
|
153
|
-
var
|
|
153
|
+
var ge = T(function({ name: e, label: n, size: r = 24, directional: i, className: a, ...o }, s) {
|
|
154
154
|
let c = q[e];
|
|
155
155
|
return /* @__PURE__ */ L("svg", {
|
|
156
156
|
...o,
|
|
@@ -170,39 +170,117 @@ var he = T(function({ name: e, label: n, size: r = 24, directional: i, className
|
|
|
170
170
|
children: [n && /* @__PURE__ */ I("title", { children: n }), /* @__PURE__ */ I("g", { dangerouslySetInnerHTML: { __html: c.body } })]
|
|
171
171
|
});
|
|
172
172
|
}), X = w(null);
|
|
173
|
-
function
|
|
174
|
-
let o = k(), s =
|
|
173
|
+
function _e({ children: e, defaultDuration: n = 5e3, dismissLabel: r, regionLabel: i, className: a }) {
|
|
174
|
+
let o = k(), s = M(0), c = M(null), l = j(() => {
|
|
175
|
+
let e;
|
|
176
|
+
return () => e ??= new Proxy(c.current?.ownerDocument ?? document, { get(e, t) {
|
|
177
|
+
if (t === "getElementById") return (t) => t === "toast-group:bottom-end" ? c.current : e.getElementById(t);
|
|
178
|
+
let n = Reflect.get(e, t, e);
|
|
179
|
+
return typeof n == "function" ? n.bind(e) : n;
|
|
180
|
+
} });
|
|
181
|
+
}, []), u = j(() => Y({
|
|
175
182
|
placement: "bottom-end",
|
|
176
183
|
overlap: !1,
|
|
177
184
|
gap: 8,
|
|
178
185
|
offsets: "var(--dds-space-16)",
|
|
179
186
|
removeDelay: 0,
|
|
180
|
-
hotkey: ["DDS_NO_HOTKEY"]
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
187
|
+
hotkey: ["DDS_NO_HOTKEY"],
|
|
188
|
+
max: 2 ** 53 - 1
|
|
189
|
+
}), []), d = j(() => ({
|
|
190
|
+
disposed: !1,
|
|
191
|
+
defaultDuration: n,
|
|
192
|
+
records: /* @__PURE__ */ new Map()
|
|
193
|
+
}), [u]);
|
|
194
|
+
A(() => (d.disposed = !1, () => {
|
|
195
|
+
d.disposed = !0;
|
|
196
|
+
}), [d]), A(() => {
|
|
197
|
+
d.defaultDuration = n;
|
|
198
|
+
}, [d, n]);
|
|
199
|
+
let f = j(() => {
|
|
200
|
+
let e = (e) => d.disposed ? void 0 : d.records.get(e), t = (t, r = !1) => {
|
|
201
|
+
let i = t.input, a = i.duration ?? d.defaultDuration, o = i.action, s = {
|
|
202
|
+
id: i.id,
|
|
203
|
+
description: i.message,
|
|
204
|
+
type: i.tone === "danger" ? "error" : i.tone ?? "info",
|
|
205
|
+
duration: i.tone === "loading" || a <= 0 ? Infinity : a,
|
|
206
|
+
action: o ? {
|
|
207
|
+
label: o.label,
|
|
208
|
+
onClick: () => {
|
|
209
|
+
e(i.id) !== t || t.input.action !== o || !u.isVisible(i.id) || (n.dismiss(i.id), o.onClick());
|
|
210
|
+
}
|
|
211
|
+
} : void 0,
|
|
212
|
+
meta: { dds: i },
|
|
213
|
+
onStatusChange: ({ status: e }) => {
|
|
214
|
+
e !== "visible" && d.records.get(i.id) === t && d.records.delete(i.id);
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
r ? u.update(i.id, s) : u.create(s);
|
|
218
|
+
}, n = {
|
|
219
|
+
show(e) {
|
|
220
|
+
let n = `dds-toast-${o}-${++s.current}`;
|
|
221
|
+
if (d.disposed) return n;
|
|
222
|
+
let r = {
|
|
223
|
+
input: {
|
|
224
|
+
...e,
|
|
225
|
+
id: n
|
|
226
|
+
},
|
|
227
|
+
revision: 0
|
|
228
|
+
};
|
|
229
|
+
return d.records.set(n, r), t(r), n;
|
|
230
|
+
},
|
|
231
|
+
loading: (e) => n.show({
|
|
232
|
+
...e,
|
|
233
|
+
tone: "loading"
|
|
234
|
+
}),
|
|
235
|
+
update(n, r) {
|
|
236
|
+
let i = e(n);
|
|
237
|
+
!i || !u.isVisible(n) || (i.input = {
|
|
238
|
+
...i.input,
|
|
239
|
+
...r,
|
|
240
|
+
id: n
|
|
241
|
+
}, i.revision++, t(i, !0));
|
|
242
|
+
},
|
|
243
|
+
promise(t, r) {
|
|
244
|
+
let i = n.loading(r.loading), a = e(i), o = a?.revision, s = () => !!a && e(i) === a && a.revision === o && u.isVisible(i), c = (e, t, r) => {
|
|
245
|
+
if (s()) try {
|
|
246
|
+
let a = typeof e == "function" ? e(t) : e, o = {
|
|
247
|
+
...a,
|
|
248
|
+
tone: a.tone ?? r
|
|
249
|
+
};
|
|
250
|
+
s() && n.update(i, o);
|
|
251
|
+
} catch {
|
|
252
|
+
s() && n.dismiss(i);
|
|
253
|
+
}
|
|
254
|
+
}, l = Promise.resolve().then(() => typeof t == "function" ? t() : t).then((e) => (c(r.success, e, "success"), e), (e) => {
|
|
255
|
+
throw c(r.error, e, "danger"), e;
|
|
256
|
+
});
|
|
257
|
+
return Object.defineProperty(l, "id", {
|
|
258
|
+
value: i,
|
|
259
|
+
enumerable: !0
|
|
260
|
+
});
|
|
261
|
+
},
|
|
262
|
+
dismiss(e) {
|
|
263
|
+
d.records.delete(e), d.disposed || u.remove(e);
|
|
264
|
+
},
|
|
265
|
+
clear() {
|
|
266
|
+
d.records.clear(), d.disposed || u.remove();
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
return n;
|
|
270
|
+
}, [
|
|
271
|
+
u,
|
|
199
272
|
o,
|
|
200
|
-
|
|
273
|
+
d
|
|
201
274
|
]);
|
|
202
|
-
return O(() => () =>
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
275
|
+
return O(() => () => {
|
|
276
|
+
d.records.clear(), u.remove();
|
|
277
|
+
}, [u, d]), /* @__PURE__ */ L(X.Provider, {
|
|
278
|
+
value: f,
|
|
279
|
+
children: [e, /* @__PURE__ */ I(oe, {
|
|
280
|
+
toaster: u,
|
|
281
|
+
ref: c,
|
|
282
|
+
getRootNode: l,
|
|
283
|
+
id: `dds-toast-region-${o}`,
|
|
206
284
|
label: i ?? "",
|
|
207
285
|
"aria-label": i ?? "",
|
|
208
286
|
role: i ? "region" : "presentation",
|
|
@@ -210,19 +288,30 @@ function ge({ children: e, defaultDuration: n = 5e3, dismissLabel: r, regionLabe
|
|
|
210
288
|
children: (e) => {
|
|
211
289
|
let n = e.meta?.dds;
|
|
212
290
|
return /* @__PURE__ */ L(J.Root, {
|
|
213
|
-
className: t("dds-toast", `dds-toast--${n.tone ?? "info"}
|
|
291
|
+
className: t("dds-toast", `dds-toast--${n.tone ?? "info"}`, !!n.action && "dds-toast--action"),
|
|
214
292
|
role: n.tone === "danger" ? "alert" : "status",
|
|
215
|
-
children: [
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
293
|
+
children: [
|
|
294
|
+
n.tone === "loading" && /* @__PURE__ */ I("span", {
|
|
295
|
+
className: "dds-spinner",
|
|
296
|
+
"aria-hidden": "true"
|
|
297
|
+
}),
|
|
298
|
+
/* @__PURE__ */ I(J.Description, { children: e.description }),
|
|
299
|
+
n.action && /* @__PURE__ */ I(J.ActionTrigger, {
|
|
300
|
+
className: "dds-btn dds-btn--secondary dds-btn--sm dds-toast__action",
|
|
301
|
+
children: n.action.label
|
|
302
|
+
}),
|
|
303
|
+
r && /* @__PURE__ */ I(J.CloseTrigger, {
|
|
304
|
+
className: "dds-iconbtn dds-iconbtn--sm",
|
|
305
|
+
"aria-label": typeof r == "function" ? r(n) : r,
|
|
306
|
+
children: "×"
|
|
307
|
+
})
|
|
308
|
+
]
|
|
220
309
|
});
|
|
221
310
|
}
|
|
222
311
|
})]
|
|
223
312
|
});
|
|
224
313
|
}
|
|
225
|
-
function
|
|
314
|
+
function ve() {
|
|
226
315
|
let e = D(X);
|
|
227
316
|
if (!e) throw Error("useToast must be called inside <ToastProvider>");
|
|
228
317
|
return e;
|
|
@@ -230,7 +319,7 @@ function _e() {
|
|
|
230
319
|
//#endregion
|
|
231
320
|
//#region src/layout.tsx
|
|
232
321
|
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] =
|
|
322
|
+
let m = k(), h = `dds-console-rail-${m}`, g = `dds-console-main-${m}`, [_, v] = N(!1), [y, b] = N(!1), x = M(null), S = M(null);
|
|
234
323
|
function C() {
|
|
235
324
|
v(!1), x.current?.focus();
|
|
236
325
|
}
|
|
@@ -327,7 +416,7 @@ function Q(e, t) {
|
|
|
327
416
|
return t.active ?? (t.href.split("/").filter(Boolean).length <= 1 ? e === t.href : e === t.href || e.startsWith(`${t.href}/`));
|
|
328
417
|
}
|
|
329
418
|
function $({ surface: e, activePath: t, nav: n, labels: r, expandedGroups: i, defaultExpandedGroups: a, onExpandedGroupsChange: o, onNavigate: s }) {
|
|
330
|
-
let c = k(), [l, u] =
|
|
419
|
+
let c = k(), [l, u] = N(() => a ?? n.flatMap((e, n) => e.collapsible && e.items.some((e) => Q(t, e)) ? [e.id ?? `group-${n}`] : [])), d = i ?? l;
|
|
331
420
|
function f(e) {
|
|
332
421
|
let t = d.includes(e) ? d.filter((t) => t !== e) : [...d, e];
|
|
333
422
|
i === void 0 && u(t), o?.(t);
|
|
@@ -381,7 +470,7 @@ function $({ surface: e, activePath: t, nav: n, labels: r, expandedGroups: i, de
|
|
|
381
470
|
}
|
|
382
471
|
//#endregion
|
|
383
472
|
//#region src/console-shell.tsx
|
|
384
|
-
var
|
|
473
|
+
var ye = 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
474
|
return /* @__PURE__ */ I(Z, {
|
|
386
475
|
...p,
|
|
387
476
|
ref: m,
|
|
@@ -431,8 +520,8 @@ var ve = T(function({ surface: e, activePath: t, brand: n, context: r, nav: i =
|
|
|
431
520
|
});
|
|
432
521
|
//#endregion
|
|
433
522
|
//#region src/top-nav.tsx
|
|
434
|
-
function
|
|
435
|
-
let a =
|
|
523
|
+
function be({ surface: e, activePath: t, nav: n, labels: r, onNavigate: i }) {
|
|
524
|
+
let a = M(null);
|
|
436
525
|
return O(() => {
|
|
437
526
|
function e(e) {
|
|
438
527
|
a.current?.contains(e.target) || a.current?.querySelectorAll("details[open]").forEach((e) => e.removeAttribute("open"));
|
|
@@ -482,7 +571,7 @@ function ye({ surface: e, activePath: t, nav: n, labels: r, onNavigate: i }) {
|
|
|
482
571
|
}
|
|
483
572
|
//#endregion
|
|
484
573
|
//#region src/status-pill.tsx
|
|
485
|
-
function
|
|
574
|
+
function xe(e) {
|
|
486
575
|
let t = new Set(e.openDomains ?? []);
|
|
487
576
|
return function(n) {
|
|
488
577
|
let r = e.tones[n.domain]?.[n.value], i = e.label(n.domain, n.value, n.locale);
|
|
@@ -503,8 +592,8 @@ function be(e) {
|
|
|
503
592
|
}
|
|
504
593
|
//#endregion
|
|
505
594
|
//#region src/pending-action.ts
|
|
506
|
-
function
|
|
507
|
-
let [e, t] =
|
|
595
|
+
function Se() {
|
|
596
|
+
let [e, t] = N(null), n = M(null);
|
|
508
597
|
O(() => () => {
|
|
509
598
|
n.current?.abort(), n.current = null;
|
|
510
599
|
}, []);
|
|
@@ -521,7 +610,7 @@ function xe() {
|
|
|
521
610
|
}, []), i = E(() => {
|
|
522
611
|
n.current?.abort(), n.current = null, t(null);
|
|
523
612
|
}, []);
|
|
524
|
-
return
|
|
613
|
+
return j(() => ({
|
|
525
614
|
current: e,
|
|
526
615
|
busy: e !== null,
|
|
527
616
|
is: (t) => e === t,
|
|
@@ -534,6 +623,6 @@ function xe() {
|
|
|
534
623
|
]);
|
|
535
624
|
}
|
|
536
625
|
//#endregion
|
|
537
|
-
export {
|
|
626
|
+
export { ee as ArkCheckbox, se as ArkDatePicker, ie as ArkDialog, P as ArkField, B as ArkRadioGroup, te as ArkSwitch, ne as ArkTabs, ae as ArkToast, U as ArkTooltip, s as Button, _ as Calendar, r as Checkbox, p as Combobox, ye as ConsoleShell, c as DatePicker, l as DateRangePicker, me as Dialog, h as DropdownMenu, a as Field, ge 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, pe as RadioGroup, y as SegmentedControl, i as Select, m as SelectPicker, o as Switch, ue as Tab, le as TabList, de as TabPanel, ce as Tabs, v as TimePicker, _e as ToastProvider, he as Tooltip, be as TopNav, t as classes, xe as createStatusPill, S as normalizeNumberText, C as numberInputMessages, Se as usePendingAction, ve as useToast, b as validateSegmentedItems };
|
|
538
627
|
|
|
539
628
|
//# 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/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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"}
|
|
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 useInsertionEffect,\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\" | \"loading\";\nexport interface ToastAction {\n label: string;\n onClick: () => void;\n}\nexport interface ToastInput {\n message: ReactNode;\n tone?: ToastTone | undefined;\n duration?: number | undefined;\n action?: ToastAction | null | undefined;\n}\nexport type ToastUpdate = Partial<ToastInput>;\nexport type ToastLoadingInput = Omit<ToastInput, \"tone\" | \"duration\">;\nexport interface ToastPromiseOptions<T> {\n loading: ToastLoadingInput;\n success: ToastInput | ((value: T) => ToastInput);\n error: ToastInput | ((reason: unknown) => ToastInput);\n}\nexport type ToastPromise<T> = Promise<T> & { readonly id: string };\nexport interface ToastRecord extends ToastInput {\n id: string;\n}\nexport interface ToastApi {\n show: (toast: ToastInput) => string;\n loading: (toast: ToastLoadingInput) => string;\n update: (id: string, patch: ToastUpdate) => void;\n promise: <T>(\n operation: Promise<T> | (() => Promise<T>),\n options: ToastPromiseOptions<T>,\n ) => ToastPromise<T>;\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 region = useRef<HTMLDivElement>(null);\n const getRootNode = useMemo(() => {\n let scopedDocument: Document | undefined;\n // Match Solid's provider-local lookup while preserving the real document's\n // native method receivers. Zag otherwise locates the first bottom-end group.\n return () =>\n (scopedDocument ??= new Proxy(region.current?.ownerDocument ?? document, {\n get(target, property) {\n if (property === \"getElementById\")\n return (id: string) =>\n id === \"toast-group:bottom-end\"\n ? region.current\n : target.getElementById(id);\n const value = Reflect.get(target, property, target);\n return typeof value === \"function\" ? value.bind(target) : value;\n },\n }));\n }, []);\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 max: Number.MAX_SAFE_INTEGER,\n }),\n [],\n );\n const state = useMemo(\n () => ({\n disposed: false,\n defaultDuration,\n records: new Map<string, { input: ToastRecord; revision: number }>(),\n }),\n [toaster],\n );\n // Only mutate lifecycle flags here, never the Ark store. Insertion effects\n // distinguish actual unmount from StrictMode's passive-effect replay, so\n // child effects can create notices during both setups without resurrecting\n // a genuinely disposed provider through a captured API.\n useInsertionEffect(() => {\n state.disposed = false;\n return () => {\n state.disposed = true;\n };\n }, [state]);\n useInsertionEffect(() => {\n state.defaultDuration = defaultDuration;\n }, [state, defaultDuration]);\n const api = useMemo<ToastApi>(() => {\n const current = (id: string) =>\n state.disposed ? undefined : state.records.get(id);\n const write = (\n entry: { input: ToastRecord; revision: number },\n update = false,\n ) => {\n const record = entry.input;\n const duration = record.duration ?? state.defaultDuration;\n const action = record.action;\n const options = {\n id: record.id,\n description: record.message,\n type: record.tone === \"danger\" ? \"error\" : (record.tone ?? \"info\"),\n duration:\n record.tone === \"loading\" || duration <= 0 ? Infinity : duration,\n action: action\n ? {\n label: action.label,\n onClick: () => {\n if (\n current(record.id) !== entry ||\n entry.input.action !== action ||\n !toaster.isVisible(record.id)\n )\n return;\n api.dismiss(record.id);\n action.onClick();\n },\n }\n : undefined,\n meta: { dds: record },\n onStatusChange: ({ status }: { status: string }) => {\n if (status !== \"visible\" && state.records.get(record.id) === entry)\n state.records.delete(record.id);\n },\n };\n if (update) toaster.update(record.id, options);\n else toaster.create(options);\n };\n const api: ToastApi = {\n show(input) {\n const id = `dds-toast-${prefix}-${++sequence.current}`;\n if (state.disposed) return id;\n const entry = { input: { ...input, id }, revision: 0 };\n state.records.set(id, entry);\n write(entry);\n return id;\n },\n loading: (input) => api.show({ ...input, tone: \"loading\" }),\n update(id, patch) {\n const entry = current(id);\n // Ark update is an upsert; DDS update must never recreate an old ID.\n if (!entry || !toaster.isVisible(id)) return;\n entry.input = { ...entry.input, ...patch, id };\n entry.revision++;\n write(entry, true);\n },\n promise<T>(\n operation: Promise<T> | (() => Promise<T>),\n options: ToastPromiseOptions<T>,\n ) {\n const id = api.loading(options.loading);\n const entry = current(id);\n const revision = entry?.revision;\n const owns = () =>\n !!entry &&\n current(id) === entry &&\n entry.revision === revision &&\n toaster.isVisible(id);\n const present = <T,>(\n setting: ToastInput | ((value: T) => ToastInput),\n value: T,\n tone: \"success\" | \"danger\",\n ) => {\n if (!owns()) return;\n try {\n const input =\n typeof setting === \"function\" ? setting(value) : setting;\n const patch = { ...input, tone: input.tone ?? tone };\n if (owns()) api.update(id, patch);\n } catch {\n // Presentation must not change the actual task's outcome.\n if (owns()) api.dismiss(id);\n }\n };\n const pending = Promise.resolve()\n .then(() =>\n typeof operation === \"function\" ? operation() : operation,\n )\n .then(\n (value) => {\n present(options.success, value, \"success\");\n return value;\n },\n (reason: unknown) => {\n present(options.error, reason, \"danger\");\n throw reason;\n },\n );\n return Object.defineProperty(pending, \"id\", {\n value: id,\n enumerable: true,\n }) as ToastPromise<T>;\n },\n dismiss(id) {\n state.records.delete(id);\n if (!state.disposed) toaster.remove(id);\n },\n clear() {\n state.records.clear();\n if (!state.disposed) toaster.remove();\n },\n };\n return api;\n }, [toaster, prefix, state]);\n useEffect(\n () => () => {\n state.records.clear();\n toaster.remove();\n },\n [toaster, state],\n );\n return (\n <ToastContext.Provider value={api}>\n {children}\n <Toaster\n toaster={toaster}\n ref={region}\n getRootNode={getRootNode}\n id={`dds-toast-region-${prefix}`}\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 !!record.action && \"dds-toast--action\",\n )}\n role={record.tone === \"danger\" ? \"alert\" : \"status\"}\n >\n {record.tone === \"loading\" && (\n <span className=\"dds-spinner\" aria-hidden=\"true\" />\n )}\n <ArkToast.Description>{toast.description}</ArkToast.Description>\n {record.action && (\n <ArkToast.ActionTrigger className=\"dds-btn dds-btn--secondary dds-btn--sm dds-toast__action\">\n {record.action.label}\n </ArkToast.ActionTrigger>\n )}\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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"}
|
package/dist/toast.d.ts
CHANGED
|
@@ -1,15 +1,33 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
|
-
export type ToastTone = "success" | "warning" | "danger" | "info";
|
|
2
|
+
export type ToastTone = "success" | "warning" | "danger" | "info" | "loading";
|
|
3
|
+
export interface ToastAction {
|
|
4
|
+
label: string;
|
|
5
|
+
onClick: () => void;
|
|
6
|
+
}
|
|
3
7
|
export interface ToastInput {
|
|
4
8
|
message: ReactNode;
|
|
5
|
-
tone?: ToastTone;
|
|
6
|
-
duration?: number;
|
|
9
|
+
tone?: ToastTone | undefined;
|
|
10
|
+
duration?: number | undefined;
|
|
11
|
+
action?: ToastAction | null | undefined;
|
|
12
|
+
}
|
|
13
|
+
export type ToastUpdate = Partial<ToastInput>;
|
|
14
|
+
export type ToastLoadingInput = Omit<ToastInput, "tone" | "duration">;
|
|
15
|
+
export interface ToastPromiseOptions<T> {
|
|
16
|
+
loading: ToastLoadingInput;
|
|
17
|
+
success: ToastInput | ((value: T) => ToastInput);
|
|
18
|
+
error: ToastInput | ((reason: unknown) => ToastInput);
|
|
7
19
|
}
|
|
20
|
+
export type ToastPromise<T> = Promise<T> & {
|
|
21
|
+
readonly id: string;
|
|
22
|
+
};
|
|
8
23
|
export interface ToastRecord extends ToastInput {
|
|
9
24
|
id: string;
|
|
10
25
|
}
|
|
11
26
|
export interface ToastApi {
|
|
12
27
|
show: (toast: ToastInput) => string;
|
|
28
|
+
loading: (toast: ToastLoadingInput) => string;
|
|
29
|
+
update: (id: string, patch: ToastUpdate) => void;
|
|
30
|
+
promise: <T>(operation: Promise<T> | (() => Promise<T>), options: ToastPromiseOptions<T>) => ToastPromise<T>;
|
|
13
31
|
dismiss: (id: string) => void;
|
|
14
32
|
clear: () => void;
|
|
15
33
|
}
|
package/dist/toast.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toast.d.ts","sourceRoot":"","sources":["../src/toast.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"toast.d.ts","sourceRoot":"","sources":["../src/toast.tsx"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAGf,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;AAC9E,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AACD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,SAAS,CAAC;IACnB,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,CAAC;CACzC;AACD,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAC9C,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC;AACtE,MAAM,WAAW,mBAAmB,CAAC,CAAC;IACpC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,OAAO,EAAE,UAAU,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,UAAU,CAAC,CAAC;IACjD,KAAK,EAAE,UAAU,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,KAAK,UAAU,CAAC,CAAC;CACvD;AACD,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AACnE,MAAM,WAAW,WAAY,SAAQ,UAAU;IAC7C,EAAE,EAAE,MAAM,CAAC;CACZ;AACD,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,MAAM,CAAC;IACpC,OAAO,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,MAAM,CAAC;IAC9C,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACjD,OAAO,EAAE,CAAC,CAAC,EACT,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC,EAC1C,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,KAC5B,YAAY,CAAC,CAAC,CAAC,CAAC;IACrB,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AACD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,SAAS,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,MAAM,CAAC,CAAC;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,eAAsB,EACtB,YAAY,EACZ,WAAW,EACX,SAAS,GACV,EAAE,kBAAkB,+BAqOpB;AACD,wBAAgB,QAAQ,IAAI,QAAQ,CAInC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devslab/dds-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.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.
|
|
103
|
-
"@devslab/dds-icons": "0.
|
|
104
|
-
"@devslab/dds-tokens": "0.
|
|
102
|
+
"@devslab/dds-css": "0.30.0",
|
|
103
|
+
"@devslab/dds-icons": "0.30.0",
|
|
104
|
+
"@devslab/dds-tokens": "0.30.0",
|
|
105
105
|
"@tanstack/react-virtual": "3.14.21"
|
|
106
106
|
},
|
|
107
107
|
"peerDependencies": {
|