@devslab/dds-react 0.22.0 → 0.23.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
@@ -48,6 +48,20 @@ const StatusPill = createStatusPill({
48
48
 
49
49
  Unknown closed-domain status values throw to expose incomplete catalogs. Domains listed in `openDomains` instead show the unknown value as escaped text.
50
50
 
51
+ ## usePendingAction
52
+
53
+ 버튼이 여러 개인 화면은 어느 버튼이 작업을 시작했는지 알아야 한다. 모든 버튼에 같은 플래그 하나를 넘기면 한 번만 눌러도 전부 돈다.
54
+
55
+ ```tsx
56
+ const action = usePendingAction<"approve" | "reject">();
57
+ <Button tone="danger" loading={action.is("reject")} disabled={action.busy}
58
+ onClick={() => action.run("reject", () => decide("reject"))}>반려</Button>
59
+ <Button loading={action.is("approve")} disabled={action.busy}
60
+ onClick={() => action.run("approve", () => decide("approve"))}>승인</Button>
61
+ ```
62
+
63
+ Solid `createPendingAction`과 같은 계약이고 accessor 대신 값을 쓴다. `is(key)`는 실행 중인 동작에만 참이고 `busy`로 나머지를 잠근다. `run`은 작업이 끝나면 성공·실패와 관계없이 상태를 지우고 오류는 호출자에게 넘긴다. 다른 동작이 실행 중이면 아무것도 하지 않는다. React가 첫 클릭을 아직 렌더하지 않은 같은 이벤트 루프 안의 두 번째 클릭도 막는다. 목록 다시 불러오기처럼 마지막 요청이 이겨야 하는 곳에는 `{ replace: true }`를 준다. 작업은 `AbortSignal`을 받고, 이 signal은 `reset()`, 그 실행을 대체한 새 실행, 언마운트 때 abort된다. await 뒤 상태를 바꾸기 전에 `signal.aborted`를 확인하거나 `fetch`에 넘긴다. 늦게 끝난 이전 작업은 새 동작의 상태를 지우지 못한다.
64
+
51
65
  ### DatePicker 직접 입력과 저장
52
66
 
53
67
  `value`/`onChange`는 기존과 같이 날짜 전용 `YYYY-MM-DD` 문자열과 명시적 지우기 `''`만 전달합니다. 입력한 날짜가 완전하고 실재하면 즉시 반영하며 잘못되거나 미완성인 입력을 이전 날짜로 치환하지 않습니다. `required`는 실제 입력의 필수 상태로 전달하고, `readOnly`는 편집과 달력 열기를 막습니다. 잠금 전환 시 열린 달력을 닫습니다. 잘못된 저장 기본값은 원문과 오류를 표시합니다.
package/README.md CHANGED
@@ -54,6 +54,20 @@ const StatusPill = createStatusPill({
54
54
 
55
55
  Unknown closed-domain status values throw to expose incomplete catalogs. Domains listed in `openDomains` instead show the unknown value as escaped text.
56
56
 
57
+ ## usePendingAction
58
+
59
+ A screen with several buttons needs to know which one started the work. Pass one shared flag to every button and they all spin on a single click.
60
+
61
+ ```tsx
62
+ const action = usePendingAction<"approve" | "reject">();
63
+ <Button tone="danger" loading={action.is("reject")} disabled={action.busy}
64
+ onClick={() => action.run("reject", () => decide("reject"))}>Reject</Button>
65
+ <Button loading={action.is("approve")} disabled={action.busy}
66
+ onClick={() => action.run("approve", () => decide("approve"))}>Approve</Button>
67
+ ```
68
+
69
+ The same contract as Solid's `createPendingAction`, with values in place of accessors. `is(key)` is true only for the running action; `busy` locks the rest. `run` clears the state when the task settles, passes its error on, and does nothing while another action runs, even for a second click in the same event loop turn, before React has rendered the first. Pass `{ replace: true }` where the latest request should win, such as a list reload. The task receives an `AbortSignal` that aborts on `reset()`, on a run that replaced it, and on unmount: check `signal.aborted` after each await before setting state, or pass it to `fetch`. A late completion never clears a newer action.
70
+
57
71
  ### DatePicker manual input and saving
58
72
 
59
73
  `value`/`onChange` remain canonical date-only `YYYY-MM-DD` strings (or intentional clear `''`). Complete real dates commit while typing; invalid/incomplete text stays visible and never becomes a replacement date. `required` forwards native/accessible required state; `readOnly` prevents edits/calendar opening. Locked transitions close the portal. Invalid persisted values render an error without being parsed or cleared.
package/dist/index.d.ts CHANGED
@@ -15,6 +15,7 @@ export { Toast as ArkToast } from "@ark-ui/react/toast";
15
15
  export * from "./date-picker";
16
16
  export { DatePicker as ArkDatePicker } from "@ark-ui/react/date-picker";
17
17
  export * from "./status-pill";
18
+ export * from "./pending-action";
18
19
  export * from "./input";
19
20
  export * from "./combobox";
20
21
  export * from "./select-picker";
@@ -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,OAAO,EAAE,UAAU,IAAI,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAExE,cAAc,eAAe,CAAC;AAE9B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,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,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,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"}
package/dist/index.js CHANGED
@@ -6,41 +6,41 @@ import { SelectPicker as f } from "./select-picker.js";
6
6
  import { DropdownMenu as p } from "./dropdown-menu.js";
7
7
  import { Popover as m } from "./popover.js";
8
8
  import { Calendar as h } from "./calendar.js";
9
- import { createContext as g, forwardRef as _, useContext as v, useEffect as y, useId as b, useMemo as x, useRef as S, useState as C } from "react";
10
- import { Field as w } from "@ark-ui/react/field";
11
- import { Checkbox as T } from "@ark-ui/react/checkbox";
12
- import { Switch as E } from "@ark-ui/react/switch";
13
- import { Fragment as D, jsx as O, jsxs as k } from "react/jsx-runtime";
14
- import { Tabs as A, Tabs as j, useTabsContext as ee } from "@ark-ui/react/tabs";
15
- import { RadioGroup as te, RadioGroup as M, useRadioGroupContext as N } from "@ark-ui/react/radio-group";
16
- import { Dialog as P, Dialog as F } from "@ark-ui/react/dialog";
17
- import { Tooltip as I, Tooltip as L } from "@ark-ui/react/tooltip";
18
- import { Portal as R } from "@ark-ui/react/portal";
19
- import { directionPolicy as z, icons as B } from "@devslab/dds-icons";
20
- import { Toast as V, Toast as H, Toaster as U, createToaster as W } from "@ark-ui/react/toast";
21
- import { DatePicker as G } from "@ark-ui/react/date-picker";
9
+ import { createContext as g, forwardRef as _, useCallback as v, useContext as y, useEffect as b, useId as x, useMemo as S, useRef as C, useState as w } from "react";
10
+ import { Field as T } from "@ark-ui/react/field";
11
+ import { Checkbox as E } from "@ark-ui/react/checkbox";
12
+ import { Switch as D } from "@ark-ui/react/switch";
13
+ import { Fragment as ee, jsx as O, jsxs as k } from "react/jsx-runtime";
14
+ import { Tabs as A, Tabs as j, useTabsContext as M } from "@ark-ui/react/tabs";
15
+ import { RadioGroup as te, RadioGroup as N, useRadioGroupContext as P } from "@ark-ui/react/radio-group";
16
+ import { Dialog as F, Dialog as I } from "@ark-ui/react/dialog";
17
+ import { Tooltip as L, Tooltip as R } from "@ark-ui/react/tooltip";
18
+ import { Portal as z } from "@ark-ui/react/portal";
19
+ import { directionPolicy as B, icons as V } from "@devslab/dds-icons";
20
+ import { Toast as H, Toast as U, Toaster as W, createToaster as G } from "@ark-ui/react/toast";
21
+ import { DatePicker as K } from "@ark-ui/react/date-picker";
22
22
  //#region src/selection.tsx
23
- var K = _(function({ onValueChange: e, unstyled: n, className: r, ...i }, a) {
23
+ var q = _(function({ onValueChange: e, unstyled: n, className: r, ...i }, a) {
24
24
  return /* @__PURE__ */ O(j.Root, {
25
25
  ...i,
26
26
  ref: a,
27
27
  onValueChange: (t) => e?.(t.value),
28
28
  className: t(!n && "dds-tabs-root", r)
29
29
  });
30
- }), q = _(function({ unstyled: e, className: n, ...r }, i) {
30
+ }), J = _(function({ unstyled: e, className: n, ...r }, i) {
31
31
  return /* @__PURE__ */ O(j.List, {
32
32
  ...r,
33
33
  ref: i,
34
34
  className: t(!e && "dds-tabs", n)
35
35
  });
36
- }), J = _(function({ unstyled: e, className: n, ...r }, i) {
36
+ }), Y = _(function({ unstyled: e, className: n, ...r }, i) {
37
37
  return /* @__PURE__ */ O(j.Trigger, {
38
38
  ...r,
39
39
  ref: i,
40
40
  className: t(!e && "dds-tab", n)
41
41
  });
42
- }), Y = _(function({ value: e, style: t, ...n }, r) {
43
- let i = ee().value !== e;
42
+ }), X = _(function({ value: e, style: t, ...n }, r) {
43
+ let i = M().value !== e;
44
44
  return /* @__PURE__ */ O(j.Content, {
45
45
  ...n,
46
46
  value: e,
@@ -52,8 +52,8 @@ var K = _(function({ onValueChange: e, unstyled: n, className: r, ...i }, a) {
52
52
  } : t
53
53
  });
54
54
  });
55
- function X({ option: e }) {
56
- let t = N(), { style: n, defaultChecked: r, ...i } = t.getItemHiddenInputProps(e);
55
+ function Z({ option: e }) {
56
+ let t = P(), { style: n, defaultChecked: r, ...i } = t.getItemHiddenInputProps(e);
57
57
  return /* @__PURE__ */ O("input", {
58
58
  ...i,
59
59
  checked: t.value === e.value,
@@ -61,8 +61,8 @@ function X({ option: e }) {
61
61
  className: "dds-check__input"
62
62
  });
63
63
  }
64
- var Z = _(function({ options: e, label: n, onValueChange: r, className: i, children: a, ...o }, s) {
65
- return /* @__PURE__ */ k(M.Root, {
64
+ var ne = _(function({ options: e, label: n, onValueChange: r, className: i, children: a, ...o }, s) {
65
+ return /* @__PURE__ */ k(N.Root, {
66
66
  ...o,
67
67
  ref: s,
68
68
  onValueChange: (e) => {
@@ -70,26 +70,26 @@ var Z = _(function({ options: e, label: n, onValueChange: r, className: i, child
70
70
  },
71
71
  className: t("dds-radio-group", i),
72
72
  children: [
73
- /* @__PURE__ */ O(M.Label, {
73
+ /* @__PURE__ */ O(N.Label, {
74
74
  className: "dds-field__label",
75
75
  children: n
76
76
  }),
77
- e.map((e) => /* @__PURE__ */ k(M.Item, {
77
+ e.map((e) => /* @__PURE__ */ k(N.Item, {
78
78
  value: e.value,
79
79
  disabled: e.disabled,
80
80
  className: "dds-check",
81
- children: [/* @__PURE__ */ O(X, { option: e }), /* @__PURE__ */ O(M.ItemText, { children: e.label })]
81
+ children: [/* @__PURE__ */ O(Z, { option: e }), /* @__PURE__ */ O(N.ItemText, { children: e.label })]
82
82
  }, e.value)),
83
83
  a
84
84
  ]
85
85
  });
86
- }), ne = _(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) {
86
+ }), re = _(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) {
87
87
  let _ = {
88
- title: /* @__PURE__ */ O(F.Title, {
88
+ title: /* @__PURE__ */ O(I.Title, {
89
89
  className: m ? void 0 : "dds-dialog__title",
90
90
  children: e
91
91
  }),
92
- description: n && /* @__PURE__ */ O(F.Description, {
92
+ description: n && /* @__PURE__ */ O(I.Description, {
93
93
  className: m ? void 0 : "dds-dialog__body",
94
94
  children: n
95
95
  }),
@@ -98,14 +98,14 @@ var Z = _(function({ options: e, label: n, onValueChange: r, className: i, child
98
98
  className: m ? void 0 : "dds-dialog__actions",
99
99
  children: i
100
100
  })
101
- }, v = /* @__PURE__ */ O(F.Positioner, {
101
+ }, v = /* @__PURE__ */ O(I.Positioner, {
102
102
  className: t(!m && "dds-dialog-overlay", l),
103
- children: /* @__PURE__ */ O(F.Content, {
103
+ children: /* @__PURE__ */ O(I.Content, {
104
104
  ...u,
105
105
  ref: g,
106
106
  "aria-describedby": n ? u?.["aria-describedby"] : void 0,
107
107
  className: t(!m && "dds-dialog", c, u?.className),
108
- children: p ? p(_) : /* @__PURE__ */ k(D, { children: [
108
+ children: p ? p(_) : /* @__PURE__ */ k(ee, { children: [
109
109
  _.title,
110
110
  _.description,
111
111
  r,
@@ -113,7 +113,7 @@ var Z = _(function({ options: e, label: n, onValueChange: r, className: i, child
113
113
  ] })
114
114
  })
115
115
  });
116
- return /* @__PURE__ */ O(F.Root, {
116
+ return /* @__PURE__ */ O(I.Root, {
117
117
  ...h,
118
118
  onOpenChange: (e) => a?.(e.open),
119
119
  closeOnInteractOutside: o ?? h.closeOnInteractOutside,
@@ -121,21 +121,21 @@ var Z = _(function({ options: e, label: n, onValueChange: r, className: i, child
121
121
  finalFocusEl: f ? () => f() ?? null : h.finalFocusEl,
122
122
  lazyMount: !0,
123
123
  unmountOnExit: !0,
124
- children: s ? /* @__PURE__ */ O(R, { children: v }) : v
124
+ children: s ? /* @__PURE__ */ O(z, { children: v }) : v
125
125
  });
126
126
  });
127
- function re({ content: e, children: n, onOpenChange: r, className: i, contentProps: a, ...o }) {
128
- return /* @__PURE__ */ O(L.Root, {
127
+ function ie({ content: e, children: n, onOpenChange: r, className: i, contentProps: a, ...o }) {
128
+ return /* @__PURE__ */ O(R.Root, {
129
129
  openDelay: 0,
130
130
  closeDelay: 0,
131
131
  ...o,
132
132
  onOpenChange: (e) => r?.(e.open),
133
133
  children: /* @__PURE__ */ k("span", {
134
134
  className: t("dds-tooltip", i),
135
- children: [typeof n == "function" ? /* @__PURE__ */ O(L.Context, { children: (e) => n(e.getTriggerProps()) }) : /* @__PURE__ */ O(L.Trigger, {
135
+ children: [typeof n == "function" ? /* @__PURE__ */ O(R.Context, { children: (e) => n(e.getTriggerProps()) }) : /* @__PURE__ */ O(R.Trigger, {
136
136
  asChild: !0,
137
137
  children: n
138
- }), /* @__PURE__ */ O(R, { children: /* @__PURE__ */ O(L.Positioner, { children: /* @__PURE__ */ O(L.Content, {
138
+ }), /* @__PURE__ */ O(z, { children: /* @__PURE__ */ O(R.Positioner, { children: /* @__PURE__ */ O(R.Content, {
139
139
  ...a,
140
140
  className: t("dds-tooltip__bubble", a?.className),
141
141
  children: e
@@ -145,8 +145,8 @@ function re({ content: e, children: n, onOpenChange: r, className: i, contentPro
145
145
  }
146
146
  //#endregion
147
147
  //#region src/icon.tsx
148
- var Q = _(function({ name: e, label: n, size: r = 24, directional: i, className: a, ...o }, s) {
149
- let c = B[e];
148
+ var ae = _(function({ name: e, label: n, size: r = 24, directional: i, className: a, ...o }, s) {
149
+ let c = V[e];
150
150
  return /* @__PURE__ */ k("svg", {
151
151
  ...o,
152
152
  ref: s,
@@ -161,19 +161,19 @@ var Q = _(function({ name: e, label: n, size: r = 24, directional: i, className:
161
161
  role: n ? "img" : void 0,
162
162
  "aria-label": n,
163
163
  "aria-hidden": !n || void 0,
164
- className: t((i ?? z.mirrorInRtl.includes(e)) && z.cssClass, a),
164
+ className: t((i ?? B.mirrorInRtl.includes(e)) && B.cssClass, a),
165
165
  children: [n && /* @__PURE__ */ O("title", { children: n }), /* @__PURE__ */ O("g", { dangerouslySetInnerHTML: { __html: c.body } })]
166
166
  });
167
- }), $ = g(null);
168
- function ie({ children: e, defaultDuration: n = 5e3, dismissLabel: r, regionLabel: i, className: a }) {
169
- let o = b(), s = S(0), c = x(() => W({
167
+ }), Q = g(null);
168
+ function oe({ children: e, defaultDuration: n = 5e3, dismissLabel: r, regionLabel: i, className: a }) {
169
+ let o = x(), s = C(0), c = S(() => G({
170
170
  placement: "bottom-end",
171
171
  overlap: !1,
172
172
  gap: 8,
173
173
  offsets: "var(--dds-space-16)",
174
174
  removeDelay: 0,
175
175
  hotkey: ["DDS_NO_HOTKEY"]
176
- }), []), l = x(() => ({
176
+ }), []), l = S(() => ({
177
177
  show(e) {
178
178
  let t = `dds-toast-${o}-${++s.current}`, r = e.duration ?? n;
179
179
  return c.create({
@@ -194,9 +194,9 @@ function ie({ children: e, defaultDuration: n = 5e3, dismissLabel: r, regionLabe
194
194
  o,
195
195
  n
196
196
  ]);
197
- return y(() => () => c.remove(), [c]), /* @__PURE__ */ k($.Provider, {
197
+ return b(() => () => c.remove(), [c]), /* @__PURE__ */ k(Q.Provider, {
198
198
  value: l,
199
- children: [e, /* @__PURE__ */ O(U, {
199
+ children: [e, /* @__PURE__ */ O(W, {
200
200
  toaster: c,
201
201
  label: i ?? "",
202
202
  "aria-label": i ?? "",
@@ -204,10 +204,10 @@ function ie({ children: e, defaultDuration: n = 5e3, dismissLabel: r, regionLabe
204
204
  className: t("dds-toast-region", a),
205
205
  children: (e) => {
206
206
  let n = e.meta?.dds;
207
- return /* @__PURE__ */ k(V.Root, {
207
+ return /* @__PURE__ */ k(H.Root, {
208
208
  className: t("dds-toast", `dds-toast--${n.tone ?? "info"}`),
209
209
  role: n.tone === "danger" ? "alert" : "status",
210
- children: [/* @__PURE__ */ O(V.Description, { children: e.description }), r && /* @__PURE__ */ O(V.CloseTrigger, {
210
+ children: [/* @__PURE__ */ O(H.Description, { children: e.description }), r && /* @__PURE__ */ O(H.CloseTrigger, {
211
211
  className: "dds-iconbtn dds-iconbtn--sm",
212
212
  "aria-label": typeof r == "function" ? r(n) : r,
213
213
  children: "×"
@@ -217,19 +217,19 @@ function ie({ children: e, defaultDuration: n = 5e3, dismissLabel: r, regionLabe
217
217
  })]
218
218
  });
219
219
  }
220
- function ae() {
221
- let e = v($);
220
+ function $() {
221
+ let e = y(Q);
222
222
  if (!e) throw Error("useToast must be called inside <ToastProvider>");
223
223
  return e;
224
224
  }
225
225
  //#endregion
226
226
  //#region src/console-shell.tsx
227
- function oe(e, t) {
227
+ function se(e, t) {
228
228
  return t.active ?? (t.href.split("/").filter(Boolean).length <= 1 ? e === t.href : e === t.href || e.startsWith(`${t.href}/`));
229
229
  }
230
- var se = _(function({ surface: e, activePath: n, brand: r, context: i, nav: a, labels: o, header: s, foot: c, children: l, className: u, ...d }, f) {
231
- let [p, m] = C(!1), [h, g] = C(!1), _ = b(), v = `dds-console-rail-${_}`, x = `dds-console-main-${_}`;
232
- return y(() => {
230
+ var ce = _(function({ surface: e, activePath: n, brand: r, context: i, nav: a, labels: o, header: s, foot: c, children: l, className: u, ...d }, f) {
231
+ let [p, m] = w(!1), [h, g] = w(!1), _ = x(), v = `dds-console-rail-${_}`, y = `dds-console-main-${_}`;
232
+ return b(() => {
233
233
  g(!0);
234
234
  let e = (e) => {
235
235
  e.key === "Escape" && m(!1);
@@ -244,7 +244,7 @@ var se = _(function({ surface: e, activePath: n, brand: r, context: i, nav: a, l
244
244
  children: [
245
245
  /* @__PURE__ */ O("a", {
246
246
  className: "dds-console-skip dds-visually-hidden",
247
- href: `#${x}`,
247
+ href: `#${y}`,
248
248
  children: o.skip
249
249
  }),
250
250
  /* @__PURE__ */ k("button", {
@@ -297,7 +297,7 @@ var se = _(function({ surface: e, activePath: n, brand: r, context: i, nav: a, l
297
297
  className: "dds-console-rail__item",
298
298
  "data-nav": `${e}.${t.id}`,
299
299
  href: t.href,
300
- "aria-current": oe(n, t) ? "page" : void 0,
300
+ "aria-current": se(n, t) ? "page" : void 0,
301
301
  onClick: () => m(!1),
302
302
  children: [/* @__PURE__ */ O("span", { children: t.label }), t.badge !== void 0 && t.badge > 0 && /* @__PURE__ */ O("span", {
303
303
  className: "dds-console-rail__badge",
@@ -314,7 +314,7 @@ var se = _(function({ surface: e, activePath: n, brand: r, context: i, nav: a, l
314
314
  ]
315
315
  }),
316
316
  /* @__PURE__ */ k("main", {
317
- id: x,
317
+ id: y,
318
318
  className: "dds-console-main",
319
319
  tabIndex: -1,
320
320
  children: [/* @__PURE__ */ k("header", {
@@ -336,7 +336,7 @@ var se = _(function({ surface: e, activePath: n, brand: r, context: i, nav: a, l
336
336
  });
337
337
  //#endregion
338
338
  //#region src/status-pill.tsx
339
- function ce(e) {
339
+ function le(e) {
340
340
  let t = new Set(e.openDomains ?? []);
341
341
  return function(n) {
342
342
  let r = e.tones[n.domain]?.[n.value], i = e.label(n.domain, n.value, n.locale);
@@ -356,6 +356,38 @@ function ce(e) {
356
356
  };
357
357
  }
358
358
  //#endregion
359
- export { T as ArkCheckbox, G as ArkDatePicker, P as ArkDialog, w as ArkField, te as ArkRadioGroup, E as ArkSwitch, A as ArkTabs, H as ArkToast, I as ArkTooltip, s as Button, h as Calendar, r as Checkbox, d as Combobox, se as ConsoleShell, c as DatePicker, ne as Dialog, p as DropdownMenu, a as Field, Q as Icon, n as IconButton, l as Input, u as InputGroup, m as Popover, e as Radio, Z as RadioGroup, i as Select, f as SelectPicker, o as Switch, J as Tab, q as TabList, Y as TabPanel, K as Tabs, ie as ToastProvider, re as Tooltip, t as classes, ce as createStatusPill, ae as useToast };
359
+ //#region src/pending-action.ts
360
+ function ue() {
361
+ let [e, t] = w(null), n = C(null);
362
+ b(() => () => {
363
+ n.current?.abort(), n.current = null;
364
+ }, []);
365
+ let r = v(async (e, r, i) => {
366
+ if (n.current && !i?.replace) return;
367
+ n.current?.abort();
368
+ let a = new AbortController();
369
+ n.current = a, t(e);
370
+ try {
371
+ return await r(a.signal);
372
+ } finally {
373
+ n.current === a && (n.current = null, t(null));
374
+ }
375
+ }, []), i = v(() => {
376
+ n.current?.abort(), n.current = null, t(null);
377
+ }, []);
378
+ return S(() => ({
379
+ current: e,
380
+ busy: e !== null,
381
+ is: (t) => e === t,
382
+ run: r,
383
+ reset: i
384
+ }), [
385
+ e,
386
+ r,
387
+ i
388
+ ]);
389
+ }
390
+ //#endregion
391
+ export { E as ArkCheckbox, K as ArkDatePicker, F as ArkDialog, T as ArkField, te as ArkRadioGroup, D as ArkSwitch, A as ArkTabs, U as ArkToast, L as ArkTooltip, s as Button, h as Calendar, r as Checkbox, d as Combobox, ce as ConsoleShell, c as DatePicker, re as Dialog, p as DropdownMenu, a as Field, ae as Icon, n as IconButton, l as Input, u as InputGroup, m as Popover, e as Radio, ne as RadioGroup, i as Select, f as SelectPicker, o as Switch, Y as Tab, J as TabList, X as TabPanel, q as Tabs, oe as ToastProvider, ie as Tooltip, t as classes, le as createStatusPill, ue as usePendingAction, $ as useToast };
360
392
 
361
393
  //# 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"],"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"],"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/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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"}
@@ -0,0 +1,36 @@
1
+ /** Options for one `run` call. */
2
+ export interface PendingActionRunOptions {
3
+ /**
4
+ * Start even while another action runs: that one is aborted and this one takes its place, so the
5
+ * latest request wins (a list reload after typing, paging or sorting). Without it a second start
6
+ * while one runs is ignored, which is what a button wants.
7
+ */
8
+ replace?: boolean;
9
+ }
10
+ /**
11
+ * Which of a screen's actions is running. A screen with several buttons gives each one its own
12
+ * key, so only the button that started the work shows progress, while every other control can
13
+ * still be locked through `busy`. One shared flag for all the buttons spins every one of them.
14
+ * The same contract as `createPendingAction` in `@devslab/dds-solid`, with values for accessors.
15
+ */
16
+ export interface PendingAction<K extends string = string> {
17
+ /** The key of the action now running, or null. */
18
+ readonly current: K | null;
19
+ /** True while any action runs: lock the other controls with it. */
20
+ readonly busy: boolean;
21
+ /** True while `key` is the running action: give that control its progress state. */
22
+ is(key: K): boolean;
23
+ /**
24
+ * Runs `task` as `key` and clears the state when it settles, whether it resolves or throws (the
25
+ * error reaches the caller). While another action runs it does nothing and resolves to undefined,
26
+ * unless `replace` is set. The task receives a signal that aborts when this run stops counting:
27
+ * `reset()`, a run that replaced it, or the component unmounting. Check `signal.aborted` after
28
+ * each await before touching state, or pass the signal to `fetch`.
29
+ */
30
+ run<T>(key: K, task: (signal: AbortSignal) => T | Promise<T>, options?: PendingActionRunOptions): Promise<T | undefined>;
31
+ /** Stops tracking the running action and aborts its signal, for example when the screen's data was replaced. */
32
+ reset(): void;
33
+ }
34
+ /** Tracks the running action of a component. */
35
+ export declare function usePendingAction<K extends string = string>(): PendingAction<K>;
36
+ //# sourceMappingURL=pending-action.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pending-action.d.ts","sourceRoot":"","sources":["../src/pending-action.ts"],"names":[],"mappings":"AAEA,kCAAkC;AAClC,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACtD,kDAAkD;IAClD,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC;IAC3B,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,oFAAoF;IACpF,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC;IACpB;;;;;;OAMG;IACH,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IACzH,gHAAgH;IAChH,KAAK,IAAI,IAAI,CAAC;CACf;AAED,gDAAgD;AAChD,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,KAAK,aAAa,CAAC,CAAC,CAAC,CAuC9E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devslab/dds-react",
3
- "version": "0.22.0",
3
+ "version": "0.23.0",
4
4
  "description": "Accessible React primitives for the DevsLab Design System",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -74,9 +74,9 @@
74
74
  },
75
75
  "dependencies": {
76
76
  "@ark-ui/react": "5.39.3",
77
- "@devslab/dds-css": "0.22.0",
78
- "@devslab/dds-icons": "0.22.0",
79
- "@devslab/dds-tokens": "0.22.0",
77
+ "@devslab/dds-css": "0.23.0",
78
+ "@devslab/dds-icons": "0.23.0",
79
+ "@devslab/dds-tokens": "0.23.0",
80
80
  "@tanstack/react-virtual": "3.14.21"
81
81
  },
82
82
  "peerDependencies": {