@danxbot/ui 20.19.0 → 20.21.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.
@@ -1,4 +1,5 @@
1
1
  import type { ButtonProps } from "./Button";
2
+ import { type IconName } from "./Icon";
2
3
  export type SortDirection = "asc" | "desc";
3
4
  export interface SortOption<Field extends string = string> {
4
5
  value: Field;
@@ -15,6 +16,12 @@ export interface SortOption<Field extends string = string> {
15
16
  asc: string;
16
17
  desc: string;
17
18
  };
19
+ /**
20
+ * A registered icon for the field (DX-4615). When the sorted field carries one, the closed control draws it before the
21
+ * direction's arrow ("what" then "which way"), and the popover draws it beside the field's label. A list whose options
22
+ * carry none renders exactly as it did; give every option an icon or none, so the rows and the trigger stay one shape.
23
+ */
24
+ icon?: IconName;
18
25
  }
19
26
  export interface SortValue<Field extends string = string> {
20
27
  field: Field;
@@ -27,7 +34,12 @@ export interface SortMenuProps<Field extends string = string> {
27
34
  /** Names the control for assistive technology, e.g. "Sort plans". The active order is appended to it. */
28
35
  "aria-label": string;
29
36
  size?: ButtonProps["size"];
37
+ /**
38
+ * The trigger's resting look (DX-4615). `outline` (default) draws the bordered button; `ghost` draws the bare arrow, for a
39
+ * header that already holds other borderless icons (a board lane's title row). Same arrow, same tooltip, same popover.
40
+ */
41
+ triggerVariant?: "outline" | "ghost";
30
42
  align?: "start" | "center" | "end";
31
43
  className?: string;
32
44
  }
33
- export declare function SortMenu<Field extends string = string>({ options, value, onValueChange, "aria-label": ariaLabel, size, align, className, }: SortMenuProps<Field>): import("react").JSX.Element;
45
+ export declare function SortMenu<Field extends string = string>({ options, value, onValueChange, "aria-label": ariaLabel, size, triggerVariant, align, className, }: SortMenuProps<Field>): import("react").JSX.Element;
@@ -1462,6 +1462,68 @@ export declare const coreIcons: {
1462
1462
  readonly wrench: readonly [readonly ["path", {
1463
1463
  readonly d: "M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z";
1464
1464
  }]];
1465
+ readonly "calendar-plus": readonly [readonly ["path", {
1466
+ readonly d: "M16 19h6";
1467
+ }], readonly ["path", {
1468
+ readonly d: "M16 2v4";
1469
+ }], readonly ["path", {
1470
+ readonly d: "M19 16v6";
1471
+ }], readonly ["path", {
1472
+ readonly d: "M21 12.598V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8.5";
1473
+ }], readonly ["path", {
1474
+ readonly d: "M3 10h18";
1475
+ }], readonly ["path", {
1476
+ readonly d: "M8 2v4";
1477
+ }]];
1478
+ readonly "clock-arrow-up": readonly [readonly ["path", {
1479
+ readonly d: "M12 6v6l1.56.78";
1480
+ }], readonly ["path", {
1481
+ readonly d: "M13.227 21.925a10 10 0 1 1 8.767-9.588";
1482
+ }], readonly ["path", {
1483
+ readonly d: "m14 18 4-4 4 4";
1484
+ }], readonly ["path", {
1485
+ readonly d: "M18 22v-8";
1486
+ }]];
1487
+ readonly files: readonly [readonly ["path", {
1488
+ readonly d: "M15 2a2 2 0 0 1 1.414.586l4 4A2 2 0 0 1 21 8v7a2 2 0 0 1-2 2h-8a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2z";
1489
+ }], readonly ["path", {
1490
+ readonly d: "M15 2v4a2 2 0 0 0 2 2h4";
1491
+ }], readonly ["path", {
1492
+ readonly d: "M5 7a2 2 0 0 0-2 2v11a2 2 0 0 0 2 2h8a2 2 0 0 0 1.732-1";
1493
+ }]];
1494
+ readonly hash: readonly [readonly ["line", {
1495
+ readonly x1: "4";
1496
+ readonly x2: "20";
1497
+ readonly y1: "9";
1498
+ readonly y2: "9";
1499
+ }], readonly ["line", {
1500
+ readonly x1: "4";
1501
+ readonly x2: "20";
1502
+ readonly y1: "15";
1503
+ readonly y2: "15";
1504
+ }], readonly ["line", {
1505
+ readonly x1: "10";
1506
+ readonly x2: "8";
1507
+ readonly y1: "3";
1508
+ readonly y2: "21";
1509
+ }], readonly ["line", {
1510
+ readonly x1: "16";
1511
+ readonly x2: "14";
1512
+ readonly y1: "3";
1513
+ readonly y2: "21";
1514
+ }]];
1515
+ readonly milestone: readonly [readonly ["path", {
1516
+ readonly d: "M12 13v8";
1517
+ }], readonly ["path", {
1518
+ readonly d: "M12 3v3";
1519
+ }], readonly ["path", {
1520
+ readonly d: "M4 6a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1h13a2 2 0 0 0 1.152-.365l3.424-2.317a1 1 0 0 0 0-1.635l-3.424-2.318A2 2 0 0 0 17 6z";
1521
+ }]];
1522
+ readonly signature: readonly [readonly ["path", {
1523
+ readonly d: "m21 17-2.156-1.868A.5.5 0 0 0 18 15.5v.5a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1c0-2.545-3.991-3.97-8.5-4a1 1 0 0 0 0 5c4.153 0 4.745-11.295 5.708-13.5a2.5 2.5 0 1 1 3.31 3.284";
1524
+ }], readonly ["path", {
1525
+ readonly d: "M3 21h18";
1526
+ }]];
1465
1527
  readonly "align-center": readonly [readonly ["path", {
1466
1528
  readonly d: "M21 5H3";
1467
1529
  }], readonly ["path", {
@@ -116,7 +116,7 @@ export { Board, BoardColumn, BoardCard, BoardCardSurface, type BoardProps, type
116
116
  export { buildBoardModel, resolveMove, applyBoardMoves, useBoard, moveAnchor, columnLength, positionInColumn, type BoardModel, type MoveAnchor, type UseBoardResult, } from "./lib/board";
117
117
  export type { BoardAccessors, BoardColumnDef, BoardEdge, BoardColumnId, BoardColumnModel, BoardItemId, BoardMove, BoardMoveTarget, BoardMoveRequest, BoardMoveSource, BoardMoveVerdict, BoardReorderLabels, UseBoardOptions, } from "./lib/board";
118
118
  export { PagedWindowList, type PagedWindowItemPosition, type PagedWindowListProps, type PagedWindowStrings, } from "./components/PagedWindowList";
119
- export { PagedWindowStore, usePagedWindow, windowPageNumbers, type LoadCount, type LoadPage, type LoadPageContext, type PageResponse, type PageSnapshot, type PageStatus, type PagedWindow, type PagedWindowMode, type PagedWindowOptions, type PagedWindowSnapshot, type UsePagedWindowOptions, } from "./lib/paged-window";
119
+ export { PAGED_WINDOW_SETTLE_MS, PagedWindowStore, usePagedWindow, windowPageNumbers, type LoadCount, type LoadPage, type LoadPageContext, type PageResponse, type PageSnapshot, type PageStatus, type PagedWindow, type PagedWindowMode, type PagedWindowOptions, type PagedWindowSnapshot, type UsePagedWindowOptions, } from "./lib/paged-window";
120
120
  export type { MessageRole, MessagePart, TextPart, CodePart, ReasoningPart, ToolPart, ToolStatus, FilePart, ComponentPart, ChatFile, ChatMessage, RenderContext, PartRenderer, PartRenderers, ChatComponentRenderer, ChatComponents, } from "./components/chat/types";
121
121
  export { Chat, ChatPopover, type ChatProps, type ChatPopoverProps, type ChatSurface, } from "./components/chat/Chat";
122
122
  export { Message, MessagePartView, ToolCall, type MessageProps, type MessageAction, type MessagePartViewProps, type ToolCallProps, } from "./components/chat/Message";
@@ -1,2 +1,2 @@
1
- export { PagedWindowStore, windowPageNumbers, type LoadCount, type LoadPage, type LoadPageContext, type PageResponse, type PageSnapshot, type PageStatus, type PagedWindowMode, type PagedWindowOptions, type PagedWindowSnapshot, } from "./store";
1
+ export { PAGED_WINDOW_SETTLE_MS, PagedWindowStore, windowPageNumbers, type LoadCount, type LoadPage, type LoadPageContext, type PageResponse, type PageSnapshot, type PageStatus, type PagedWindowMode, type PagedWindowOptions, type PagedWindowSnapshot, } from "./store";
2
2
  export { usePagedWindow, type PagedWindow, type UsePagedWindowOptions } from "./use-paged-window";
@@ -12,6 +12,8 @@ export type LoadPage<T> = (page: number, context: LoadPageContext) => Promise<Pa
12
12
  /** Answers the list's length alone — no items. What a hidden (`count` mode) lane asks. */
13
13
  export type LoadCount = (context: LoadPageContext) => Promise<number>;
14
14
  export type PagedWindowMode = "pages" | "count";
15
+ /** How long the viewer's page must stay put before the window moves to it, in ms. */
16
+ export declare const PAGED_WINDOW_SETTLE_MS = 200;
15
17
  export type PageStatus = "loading" | "ready" | "error";
16
18
  export interface PageSnapshot<T> {
17
19
  page: number;
@@ -54,6 +56,12 @@ export interface PagedWindowOptions<T> {
54
56
  loadCount?: LoadCount;
55
57
  /** @default "pages" */
56
58
  mode?: PagedWindowMode;
59
+ /**
60
+ * How long the viewer's page must stay put before the window moves to it; 0
61
+ * moves it synchronously. A negative or fractional value throws.
62
+ * @default PAGED_WINDOW_SETTLE_MS
63
+ */
64
+ settleMs?: number;
57
65
  }
58
66
  /**
59
67
  * The pages to hold for an anchor: `windowPages` of them centred on it (the
@@ -64,13 +72,17 @@ export declare function windowPageNumbers(anchorPage: number, pageCount: number,
64
72
  export declare class PagedWindowStore<T> {
65
73
  private readonly pageSize;
66
74
  private readonly windowPages;
75
+ private readonly settleMs;
67
76
  private loadPage;
68
77
  private loadCount;
69
78
  private held;
70
79
  private total;
80
+ /** Where the viewer is; moves the instant they do. */
71
81
  private anchor;
72
- /** The anchor the held pages were last synced to; differs from `anchor` only while frozen. */
82
+ /** The anchor the held pages were last synced to; differs from `anchor` while the viewer is still moving, or frozen. */
73
83
  private appliedAnchor;
84
+ /** Moves the window to `anchor` once it has been still for `settleMs`; null when no move is waiting. */
85
+ private settleTimer;
74
86
  private mode;
75
87
  private frozen;
76
88
  private epoch;
@@ -85,7 +97,7 @@ export declare class PagedWindowStore<T> {
85
97
  private countError;
86
98
  private snapshot;
87
99
  private listeners;
88
- constructor({ pageSize, windowPages, loadPage, loadCount, mode }: PagedWindowOptions<T>);
100
+ constructor({ pageSize, windowPages, loadPage, loadCount, mode, settleMs, }: PagedWindowOptions<T>);
89
101
  /**
90
102
  * Replace the loaders. The React binding calls this after every commit so a
91
103
  * consumer's loaders can close over fresh state without the store being
@@ -95,7 +107,10 @@ export declare class PagedWindowStore<T> {
95
107
  setLoaders(loadPage: LoadPage<T>, loadCount: LoadCount | undefined): void;
96
108
  getSnapshot: () => PagedWindowSnapshot<T>;
97
109
  subscribe: (listener: () => void) => (() => void);
98
- /** The viewer moved to another page. Ignored while frozen, applied on thaw. */
110
+ /**
111
+ * The viewer moved to another page. The window follows once they have stayed
112
+ * there for `settleMs`; while frozen it follows on thaw.
113
+ */
99
114
  setAnchorPage(page: number): void;
100
115
  /**
101
116
  * While true nothing about the window changes: it neither loads nor drops
@@ -130,7 +145,16 @@ export declare class PagedWindowStore<T> {
130
145
  private wanted;
131
146
  /** Bring the held pages to the wanted ones — unless frozen, when that waits for the thaw. */
132
147
  private sync;
133
- /** `force` is `reset()`'s alone: it brings the window to its (new) list even while frozen. */
148
+ /** The viewer has settled on `anchor`: the window moves to it, in one step. */
149
+ private applyAnchor;
150
+ private clearSettle;
151
+ /**
152
+ * Moves the held pages to the window around `appliedAnchor` — which only
153
+ * `applyAnchor`, `thaw` and `reset` move, so a response arriving while the
154
+ * viewer is still moving brings in no page of the unsettled position.
155
+ * `force` is `reset()`'s alone: it brings the window to its (new) list even
156
+ * while frozen.
157
+ */
134
158
  private reconcile;
135
159
  /** Everything the frozen window put off, in the order the header promises. */
136
160
  private thaw;
@@ -34,8 +34,14 @@ export interface PagedWindow<T> extends PagedWindowSnapshot<T> {
34
34
  * view which ones to show. `loadPage` answers one page AND the list's current
35
35
  * length, so the scrollbar can span `total` before most of it is loaded.
36
36
  *
37
+ * The window moves to the viewer's page only after it has stayed put for
38
+ * `settleMs` (200 ms by default), so a fast scroll loads the pages it lands
39
+ * on, never the ones it passes (DX-4614); a read for a page that leaves the
40
+ * window is aborted through its `signal`, and an aborted read is never an error.
41
+ *
37
42
  * `pageSize` and `windowPages` are fixed for the life of the hook: changing one
38
43
  * means every held page is cut differently, which is a different list — give it
39
- * a new `queryKey` and a new mount instead. It throws rather than guessing.
44
+ * a new `queryKey` and a new mount instead. `settleMs` is fixed too: the store
45
+ * reads it once. All three throw rather than guess.
40
46
  */
41
- export declare function usePagedWindow<T>({ pageSize, windowPages, loadPage, loadCount, queryKey, mode, }: UsePagedWindowOptions<T>): PagedWindow<T>;
47
+ export declare function usePagedWindow<T>({ pageSize, windowPages, loadPage, loadCount, queryKey, mode, settleMs, }: UsePagedWindowOptions<T>): PagedWindow<T>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danxbot/ui",
3
- "version": "20.19.0",
3
+ "version": "20.21.0",
4
4
  "type": "module",
5
5
  "description": "Danxbot — a domain-agnostic React design system with motion as a first-class primitive.",
6
6
  "license": "MIT",