@danxbot/ui 2.5.0 → 2.7.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.
@@ -5,10 +5,21 @@ export interface DragDropProps extends DragSessionCallbacks {
5
5
  strings?: Partial<DragStrings>;
6
6
  /** Tune the edge auto-scroll. It cannot be turned off; see the banner. */
7
7
  autoScroll?: AutoScrollOptions;
8
+ /**
9
+ * What the card in the hand SHOWS. Defaults to the carried item's own
10
+ * children, which is the version that cannot drift from the row it stands
11
+ * for.
12
+ *
13
+ * It does not decide whether the card is carried, or how — every carried card
14
+ * is a portalled clone, always. Worth passing when the resting row is dense:
15
+ * the clone is moving, usually under a cursor, and the two or three fields
16
+ * that identify the record are the only ones anybody reads off it.
17
+ */
18
+ renderCarried?: (id: DragId) => ReactNode;
8
19
  className?: string;
9
20
  children?: ReactNode;
10
21
  }
11
- export declare function DragDrop({ strings, autoScroll, className, children, ...callbacks }: DragDropProps): import("react").JSX.Element;
22
+ export declare function DragDrop({ strings, autoScroll, renderCarried, className, children, ...callbacks }: DragDropProps): import("react").JSX.Element;
12
23
  export interface DragDropContainerProps {
13
24
  id: ContainerId;
14
25
  /**
@@ -52,9 +63,3 @@ export interface DragDropHandleProps {
52
63
  children?: ReactNode;
53
64
  }
54
65
  export declare function DragDropHandle({ label, className, children }: DragDropHandleProps): import("react").JSX.Element;
55
- export interface DragDropOverlayProps {
56
- /** Renders the carried card. Called only while a card is being carried. */
57
- children: (id: DragId) => ReactNode;
58
- className?: string;
59
- }
60
- export declare function DragDropOverlay({ children, className }: DragDropOverlayProps): import("react").ReactPortal | null;
@@ -1,3 +1,4 @@
1
+ import { type ReactNode } from "react";
1
2
  import type { DragAxis, DragId, ContainerId, DragSession } from "../../lib/dnd";
2
3
  import type { ContainerShift } from "./shift";
3
4
  export interface DragDropContextValue {
@@ -14,15 +15,22 @@ export interface DragDropContextValue {
14
15
  */
15
16
  instructionsId: string;
16
17
  /**
17
- * True while a `<DragDropOverlay>` is mounted, i.e. while a portalled clone
18
- * is carrying the card and the row itself should render as the hole it left.
18
+ * What the carried card SHOWS — never how, whether, or where it is carried.
19
19
  *
20
- * It selects WHICH of the two carries the card, never WHETHER one does: with
21
- * no overlay the row follows the pointer under its own transform
22
- * (`shift.ts#carriedOffset`). Either way the slot is vacated and closes.
20
+ * There is exactly one carry mechanism (`DragDrop.tsx#CarriedCard`: a `fixed`
21
+ * clone portalled to the body) and every item uses it, so this is content and
22
+ * nothing else. Absent the ordinary case the clone renders the carried
23
+ * item's OWN children, which is the only version of the card that cannot
24
+ * drift from the row it stands for.
25
+ *
26
+ * This used to be a `lifted` boolean counting mounted `<DragDropOverlay>`s,
27
+ * and it selected a MECHANISM: overlay mounted meant a portalled clone,
28
+ * absent meant the row transformed itself in flow. Two mechanisms is what
29
+ * this field no longer is. A board that forgot the overlay got a card that
30
+ * could not leave its own scroll container, which is a defect a consumer had
31
+ * no way to know it owed — and the reason the mechanism is not a choice.
23
32
  */
24
- lifted: boolean;
25
- registerOverlay: () => () => void;
33
+ renderCarried: ((id: DragId) => ReactNode) | undefined;
26
34
  /** Items and containers publish their spoken names here at mount. */
27
35
  registerLabel: (kind: "item" | "container", id: string, label: string | undefined) => () => void;
28
36
  }
@@ -21,12 +21,6 @@ export declare const dnd: import("tailwind-variants").TVReturnType<{
21
21
  };
22
22
  false: {};
23
23
  };
24
- carried: {
25
- true: {
26
- shift: string;
27
- };
28
- false: {};
29
- };
30
24
  mode: {
31
25
  pointer: {
32
26
  overlay: string;
@@ -67,12 +61,6 @@ export declare const dnd: import("tailwind-variants").TVReturnType<{
67
61
  };
68
62
  false: {};
69
63
  };
70
- carried: {
71
- true: {
72
- shift: string;
73
- };
74
- false: {};
75
- };
76
64
  mode: {
77
65
  pointer: {
78
66
  overlay: string;
@@ -113,12 +101,6 @@ export declare const dnd: import("tailwind-variants").TVReturnType<{
113
101
  };
114
102
  false: {};
115
103
  };
116
- carried: {
117
- true: {
118
- shift: string;
119
- };
120
- false: {};
121
- };
122
104
  mode: {
123
105
  pointer: {
124
106
  overlay: string;
@@ -27,55 +27,57 @@ export interface ContainerShift {
27
27
  markerShift: (restIndex: number) => number;
28
28
  }
29
29
  /**
30
- * The carried item's own displacement from its resting box, in px — what makes
31
- * the thing under the cursor BE the thing you picked up.
30
+ * Where a pointer-carried card sits on screen, in VIEWPORT coordinates — what
31
+ * makes the thing under the cursor BE the thing you picked up.
32
32
  *
33
- * WHY THIS EXISTS AT ALL. A `<DragDropOverlay>` is optional, and for a long
34
- * while a board without one dragged nothing: the sibling gap opened correctly,
35
- * the marker drew in the right place, and the row itself sat exactly where it
36
- * had always been. Every automated check passed, because every one of them
37
- * asserts against the ORDER a drop writes and the order was right — the defect
38
- * was that there was no visual connection between the pointer and the thing it
39
- * was moving, which is a fact about pixels and nothing but a browser can see
40
- * it. So following the pointer is now what the engine does by DEFAULT, and an
41
- * overlay is what a consumer adds when the card must escape its container
42
- * rather than what it adds to make the card move at all.
33
+ * A VIEWPORT POINT, NOT A DISPLACEMENT, AND THAT IS THE WHOLE FIX. This was an
34
+ * offset from the card's resting box for exactly as long as the ROW did the
35
+ * carrying, under an in-flow `translate` on a child of the measured element.
36
+ * Two things are wrong with carrying a card in flow and neither can be tuned
37
+ * away:
38
+ *
39
+ * IT CANNOT LEAVE. A descendant of a scroll container is clipped by it. A
40
+ * card carried past the edge of its own list is cut off at
41
+ * that edge, and the container cannot stop clipping it is
42
+ * the scroller, and a scrolling axis forces its cross axis
43
+ * to a non-`visible` value (see `recipe.ts`).
44
+ * IT INFLATES. A transformed in-flow element contributes to its
45
+ * ancestor's SCROLLABLE OVERFLOW REGION, so the held row
46
+ * grew the extent of the very container it was inside —
47
+ * measured 512 -> 607px on a straight 90px sideways drag,
48
+ * which is auto-scroll theft and then a runaway.
49
+ *
50
+ * Neither is about SIZE, so neither is fixed by shrinking the card: the growth
51
+ * is the card following the hand, and a held object has to follow the hand on
52
+ * BOTH axes or it slides out from under the cursor the moment the hand moves
53
+ * the other way. Measured: dropping the 2% lift scale took a 95.12px overhang
54
+ * to 90.00px, and 90px was the pointer's own sideways travel. So the card is
55
+ * carried by a `fixed` clone portalled to the body (`DragDrop.tsx#CarriedCard`)
56
+ * — out of the flow entirely, where there is no ancestor to clip it and no
57
+ * extent to inflate.
43
58
  *
44
59
  * `grab` is where inside the box the press landed, so the card tracks the point
45
- * that was actually pressed rather than snapping a corner to the cursor. The
46
- * rest box comes from the same snapshot the shift is computed from — re-taken
47
- * on scroll, resize and every auto-scroll frame — so the card stays under the
48
- * cursor while the list scrolls beneath it.
60
+ * that was actually pressed rather than snapping a corner to the cursor.
49
61
  *
50
62
  * Null in keyboard mode: there is no pointer to follow, and a keyboard drag
51
63
  * moves slot to slot with the marker saying where. That is not a fallback — it
52
- * is a different question with a different honest answer.
64
+ * is a different question with a different honest answer, and `gapRect` is it.
53
65
  */
54
- export declare function carriedOffset(layout: LayoutSnapshot | null, state: DragState): Point | null;
55
- /**
56
- * The carried item's follow offset as an inline style.
57
- *
58
- * A 2D `translate`, unlike `shiftStyle`'s axis-constrained one: the card is a
59
- * held object rather than a row sliding along a list, and constraining it to
60
- * the container's axis makes it slide off the cursor the moment the hand moves
61
- * the other way.
62
- */
63
- export declare function followStyle(offset: Point | null): {
64
- translate: string;
65
- };
66
+ export declare function carriedPoint(state: DragState): Point | null;
66
67
  /**
67
68
  * Everything one container needs to render the shift, or null when no drag is
68
69
  * in flight and nothing should move.
69
70
  *
70
- * WHETHER THE HOME SLOT CLOSES ASKS ONE QUESTION: has the card actually left
71
- * it? Two different things can carry it away a mounted `<DragDropOverlay>`
72
- * (`lifted`), or the card following the pointer under its own transform
73
- * (`carriedOffset`) and either one empties the slot, so either one closes it.
74
- * The reason this is not cosmetic runs the other way too: a KEYBOARD drag with
75
- * no overlay has nothing carrying the card, so the card is still sitting in its
76
- * own slot, and closing it there would slide a neighbour underneath it.
71
+ * THE HOME SLOT CLOSES WHENEVER A DRAG IS LIVE, with no condition on it, and
72
+ * that is a consequence of there being ONE carry mechanism rather than a
73
+ * simplification of two. There used to be a `lifted` argument here, because a
74
+ * portalled clone and an in-flow `translate` were different answers to "is the
75
+ * card still in its slot" and a keyboard drag with no clone was a third. Every
76
+ * drag now lifts the card out into a portalled clone pointer and keyboard
77
+ * alike — so the slot is empty every time, and a caller cannot get this wrong
78
+ * by forgetting to say so.
77
79
  */
78
- export declare function containerShift(layout: LayoutSnapshot | null, state: DragState, container: ContainerId, lifted: boolean): ContainerShift | null;
80
+ export declare function containerShift(layout: LayoutSnapshot | null, state: DragState, container: ContainerId): ContainerShift | null;
79
81
  /** A rect in viewport coordinates. */
80
82
  export interface GapRect {
81
83
  top: number;
@@ -93,7 +95,7 @@ export interface GapRect {
93
95
  * (`autoscroll.ts#keepKeyboardTargetVisible`), which is the only thing that
94
96
  * moves these boxes during a keyboard drag.
95
97
  */
96
- export declare function gapRect(layout: LayoutSnapshot | null, state: DragState, lifted: boolean): GapRect | null;
98
+ export declare function gapRect(layout: LayoutSnapshot | null, state: DragState): GapRect | null;
97
99
  /**
98
100
  * The shift as an inline style.
99
101
  *
@@ -28,6 +28,11 @@ export interface KanbanBoardProps<T> extends Omit<DragSessionCallbacks, "onDragE
28
28
  * Worth overriding when the resting card is dense: the clone is moving, often
29
29
  * under a cursor, and the two or three fields that identify the record are
30
30
  * the only ones anybody reads off it.
31
+ *
32
+ * It changes what the carried card SHOWS and nothing else. Whether a card is
33
+ * carried, and how, is not a board's decision — `DragDrop` lifts every card
34
+ * into a portalled clone, and a board that omitted the piece that did the
35
+ * carrying used to get cards that could not leave their own lane.
31
36
  */
32
37
  renderDragging?: (item: T) => ReactNode;
33
38
  onMove: (move: KanbanMove) => void;
@@ -12,6 +12,8 @@ export declare const kanban: import("tailwind-variants").TVReturnType<{
12
12
  laneLabel: string;
13
13
  laneHint: string;
14
14
  laneItems: string;
15
+ card: string[];
16
+ cardHandle: string;
15
17
  laneEmpty: string;
16
18
  laneRefusal: string;
17
19
  }, undefined, {
@@ -28,6 +30,8 @@ export declare const kanban: import("tailwind-variants").TVReturnType<{
28
30
  laneLabel: string;
29
31
  laneHint: string;
30
32
  laneItems: string;
33
+ card: string[];
34
+ cardHandle: string;
31
35
  laneEmpty: string;
32
36
  laneRefusal: string;
33
37
  }, import("tailwind-variants").TVReturnTypeLike<{
@@ -44,6 +48,8 @@ export declare const kanban: import("tailwind-variants").TVReturnType<{
44
48
  laneLabel: string;
45
49
  laneHint: string;
46
50
  laneItems: string;
51
+ card: string[];
52
+ cardHandle: string;
47
53
  laneEmpty: string;
48
54
  laneRefusal: string;
49
55
  }>>;
@@ -69,7 +69,7 @@ export type { Command, Edit } from "./lib/markdown/commands";
69
69
  export { toggleBold, toggleItalic, toggleCode, toggleStrike, toggleInline, setHeading, adjustHeading, headingLevel, toggleList, toggleTask, indentLines, outdentLines, toggleQuote, toggleCodeBlock, fenceAround, insertRule, insertImage, insertLink, insertTable, insertRow, insertColumn, deleteRow, deleteColumn, deleteTable, alignColumn, tableAround, cellsOf, cellAt, tableTab, smartEnter, smartTab, smartShiftTab, } from "./lib/markdown/commands";
70
70
  export { tokenize, listLanguages, resolveLanguage, defineGrammar, registerGrammar, checkCoverage, type Token, type TokenType, type Grammar, type Rule, } from "./lib/syntax";
71
71
  export { parseMarkdown, MarkdownNodes, sanitizeHref, type MdNode, type MdInline, type MdCodeRenderer, } from "./lib/syntax/markdown";
72
- export { DragDrop, DragDropContainer, DragDropItem, DragDropHandle, DragDropOverlay, type DragDropProps, type DragDropContainerProps, type DragDropItemProps, type DragDropHandleProps, type DragDropOverlayProps, } from "./components/DragDrop";
72
+ export { DragDrop, DragDropContainer, DragDropItem, DragDropHandle, type DragDropProps, type DragDropContainerProps, type DragDropItemProps, type DragDropHandleProps, } from "./components/DragDrop";
73
73
  export { KanbanBoard, type KanbanBoardProps, type KanbanLane, type KanbanMove, type KanbanRefusal, } from "./components/kanban/KanbanBoard";
74
74
  export { DEFAULT_DRAG_STRINGS, DRAG_INSTRUCTIONS_ID, DragInstructions, DragLiveRegion, DragSession, DragSessionProvider, applyMove, attachAutoScroll, attachKeyboardSensor, attachPointerSensor, attachSessionWindowListeners, isNoOp, resolveTarget, sameTarget, scrollVelocity, useCreateDragSession, useDragAnnouncements, useDragSession, useDragState, useDraggable, useDropContainer, type ContainerId, type DragAxis, type DragCancelEvent, type DragEndEvent, type DragId, type DragMode, type DragPhase, type DragSessionCallbacks, type DragStartEvent, type DragState, type AutoScrollOptions, type DragAnnouncementContext, type DragAnnouncementOptions, type DragAnnouncements, type DragInstructionsProps, type DragLiveRegionProps, type DragStrings, type DropTarget, type KeyboardSensorOptions, type PointerActivation, } from "./lib/dnd";
75
75
  export type { MessageRole, MessagePart, MessagePartType, TextPart, CodePart, ReasoningPart, ToolPart, ToolStatus, FilePart, ComponentPart, ChatFile, ChatMessage, RenderContext, PartRenderer, PartRenderers, ChatComponentRenderer, ChatComponents, } from "./components/chat/types";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danxbot/ui",
3
- "version": "2.5.0",
3
+ "version": "2.7.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",
@@ -78,7 +78,7 @@
78
78
  "audit:arrows": "node scripts/audit-arrows.mjs",
79
79
  "audit:motion": "node scripts/audit-motion.mjs",
80
80
  "audit:responsive": "node scripts/audit-responsive.mjs",
81
- "audit:dnd": "node scripts/audit-dnd.mjs && node scripts/probe-dnd-sensors.mjs && node scripts/probe-dnd-a11y.mjs && node scripts/probe-drag-follow.mjs && node scripts/probe-drag-overflow.mjs && node scripts/probe-node-canvas.mjs",
81
+ "audit:dnd": "node scripts/audit-dnd.mjs && node scripts/probe-dnd-sensors.mjs && node scripts/probe-dnd-a11y.mjs && node scripts/probe-drag-follow.mjs && node scripts/probe-drag-overflow.mjs && node scripts/probe-node-canvas.mjs && node scripts/probe-kanban.mjs",
82
82
  "audit:axtree": "node scripts/audit-axtree.mjs",
83
83
  "audit:mutations": "node scripts/audit-mutations.mjs",
84
84
  "audit:palette": "node scripts/audit-palette.mjs",