@devslab/dds-solid 0.22.1 → 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
@@ -26,6 +26,40 @@ DDS가 공개 API와 시각 토큰을 소유한다. 기존 import와 콜백 값
26
26
  포인터·포커스 상호작용 중과 브라우저 페이지가 비활성일 때는 알림 타이머가
27
27
  멈춘다. duration이 0 이하이면 명시적으로 닫을 때까지 유지한다.
28
28
 
29
+ ## createPendingAction
30
+
31
+ 버튼이 여러 개인 화면은 어느 버튼이 작업을 시작했는지 알아야 한다. 모든 버튼에
32
+ 같은 플래그 하나를 넘기면 한 번만 눌러도 전부 돈다.
33
+
34
+ ```tsx
35
+ import { Button, createPendingAction } from "@devslab/dds-solid";
36
+ const action = createPendingAction<"approve" | "reject">();
37
+ <Button tone="danger" loading={action.is("reject")} disabled={action.busy()}
38
+ onClick={() => action.run("reject", () => decide("reject"))}>반려</Button>
39
+ <Button loading={action.is("approve")} disabled={action.busy()}
40
+ onClick={() => action.run("approve", () => decide("approve"))}>승인</Button>
41
+ ```
42
+
43
+ `is(key)`는 실행 중인 동작에만 참이라 그 컨트롤만 진행 상태를 보이고, `busy()`로
44
+ 나머지를 잠근다. `run`은 작업이 끝나면 성공·실패와 관계없이 상태를 지우고 오류는
45
+ 호출자에게 그대로 넘긴다. 다른 동작이 실행 중이면 아무것도 하지 않으므로 두 번
46
+ 눌러도 요청이 두 번 나가지 않는다. 목록 다시 불러오기처럼 마지막 요청이 이겨야 하는
47
+ 곳에는 `{ replace: true }`를 준다.
48
+
49
+ 작업은 `AbortSignal`을 받는다. 그 실행이 더는 유효하지 않을 때, 곧 `reset()`, 그
50
+ 실행을 대체한 새 실행, 컴포넌트 정리 때 abort된다. await 뒤에 화면을 바꾸기 전에
51
+ `signal.aborted`를 확인하거나 signal을 `fetch`에 넘기면 되므로 요청 번호나 "아직
52
+ 살아 있음" 플래그를 따로 둘 필요가 없다. 늦게 끝난 이전 작업은 새 동작의 상태를
53
+ 지우지 못한다.
54
+
55
+ ```tsx
56
+ const list = createPendingAction<"search" | "page">();
57
+ const reload = (key: "search" | "page") => list.run(key, async (signal) => {
58
+ const rows = await loadRows(filter());
59
+ if (!signal.aborted) setRows(rows);
60
+ }, { replace: true });
61
+ ```
62
+
29
63
  ## DatePicker
30
64
 
31
65
  ```tsx
package/README.md CHANGED
@@ -25,6 +25,38 @@ same. See [the migration guide](../../docs/ark-migration.md) for integration det
25
25
  pointer/focus interaction and when the browser page is idle. A non-positive duration
26
26
  keeps the toast until dismissed.
27
27
 
28
+ ## createPendingAction
29
+
30
+ A screen with several buttons needs to know which one started the work. Pass one shared flag
31
+ to every button and they all spin on a single click.
32
+
33
+ ```tsx
34
+ import { Button, createPendingAction } from "@devslab/dds-solid";
35
+ const action = createPendingAction<"approve" | "reject">();
36
+ <Button tone="danger" loading={action.is("reject")} disabled={action.busy()}
37
+ onClick={() => action.run("reject", () => decide("reject"))}>Reject</Button>
38
+ <Button loading={action.is("approve")} disabled={action.busy()}
39
+ onClick={() => action.run("approve", () => decide("approve"))}>Approve</Button>
40
+ ```
41
+
42
+ `is(key)` is true only for the running action, so only that control shows progress; `busy()`
43
+ locks the rest. `run` clears the state when the task settles, passes its error on, and does
44
+ nothing while another action runs, so a second click cannot start a second request. Pass
45
+ `{ replace: true }` where the latest request should win instead, such as a list reload.
46
+
47
+ The task receives an `AbortSignal` that aborts when its run stops counting: `reset()`, a run that
48
+ replaced it, or the component going away. Check `signal.aborted` after each await before touching
49
+ the screen, or pass the signal to `fetch`; no separate request counter or "still mounted" flag is
50
+ needed. A late completion never clears a newer action.
51
+
52
+ ```tsx
53
+ const list = createPendingAction<"search" | "page">();
54
+ const reload = (key: "search" | "page") => list.run(key, async (signal) => {
55
+ const rows = await loadRows(filter());
56
+ if (!signal.aborted) setRows(rows);
57
+ }, { replace: true });
58
+ ```
59
+
28
60
  ## DatePicker
29
61
 
30
62
  ```tsx
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@ export { ConsoleShell, type ConsoleHeader, type ConsoleNavGroup, type ConsoleNav
4
4
  export { Dialog, type DialogProps, type DialogFrameParts } from "./dialog";
5
5
  export { RadioGroup, type RadioGroupProps, type RadioOption } from "./radio-group";
6
6
  export { Icon, type IconProps } from "./icon";
7
+ export { createPendingAction, type PendingAction, type PendingActionRunOptions } from "./pending-action";
7
8
  export { createStatusPill } from "./status-pill";
8
9
  export type { StatusTone } from "./status-pill";
9
10
  export { Tab, TabList, TabPanel, Tabs, type TabPanelProps, type TabProps, type TabsProps } from "./tabs";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACpF,OAAO,EACL,MAAM,EACN,QAAQ,EACR,KAAK,EACL,UAAU,EACV,KAAK,EACL,MAAM,EACN,MAAM,EACN,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,WAAW,GACjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC/J,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AACnF,OAAO,EAAE,IAAI,EAAE,KAAK,SAAS,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,aAAa,EAAE,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,QAAQ,CAAC;AACzG,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,UAAU,EAAE,KAAK,kBAAkB,EAAE,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AAC3H,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAEjF,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAEjE,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,OAAO,EAAE,wBAAwB,EAAE,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACpF,OAAO,EACL,MAAM,EACN,QAAQ,EACR,KAAK,EACL,UAAU,EACV,KAAK,EACL,MAAM,EACN,MAAM,EACN,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,WAAW,GACjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC/J,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AACnF,OAAO,EAAE,IAAI,EAAE,KAAK,SAAS,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,KAAK,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AACzG,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,aAAa,EAAE,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,QAAQ,CAAC;AACzG,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,UAAU,EAAE,KAAK,kBAAkB,EAAE,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AAC3H,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAEjF,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAEjE,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC"}