@danxbot/ui 1.0.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/LICENSE +21 -0
- package/README.md +126 -0
- package/dist/fonts/bricolage-grotesque-0.woff2 +0 -0
- package/dist/fonts/bricolage-grotesque-1.woff2 +0 -0
- package/dist/fonts/bricolage-grotesque-2.woff2 +0 -0
- package/dist/fonts/figtree-0.woff2 +0 -0
- package/dist/fonts/figtree-1.woff2 +0 -0
- package/dist/fonts/figtree-2.woff2 +0 -0
- package/dist/fonts/figtree-3.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-0.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-1.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-10.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-11.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-2.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-3.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-4.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-5.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-6.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-7.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-8.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-9.woff2 +0 -0
- package/dist/fonts.css +187 -0
- package/dist/index.js +42425 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +190 -0
- package/dist/types/components/Accordion.d.ts +15 -0
- package/dist/types/components/AppShell.d.ts +58 -0
- package/dist/types/components/Avatar.d.ts +154 -0
- package/dist/types/components/Badge.d.ts +73 -0
- package/dist/types/components/Button.d.ts +103 -0
- package/dist/types/components/Card.d.ts +193 -0
- package/dist/types/components/Choice.d.ts +112 -0
- package/dist/types/components/CodeEditor.d.ts +86 -0
- package/dist/types/components/Combobox.d.ts +37 -0
- package/dist/types/components/CommandPalette.d.ts +33 -0
- package/dist/types/components/DatePicker.d.ts +20 -0
- package/dist/types/components/Dialog.d.ts +117 -0
- package/dist/types/components/DragDrop.d.ts +60 -0
- package/dist/types/components/ErrorBoundary.d.ts +16 -0
- package/dist/types/components/Field.d.ts +37 -0
- package/dist/types/components/FileUpload.d.ts +22 -0
- package/dist/types/components/Icon.d.ts +40 -0
- package/dist/types/components/Input.d.ts +120 -0
- package/dist/types/components/Loading.d.ts +83 -0
- package/dist/types/components/MarkdownEditor.d.ts +24 -0
- package/dist/types/components/Menu.d.ts +57 -0
- package/dist/types/components/Navigation.d.ts +46 -0
- package/dist/types/components/NumberInput.d.ts +88 -0
- package/dist/types/components/OTPInput.d.ts +11 -0
- package/dist/types/components/Panel.d.ts +94 -0
- package/dist/types/components/Popover.d.ts +64 -0
- package/dist/types/components/Progress.d.ts +178 -0
- package/dist/types/components/Select.d.ts +53 -0
- package/dist/types/components/Slider.d.ts +203 -0
- package/dist/types/components/Spinner.d.ts +29 -0
- package/dist/types/components/Stat.d.ts +98 -0
- package/dist/types/components/StatusSelect.d.ts +23 -0
- package/dist/types/components/Surface.d.ts +110 -0
- package/dist/types/components/Table.d.ts +46 -0
- package/dist/types/components/Tabs.d.ts +84 -0
- package/dist/types/components/ThemeMenu.d.ts +4 -0
- package/dist/types/components/Toast.d.ts +46 -0
- package/dist/types/components/Toggle.d.ts +65 -0
- package/dist/types/components/Tree.d.ts +20 -0
- package/dist/types/components/calendar/CalendarMonth.d.ts +33 -0
- package/dist/types/components/calendar/CalendarTimeGrid.d.ts +75 -0
- package/dist/types/components/calendar/EventActions.d.ts +17 -0
- package/dist/types/components/calendar/format.d.ts +43 -0
- package/dist/types/components/calendar/index.d.ts +9 -0
- package/dist/types/components/calendar/palette.d.ts +17 -0
- package/dist/types/components/calendar/use-calendar-drag.d.ts +54 -0
- package/dist/types/components/calendar/use-event-keyboard.d.ts +24 -0
- package/dist/types/components/calendar/use-grid-navigation.d.ts +47 -0
- package/dist/types/components/calendar/use-now.d.ts +20 -0
- package/dist/types/components/chat/Attachment.d.ts +49 -0
- package/dist/types/components/chat/Chat.d.ts +60 -0
- package/dist/types/components/chat/Composer.d.ts +29 -0
- package/dist/types/components/chat/ContextMeter.d.ts +55 -0
- package/dist/types/components/chat/EffortControl.d.ts +23 -0
- package/dist/types/components/chat/Markdown.d.ts +22 -0
- package/dist/types/components/chat/Message.d.ts +59 -0
- package/dist/types/components/chat/MessageScroller.d.ts +13 -0
- package/dist/types/components/chat/ModelSelector.d.ts +44 -0
- package/dist/types/components/chat/types.d.ts +155 -0
- package/dist/types/components/code-editor/context.d.ts +32 -0
- package/dist/types/components/code-editor/editing.d.ts +39 -0
- package/dist/types/components/code-editor/highlight.d.ts +20 -0
- package/dist/types/components/code-editor/recipe.d.ts +109 -0
- package/dist/types/components/code-editor/state.d.ts +14 -0
- package/dist/types/components/drag-drop/context.d.ts +45 -0
- package/dist/types/components/drag-drop/recipe.d.ts +121 -0
- package/dist/types/components/drag-drop/shift.d.ts +66 -0
- package/dist/types/components/markdown/Affordances.d.ts +76 -0
- package/dist/types/components/rbac/AccountMenu.d.ts +8 -0
- package/dist/types/components/rbac/DevToolsPopover.d.ts +5 -0
- package/dist/types/components/rbac/ProfilePage.d.ts +1 -0
- package/dist/types/components/rbac/RBACProvider.d.ts +64 -0
- package/dist/types/components/rbac/RolePermissionMatrix.d.ts +6 -0
- package/dist/types/components/rbac/RolesPermissionsPage.d.ts +1 -0
- package/dist/types/components/rbac/index.d.ts +7 -0
- package/dist/types/components/rbac/types.d.ts +26 -0
- package/dist/types/components/roadmap/PhaseManager.d.ts +19 -0
- package/dist/types/components/roadmap/RoadmapItemCard.d.ts +45 -0
- package/dist/types/components/roadmap/RoadmapPage.d.ts +9 -0
- package/dist/types/components/roadmap/RoadmapSwimlaneBoard.d.ts +9 -0
- package/dist/types/components/roadmap/UseCaseCard.d.ts +14 -0
- package/dist/types/components/roadmap/UseCaseLedgerPage.d.ts +21 -0
- package/dist/types/components/roadmap/chip-tones.d.ts +2 -0
- package/dist/types/components/roadmap/derive.d.ts +12 -0
- package/dist/types/components/roadmap/index.d.ts +9 -0
- package/dist/types/components/roadmap/types.d.ts +54 -0
- package/dist/types/icons/data.d.ts +1318 -0
- package/dist/types/index.d.ts +97 -0
- package/dist/types/lib/calendar/band-packer.d.ts +53 -0
- package/dist/types/lib/calendar/drag.d.ts +125 -0
- package/dist/types/lib/calendar/index.d.ts +4 -0
- package/dist/types/lib/calendar/lane-packer.d.ts +88 -0
- package/dist/types/lib/calendar/segments.d.ts +91 -0
- package/dist/types/lib/calendar/types.d.ts +166 -0
- package/dist/types/lib/cn.d.ts +7 -0
- package/dist/types/lib/dnd/announce.d.ts +132 -0
- package/dist/types/lib/dnd/autoscroll.d.ts +88 -0
- package/dist/types/lib/dnd/geometry.d.ts +78 -0
- package/dist/types/lib/dnd/index.d.ts +16 -0
- package/dist/types/lib/dnd/sensors/gesture.d.ts +37 -0
- package/dist/types/lib/dnd/sensors/keyboard.d.ts +50 -0
- package/dist/types/lib/dnd/sensors/pointer.d.ts +59 -0
- package/dist/types/lib/dnd/session.d.ts +99 -0
- package/dist/types/lib/dnd/types.d.ts +162 -0
- package/dist/types/lib/dnd/use-drag.d.ts +56 -0
- package/dist/types/lib/icons.d.ts +40 -0
- package/dist/types/lib/markdown/caret-map.d.ts +48 -0
- package/dist/types/lib/markdown/caret.d.ts +6 -0
- package/dist/types/lib/markdown/commands.d.ts +170 -0
- package/dist/types/lib/markdown/convert.d.ts +82 -0
- package/dist/types/lib/markdown/dom.d.ts +67 -0
- package/dist/types/lib/markdown/edit.d.ts +16 -0
- package/dist/types/lib/markdown/history.d.ts +47 -0
- package/dist/types/lib/markdown/hotkeys.d.ts +39 -0
- package/dist/types/lib/markdown/input.d.ts +15 -0
- package/dist/types/lib/markdown/keys.d.ts +34 -0
- package/dist/types/lib/markdown/paste.d.ts +9 -0
- package/dist/types/lib/markdown/position.d.ts +43 -0
- package/dist/types/lib/markdown/project.d.ts +88 -0
- package/dist/types/lib/markdown/reconcile.d.ts +63 -0
- package/dist/types/lib/markdown/surface.d.ts +177 -0
- package/dist/types/lib/persist.d.ts +40 -0
- package/dist/types/lib/preferences.d.ts +80 -0
- package/dist/types/lib/sim/createSimStore.d.ts +18 -0
- package/dist/types/lib/sim/index.d.ts +5 -0
- package/dist/types/lib/sim/latency.d.ts +10 -0
- package/dist/types/lib/sim/registry.d.ts +14 -0
- package/dist/types/lib/sim/settings.d.ts +11 -0
- package/dist/types/lib/sim/types.d.ts +3 -0
- package/dist/types/lib/syntax/index.d.ts +16 -0
- package/dist/types/lib/syntax/languages/bash.d.ts +1 -0
- package/dist/types/lib/syntax/languages/css.d.ts +1 -0
- package/dist/types/lib/syntax/languages/html.d.ts +17 -0
- package/dist/types/lib/syntax/languages/index.d.ts +33 -0
- package/dist/types/lib/syntax/languages/javascript.d.ts +22 -0
- package/dist/types/lib/syntax/languages/json.d.ts +1 -0
- package/dist/types/lib/syntax/languages/mongodb.d.ts +1 -0
- package/dist/types/lib/syntax/languages/plain.d.ts +9 -0
- package/dist/types/lib/syntax/languages/sql.d.ts +4 -0
- package/dist/types/lib/syntax/languages/vue.d.ts +1 -0
- package/dist/types/lib/syntax/languages/yaml.d.ts +1 -0
- package/dist/types/lib/syntax/markdown/frames.d.ts +145 -0
- package/dist/types/lib/syntax/markdown/grammar.d.ts +1 -0
- package/dist/types/lib/syntax/markdown/index.d.ts +4 -0
- package/dist/types/lib/syntax/markdown/inline.d.ts +21 -0
- package/dist/types/lib/syntax/markdown/parse.d.ts +11 -0
- package/dist/types/lib/syntax/markdown/render.d.ts +19 -0
- package/dist/types/lib/syntax/markdown/spans.d.ts +84 -0
- package/dist/types/lib/syntax/markdown/types.d.ts +108 -0
- package/dist/types/lib/syntax/registry.d.ts +37 -0
- package/dist/types/lib/syntax/tokenize.d.ts +17 -0
- package/dist/types/lib/syntax/types.d.ts +119 -0
- package/dist/types/lib/time/index.d.ts +3 -0
- package/dist/types/lib/time/plain.d.ts +61 -0
- package/dist/types/lib/time/types.d.ts +87 -0
- package/dist/types/lib/time/zone.d.ts +97 -0
- package/dist/types/lib/use-media-query.d.ts +29 -0
- package/package.json +130 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import type { DragSession } from "./session";
|
|
2
|
+
import type { ContainerId, DragId } from "./types";
|
|
3
|
+
/** Everything a message may name. Assembled once per announcement. */
|
|
4
|
+
export interface DragAnnouncementContext {
|
|
5
|
+
id: DragId;
|
|
6
|
+
/** `labelOf(id)` if supplied, otherwise the id — which is at least speakable. */
|
|
7
|
+
label: string;
|
|
8
|
+
container: ContainerId;
|
|
9
|
+
containerLabel: string;
|
|
10
|
+
/** 1-based, as spoken. */
|
|
11
|
+
position: number;
|
|
12
|
+
/**
|
|
13
|
+
* The list length WITH the carried item counted in it, so `position` is never
|
|
14
|
+
* "4 of 3". The session's own indices exclude the carried item — see the
|
|
15
|
+
* `DropTarget.index` contract — and reporting that raw count would tell the
|
|
16
|
+
* user a list is one shorter than the one they are looking at.
|
|
17
|
+
*/
|
|
18
|
+
total: number;
|
|
19
|
+
}
|
|
20
|
+
export interface DragStrings {
|
|
21
|
+
/** Rendered by `<DragInstructions>`; referenced by each handle's `aria-describedby`. */
|
|
22
|
+
instructions: string;
|
|
23
|
+
picked: (c: DragAnnouncementContext) => string;
|
|
24
|
+
moved: (c: DragAnnouncementContext) => string;
|
|
25
|
+
dropped: (c: DragAnnouncementContext) => string;
|
|
26
|
+
/** Describes the item's ORIGINAL position — cancel is a restore, not a move. */
|
|
27
|
+
cancelled: (c: DragAnnouncementContext) => string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Exported as data so a consumer can read one message, override one message, or
|
|
31
|
+
* assert on the set — a grammar hidden inside the component that renders it can
|
|
32
|
+
* only be checked by rendering it.
|
|
33
|
+
*/
|
|
34
|
+
export declare const DEFAULT_DRAG_STRINGS: DragStrings;
|
|
35
|
+
export interface DragAnnouncementOptions {
|
|
36
|
+
/** Human name for an item. Falls back to the id. */
|
|
37
|
+
labelOf?: (id: DragId) => string;
|
|
38
|
+
/** Human name for a container. Falls back to the id. */
|
|
39
|
+
containerLabelOf?: (id: ContainerId) => string;
|
|
40
|
+
/** Override any subset of the grammar — localisation, or a domain noun. */
|
|
41
|
+
strings?: Partial<DragStrings>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* One id for the whole page, deliberately not `useId()`.
|
|
45
|
+
*
|
|
46
|
+
* `<DragInstructions>` takes no required props and the hook hands the id to
|
|
47
|
+
* every handle, so the two can only agree on a CONSTANT — a generated id would
|
|
48
|
+
* differ per hook instance and every `aria-describedby` would point at nothing,
|
|
49
|
+
* which reads as "no instructions" and is invisible to every automated check.
|
|
50
|
+
* The cost: render `<DragInstructions>` once per page, not once per board.
|
|
51
|
+
*/
|
|
52
|
+
export declare const DRAG_INSTRUCTIONS_ID = "danxbot-dnd-instructions";
|
|
53
|
+
export interface DragAnnouncements {
|
|
54
|
+
/** The current live-region text. `""` until the first pickup. */
|
|
55
|
+
message: string;
|
|
56
|
+
/** Put this on every handle's `aria-describedby`. */
|
|
57
|
+
instructionsId: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Subscribe to the session and turn it into speech.
|
|
61
|
+
*
|
|
62
|
+
* AN OBSERVER, NOT A STATE SUBSCRIPTION. The messages are derived from
|
|
63
|
+
* TRANSITIONS, not from state, and the two that matter most are indistinguishable
|
|
64
|
+
* in state: a drop and a cancel both end at the same idle value, so a subscriber
|
|
65
|
+
* sees one identical transition for two endings that need opposite messages — a
|
|
66
|
+
* drop reports where the item LANDED, a cancel where it went BACK to.
|
|
67
|
+
*
|
|
68
|
+
* `session.addObserver` exists for exactly this. It was added after the first
|
|
69
|
+
* version of this file inferred the ending from whichever DOM event was
|
|
70
|
+
* mid-dispatch, because the session's callbacks were a single slot the board
|
|
71
|
+
* already owned. That worked, and was ninety lines, and was defeated once by the
|
|
72
|
+
* microtask checkpoint the HTML spec runs BETWEEN listeners of the same event —
|
|
73
|
+
* so every cancel announced itself as a drop, in a real browser only. Nothing
|
|
74
|
+
* that reads the session should have to guess what the session just did.
|
|
75
|
+
*
|
|
76
|
+
* The context for a message is captured WHILE THE DRAG IS LIVE, never at the
|
|
77
|
+
* end. "Position 3 of 7" needs the carried item excluded from its own total, and
|
|
78
|
+
* by the time the drag has ended the session no longer knows which item that
|
|
79
|
+
* was — the number would quietly gain one.
|
|
80
|
+
*/
|
|
81
|
+
export declare function useDragAnnouncements(session: DragSession, options?: DragAnnouncementOptions): DragAnnouncements;
|
|
82
|
+
export type DragLiveRegionProps = {
|
|
83
|
+
session: DragSession;
|
|
84
|
+
} & DragAnnouncementOptions;
|
|
85
|
+
/**
|
|
86
|
+
* The live region. Render it ONCE, unconditionally, for the whole board.
|
|
87
|
+
*
|
|
88
|
+
* UNCONDITIONALLY IS THE LOAD-BEARING WORD. A live region that is inserted and
|
|
89
|
+
* populated in the same frame — `{dragging && <DragLiveRegion/>}` — frequently
|
|
90
|
+
* announces nothing at all: the accessibility tree has to observe the region
|
|
91
|
+
* BEFORE its content changes to know a change happened. It renders empty here
|
|
92
|
+
* and stays mounted, which is also why the message lives in state rather than
|
|
93
|
+
* being derived from `session.getState()` during render.
|
|
94
|
+
*
|
|
95
|
+
* ASSERTIVE, NOT POLITE. Polite queues behind whatever is currently being
|
|
96
|
+
* spoken, and a drag generates positions faster than speech consumes them — so
|
|
97
|
+
* the user hears "position 2 of 7" while the card sits at 6, which is a wrong
|
|
98
|
+
* answer rather than a late one. Assertive interrupts, so the newest position
|
|
99
|
+
* always wins. The usual argument against it — that it talks over the user —
|
|
100
|
+
* does not apply to a gesture that is modal by construction: nothing else is
|
|
101
|
+
* happening, and the drag's own output is the only thing being interrupted.
|
|
102
|
+
*
|
|
103
|
+
* `sr-only` — NOT `display:none`, NOT `visibility:hidden`, NOT `hidden`. All
|
|
104
|
+
* three remove the element from the accessibility tree entirely, and a live
|
|
105
|
+
* region outside the accessibility tree is silent while looking exactly right
|
|
106
|
+
* in the markup.
|
|
107
|
+
*/
|
|
108
|
+
export declare function DragLiveRegion({ session, ...options }: DragLiveRegionProps): import("react").JSX.Element;
|
|
109
|
+
export interface DragInstructionsProps {
|
|
110
|
+
strings?: Partial<DragStrings>;
|
|
111
|
+
/**
|
|
112
|
+
* The element id each handle's `aria-describedby` points at.
|
|
113
|
+
*
|
|
114
|
+
* Defaults to the module constant, which is what makes a prop-less
|
|
115
|
+
* `<DragInstructions>` and `useDragAnnouncements` agree without wiring. A
|
|
116
|
+
* component layer that generates its own id with `useId()` — so that two
|
|
117
|
+
* boards on one page do not emit a duplicate id — passes it here. Without
|
|
118
|
+
* this prop that layer has to re-implement the paragraph to change one
|
|
119
|
+
* attribute, which is how the instruction text ends up existing twice and
|
|
120
|
+
* drifting.
|
|
121
|
+
*/
|
|
122
|
+
id?: string;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* The instruction text every handle points at with `aria-describedby`.
|
|
126
|
+
*
|
|
127
|
+
* A keyboard drag is unusable without it: nothing about a focused handle says
|
|
128
|
+
* that Space starts a mode, and a user who does not know that never reaches any
|
|
129
|
+
* of the rest of this file. Visually hidden because the same information is
|
|
130
|
+
* carried for sighted users by the cursor and the moving card.
|
|
131
|
+
*/
|
|
132
|
+
export declare function DragInstructions({ strings, id }?: DragInstructionsProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { DragSession } from "./session";
|
|
2
|
+
import type { Point } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Edge auto-scroll: while a card is being carried, a pointer near the edge of
|
|
5
|
+
* the nearest scrollable ancestor scrolls it.
|
|
6
|
+
*
|
|
7
|
+
* WHY IT IS NOT OPTIONAL. Without it a list is only reorderable within one
|
|
8
|
+
* screenful. The target you want is off-screen, the gesture is already in
|
|
9
|
+
* flight, and there is no way to scroll with the hand that is holding the card
|
|
10
|
+
* — so the drag has to be abandoned, the list scrolled, and the drag restarted
|
|
11
|
+
* from a position that may itself now be off-screen.
|
|
12
|
+
*
|
|
13
|
+
* THREE THINGS THAT MAKE IT WORK RATHER THAN MERELY EXIST:
|
|
14
|
+
*
|
|
15
|
+
* 1. SPEED RAMPS with proximity. A single speed is unusable at both ends: fast
|
|
16
|
+
* enough to cross a long column overshoots the moment you approach the
|
|
17
|
+
* edge, slow enough to be controllable never gets anywhere. The ramp is
|
|
18
|
+
* quadratic, so the outer half of the zone crawls and the last few pixels
|
|
19
|
+
* are quick.
|
|
20
|
+
* 2. IT RE-MEASURES. Every rect in the snapshot moves when the container
|
|
21
|
+
* scrolls. Without a remeasure the insertion point keeps pointing at where
|
|
22
|
+
* the items USED to be, so the marker sits still while the list slides past
|
|
23
|
+
* it and the card lands somewhere the user never indicated.
|
|
24
|
+
* 3. IT RE-RESOLVES THE TARGET. Re-measuring alone updates the boxes but not
|
|
25
|
+
* the answer: the pointer has not moved, so nothing recomputes `over`, and
|
|
26
|
+
* the marker stays frozen on the old index against fresh rects. Feeding the
|
|
27
|
+
* unchanged point back through `moveTo` is what makes the insertion point
|
|
28
|
+
* track the content moving beneath a stationary finger.
|
|
29
|
+
*
|
|
30
|
+
* The window `scroll` listener in `sensors/pointer.ts` also remeasures, and is
|
|
31
|
+
* NOT a substitute: scroll events are coalesced and delivered after the frame
|
|
32
|
+
* has been composited, so the hit-test for the frame we just scrolled would
|
|
33
|
+
* still read the pre-scroll snapshot. This loop does it inline, before the next
|
|
34
|
+
* frame is resolved.
|
|
35
|
+
*/
|
|
36
|
+
export interface AutoScrollOptions {
|
|
37
|
+
/** Distance from an edge, in px, at which scrolling begins. */
|
|
38
|
+
threshold?: number;
|
|
39
|
+
/** Speed in px/second at the very edge, at full motion. */
|
|
40
|
+
maxSpeed?: number;
|
|
41
|
+
/** Speed in px/second at the very edge under reduced motion. See D-18. */
|
|
42
|
+
reducedMaxSpeed?: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Speed at a given distance from the edge. Exported because it is the whole
|
|
46
|
+
* behaviour and it is the one part testable without a browser.
|
|
47
|
+
*
|
|
48
|
+
* Zero outside the zone, `maxSpeed` at the edge, quadratic in between.
|
|
49
|
+
*/
|
|
50
|
+
export declare function scrollVelocity(distanceFromEdge: number, threshold: number, maxSpeed: number): number;
|
|
51
|
+
/**
|
|
52
|
+
* Start auto-scrolling for the lifetime of every drag on this session.
|
|
53
|
+
* Returns the teardown.
|
|
54
|
+
*
|
|
55
|
+
* Framework-free on purpose, like the rest of the core — a React consumer wraps
|
|
56
|
+
* it in one `useEffect`, and the tests do not need a renderer to drive it.
|
|
57
|
+
*/
|
|
58
|
+
/**
|
|
59
|
+
* What the loop needs from whoever is dragging.
|
|
60
|
+
*
|
|
61
|
+
* EXTRACTED SO THE CALENDAR CAN USE IT UNCHANGED. Every hard-won detail below —
|
|
62
|
+
* the carried sub-pixel remainder, the clamped frame delta, the per-scroller
|
|
63
|
+
* reset, the reduced-motion cap — is about SCROLLING, not about lists, and a
|
|
64
|
+
* second copy of it in the calendar would be a second copy of the one thing
|
|
65
|
+
* whose failures are invisible (a ramp that silently loses its outer half is
|
|
66
|
+
* not something anyone notices; it just feels bad).
|
|
67
|
+
*/
|
|
68
|
+
export interface AutoScrollDriver {
|
|
69
|
+
/** The pointer, or null when the gesture has no pointer (a keyboard drag). */
|
|
70
|
+
getPoint: () => Point | null;
|
|
71
|
+
/**
|
|
72
|
+
* The content moved under a pointer that did not.
|
|
73
|
+
*
|
|
74
|
+
* RE-FEEDING THE POINT IS THE WHOLE REASON THIS CALLBACK EXISTS. Remeasuring
|
|
75
|
+
* alone updates the boxes and not the ANSWER: the pointer has not moved, so
|
|
76
|
+
* nothing recomputes what it is over, and the drag freezes mid-scroll.
|
|
77
|
+
* FullCalendar solves the same problem by re-emitting a synthetic
|
|
78
|
+
* `pointermove` on scroll — the same fix arrived at from the other side.
|
|
79
|
+
*/
|
|
80
|
+
onScrolled: (point: Point) => void;
|
|
81
|
+
}
|
|
82
|
+
/** The loop, driven by anything that can answer those two questions. */
|
|
83
|
+
export declare function attachEdgeAutoScroll(driver: AutoScrollDriver, options?: AutoScrollOptions): () => void;
|
|
84
|
+
/**
|
|
85
|
+
* The list engine's adapter: drive the edge loop from a `DragSession`, and add
|
|
86
|
+
* the keyboard-only behaviour the pointer ramp cannot reach.
|
|
87
|
+
*/
|
|
88
|
+
export declare function attachAutoScroll(session: DragSession, options?: AutoScrollOptions): () => void;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { ContainerRect, ContainerRegistration, DragId, DropTarget, ItemRect, ItemRegistration, LayoutSnapshot, Point } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Measuring and hit-testing. Pure functions over a snapshot — no DOM reads
|
|
4
|
+
* except in `measure`, and no state at all, so every rule here is testable
|
|
5
|
+
* against hand-written rectangles rather than a browser.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Take every box at once.
|
|
9
|
+
*
|
|
10
|
+
* Items are emitted in container-then-index order so `resolveTarget` can walk
|
|
11
|
+
* them without re-sorting on every move. Registration order is whatever React
|
|
12
|
+
* mounted in, which is not the reading order once a list re-renders.
|
|
13
|
+
*/
|
|
14
|
+
export declare function measure(items: Iterable<ItemRegistration>, containers: Iterable<ContainerRegistration>): LayoutSnapshot;
|
|
15
|
+
/**
|
|
16
|
+
* The container under the pointer.
|
|
17
|
+
*
|
|
18
|
+
* SMALLEST AREA WINS, because containers nest: a board is a horizontal
|
|
19
|
+
* container of columns, and each column is a vertical container of cards. The
|
|
20
|
+
* pointer is inside both at all times, and the answer that is useful is always
|
|
21
|
+
* the innermost one.
|
|
22
|
+
*/
|
|
23
|
+
export declare function containerAt(snapshot: LayoutSnapshot, point: Point): ContainerRect | null;
|
|
24
|
+
/** A container's items in reading order, excluding the one being carried. */
|
|
25
|
+
export declare function remainingItems(snapshot: LayoutSnapshot, container: string, dragged: DragId | null): ItemRect[];
|
|
26
|
+
/**
|
|
27
|
+
* Insertion index for a point within one container.
|
|
28
|
+
*
|
|
29
|
+
* THE MIDPOINT RULE: insert before the first remaining item whose centre lies
|
|
30
|
+
* beyond the pointer on the container's axis; after all of them otherwise. This
|
|
31
|
+
* is the rule the dashboard's implementation already uses and it is the right
|
|
32
|
+
* one for lists — the insertion point tracks the cursor rather than the item's
|
|
33
|
+
* leading edge, so a card released halfway over a neighbour lands on the side
|
|
34
|
+
* the user is actually pointing at.
|
|
35
|
+
*
|
|
36
|
+
* The returned index counts the list WITHOUT the dragged item, which is what
|
|
37
|
+
* makes same-container and cross-container drops identical arithmetic. See the
|
|
38
|
+
* header of `types.ts`.
|
|
39
|
+
*/
|
|
40
|
+
export declare function indexAt(snapshot: LayoutSnapshot, container: ContainerRect, point: Point, dragged: DragId | null): number;
|
|
41
|
+
/**
|
|
42
|
+
* Where the dragged item would land if released at `point`.
|
|
43
|
+
*
|
|
44
|
+
* Returns null when the pointer is over no container at all. The session keeps
|
|
45
|
+
* the PREVIOUS target in that case rather than clearing it — dragging a card
|
|
46
|
+
* briefly outside the board should not make the insertion marker vanish, and a
|
|
47
|
+
* release outside every container should still land where the marker last
|
|
48
|
+
* showed. That is the behaviour every board people already use has, and the
|
|
49
|
+
* alternative reads as the drag having silently failed.
|
|
50
|
+
*/
|
|
51
|
+
export declare function resolveTarget(snapshot: LayoutSnapshot, point: Point, dragged: DragId | null): DropTarget | null;
|
|
52
|
+
/** Value equality — targets are recreated on every move, so `===` is useless. */
|
|
53
|
+
export declare function sameTarget(a: DropTarget | null, b: DropTarget | null): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Would releasing at `to` leave the item exactly where it started?
|
|
56
|
+
*
|
|
57
|
+
* Worth stating rather than inlining, because the two indices are counted
|
|
58
|
+
* against DIFFERENT lists: `from.index` is the item's position with itself
|
|
59
|
+
* present, `to.index` an insertion point with itself removed. They coincide at
|
|
60
|
+
* exactly one value. For `[A, B, C, D]` carrying `C` (`from.index` 2), the
|
|
61
|
+
* remaining list is `[A, B, D]` and inserting at 2 rebuilds `[A, B, C, D]` —
|
|
62
|
+
* so equality of the two numbers IS the no-op, and every other pair moves
|
|
63
|
+
* something.
|
|
64
|
+
*
|
|
65
|
+
* A consumer that skips this writes on every release, including the ones that
|
|
66
|
+
* change nothing. That is not free: the dashboard's board reordered by writing
|
|
67
|
+
* a priority decimal, so a no-op release still cost a request, a re-render and
|
|
68
|
+
* a row in the audit log.
|
|
69
|
+
*/
|
|
70
|
+
export declare function isNoOp(from: DropTarget, to: DropTarget): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Convert a `DropTarget` into the array operation a consumer performs.
|
|
73
|
+
*
|
|
74
|
+
* Exported because every consumer needs it and each one getting it subtly wrong
|
|
75
|
+
* is the entire off-by-one bug class this module exists to remove. Returns a
|
|
76
|
+
* NEW array; the input is untouched.
|
|
77
|
+
*/
|
|
78
|
+
export declare function applyMove<T>(list: readonly T[], fromIndex: number, toIndex: number): T[];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drag-and-drop engine. Framework-agnostic core plus a React binding.
|
|
3
|
+
*
|
|
4
|
+
* Exported as VALUES from one place — never `import "./x"` for a side effect.
|
|
5
|
+
* `sideEffects: ["*.css"]` tells every bundler such an import is safe to
|
|
6
|
+
* delete, and esbuild does; that is exactly how this project once shipped an
|
|
7
|
+
* empty icon registry (CAV-11).
|
|
8
|
+
*/
|
|
9
|
+
export type { ContainerId, ContainerRect, ContainerRegistration, DragAxis, DragCancelEvent, DragEndEvent, DragId, DragMode, DragPhase, DragSessionCallbacks, DragStartEvent, DragState, DropTarget, ItemRect, ItemRegistration, LayoutSnapshot, Point, } from "./types";
|
|
10
|
+
export { applyMove, containerAt, indexAt, isNoOp, measure, remainingItems, resolveTarget, sameTarget, } from "./geometry";
|
|
11
|
+
export { DragSession, type StartArgs } from "./session";
|
|
12
|
+
export { attachPointerSensor, attachSessionWindowListeners, type PointerActivation, type PointerSensorOptions, } from "./sensors/pointer";
|
|
13
|
+
export { attachKeyboardSensor, type KeyboardSensorOptions, } from "./sensors/keyboard";
|
|
14
|
+
export { attachAutoScroll, scrollVelocity, type AutoScrollOptions, } from "./autoscroll";
|
|
15
|
+
export { DragSessionProvider, useCreateDragSession, useDragSession, useDragState, useDraggable, useDropContainer, type UseDraggableOptions, type UseDraggableResult, type UseDropContainerOptions, type UseDropContainerResult, } from "./use-drag";
|
|
16
|
+
export { DEFAULT_DRAG_STRINGS, DRAG_INSTRUCTIONS_ID, DragInstructions, DragLiveRegion, useDragAnnouncements, type DragAnnouncementContext, type DragAnnouncementOptions, type DragAnnouncements, type DragInstructionsProps, type DragLiveRegionProps, type DragStrings, } from "./announce";
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Point } from "../types";
|
|
2
|
+
export interface PointerActivation {
|
|
3
|
+
/** Mouse and pen: travel in px before the drag starts. */
|
|
4
|
+
distance?: number;
|
|
5
|
+
/** Touch: press duration in ms before the drag starts. */
|
|
6
|
+
delay?: number;
|
|
7
|
+
/** Touch: travel in px that abandons the press as a scroll instead. */
|
|
8
|
+
tolerance?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare const ACTIVATION_DEFAULTS: Required<PointerActivation>;
|
|
11
|
+
export interface GestureHandlers {
|
|
12
|
+
/**
|
|
13
|
+
* The pointer went down. Return false to refuse the gesture outright — a
|
|
14
|
+
* disabled row, a click on a button inside the card.
|
|
15
|
+
*/
|
|
16
|
+
onPress?: (point: Point, event: PointerEvent) => boolean | void;
|
|
17
|
+
/** The activation constraint was satisfied. The drag is now live. */
|
|
18
|
+
onActivate: (point: Point) => void;
|
|
19
|
+
/** Only ever called between `onActivate` and one of the two enders. */
|
|
20
|
+
onMove: (point: Point) => void;
|
|
21
|
+
/** Released. `activated` distinguishes a drop from a plain click. */
|
|
22
|
+
onRelease: (point: Point, activated: boolean) => void;
|
|
23
|
+
/** The gesture was abandoned — a `pointercancel`, or a touch that scrolled. */
|
|
24
|
+
onCancel: () => void;
|
|
25
|
+
}
|
|
26
|
+
export interface GestureOptions {
|
|
27
|
+
activation?: PointerActivation;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Wire an element as a drag handle. Returns the teardown.
|
|
31
|
+
*
|
|
32
|
+
* The listeners live on the ELEMENT, not the document, and the element takes
|
|
33
|
+
* pointer capture at `pointerdown` — so every subsequent move and the release
|
|
34
|
+
* are delivered here even when the pointer leaves the element, which it does
|
|
35
|
+
* immediately and for the entire gesture.
|
|
36
|
+
*/
|
|
37
|
+
export declare function attachPointerGesture(element: HTMLElement, handlers: GestureHandlers, options?: GestureOptions): () => void;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { DragSession } from "../session";
|
|
2
|
+
import type { DragAxis, DragId } from "../types";
|
|
3
|
+
/**
|
|
4
|
+
* The keyboard sensor. Drives the SAME session the pointer does.
|
|
5
|
+
*
|
|
6
|
+
* WHY A SENSOR AND NOT A KEYBOARD IMPLEMENTATION. The usual shape is a pointer
|
|
7
|
+
* drag with keyboard "support" bolted on, which is two codebases computing the
|
|
8
|
+
* same answer — and the accessible one is the one nobody looks at, so it is the
|
|
9
|
+
* one that rots. Here the keyboard can only `start`, `moveIndex`,
|
|
10
|
+
* `moveContainer`, `commit` and `cancel`, exactly like the pointer, so the two
|
|
11
|
+
* cannot disagree about where a card lands. `dnd-sensors.test.ts` asserts they
|
|
12
|
+
* reach an identical target for the same intent.
|
|
13
|
+
*
|
|
14
|
+
* THE KEY MAP IS FIXED BY THE PROJECT CONTRACT, not by this file:
|
|
15
|
+
*
|
|
16
|
+
* Space / Enter pick up on a focused handle; drop when already carrying
|
|
17
|
+
* Escape cancel — handled by `attachSessionWindowListeners`, NOT here
|
|
18
|
+
* Along the axis step the insertion point inside the current container
|
|
19
|
+
* Across it move to the previous / next container
|
|
20
|
+
*
|
|
21
|
+
* "Along" and "across" swap with the container's axis: a vertical list steps
|
|
22
|
+
* with Up/Down and changes column with Left/Right; a horizontal one is the
|
|
23
|
+
* mirror. Hard-coding Up/Down as "within" makes a horizontal list unusable in
|
|
24
|
+
* the one input mode that has no alternative.
|
|
25
|
+
*
|
|
26
|
+
* NO `aria-grabbed`, NO `aria-dropeffect`. They are the attributes the name
|
|
27
|
+
* suggests and they were removed in ARIA 1.2 because assistive-technology
|
|
28
|
+
* support never arrived — an implementation using them announces nothing at
|
|
29
|
+
* all. Ordinary focus, an `aria-describedby` instruction and a live region are
|
|
30
|
+
* the working pattern; the live region is `announce.tsx`'s.
|
|
31
|
+
*/
|
|
32
|
+
export interface KeyboardSensorOptions {
|
|
33
|
+
id: DragId;
|
|
34
|
+
/**
|
|
35
|
+
* The reorder axis of the container this item currently lives in. Decides
|
|
36
|
+
* which arrow pair steps within the container and which moves between them.
|
|
37
|
+
*/
|
|
38
|
+
axis?: DragAxis;
|
|
39
|
+
/** Return false to refuse pickup — a disabled row. Mirrors the pointer sensor. */
|
|
40
|
+
canStart?: (e: KeyboardEvent) => boolean;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Wire an element as a keyboard drag handle. Returns the teardown.
|
|
44
|
+
*
|
|
45
|
+
* The element must be focusable and reachable — `tabIndex={0}` and
|
|
46
|
+
* `role="button"` — or none of this is ever delivered. A handle that is a
|
|
47
|
+
* `<span>` with a listener is invisible to the keyboard and to every screen
|
|
48
|
+
* reader, and looks completely correct on a desktop.
|
|
49
|
+
*/
|
|
50
|
+
export declare function attachKeyboardSensor(session: DragSession, element: HTMLElement, options: KeyboardSensorOptions): () => void;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { DragSession } from "../session";
|
|
2
|
+
import type { DragId } from "../types";
|
|
3
|
+
import { type PointerActivation } from "./gesture";
|
|
4
|
+
/**
|
|
5
|
+
* The pointer sensor. One listener set for mouse, touch and pen.
|
|
6
|
+
*
|
|
7
|
+
* ACTIVATION IS THE WHOLE PROBLEM. Starting the drag on `pointerdown` is what
|
|
8
|
+
* makes a drag list unusable: a tap becomes a drag, and on a phone a swipe that
|
|
9
|
+
* was meant to scroll the column picks a card up instead. So a pointer is held
|
|
10
|
+
* in `pending` until it proves itself, and the proof differs by input type:
|
|
11
|
+
*
|
|
12
|
+
* - MOUSE and PEN have a cursor, so intent is expressed by MOVING. A few
|
|
13
|
+
* pixels of travel is unambiguous and instant, and a click never reaches it.
|
|
14
|
+
* - TOUCH has no cursor and movement is how you scroll, so movement cannot be
|
|
15
|
+
* the signal. Intent is expressed by DWELLING — the long press — and any
|
|
16
|
+
* travel beyond a small tolerance before the timer fires means the finger
|
|
17
|
+
* was scrolling and the session must be abandoned.
|
|
18
|
+
*
|
|
19
|
+
* Getting that backwards is the single most common defect in drag lists, and it
|
|
20
|
+
* only shows up on a device the author was not testing on.
|
|
21
|
+
*
|
|
22
|
+
* AND THE DWELL IS ONLY HALF OF THE TOUCH ANSWER. The activation constraint
|
|
23
|
+
* decides whether WE start a drag; it says nothing about whether the BROWSER
|
|
24
|
+
* starts a scroll, and the browser decides that from `touch-action` alone,
|
|
25
|
+
* before any of this code runs. `touch-action: none` on the handle is therefore
|
|
26
|
+
* the tempting fix and it re-creates the failure it was meant to prevent, just
|
|
27
|
+
* on a smaller target: every swipe that happens to begin on the grip is eaten,
|
|
28
|
+
* the column does not move, and the list feels stuck at random.
|
|
29
|
+
*
|
|
30
|
+
* The handle is `touch-action: pan-y` instead (`pan-x` for a horizontal list),
|
|
31
|
+
* so the browser scrolls exactly as it would on any other element, and the
|
|
32
|
+
* drag takes the gesture back at the moment it activates by cancelling
|
|
33
|
+
* `touchmove` — see `beginTouchScrollGuard`. That ordering is what makes both
|
|
34
|
+
* true on the SAME element: a swipe scrolls, a press picks up.
|
|
35
|
+
*/
|
|
36
|
+
export type { PointerActivation } from "./gesture";
|
|
37
|
+
export interface PointerSensorOptions {
|
|
38
|
+
id: DragId;
|
|
39
|
+
activation?: PointerActivation;
|
|
40
|
+
/** Return false to refuse the gesture — a disabled row, or a click on a button inside the card. */
|
|
41
|
+
canStart?: (e: PointerEvent) => boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Wire an element as a drag handle for a list `DragSession`.
|
|
45
|
+
*
|
|
46
|
+
* A THIN ADAPTER, deliberately. The session's four verbs map one-to-one onto
|
|
47
|
+
* the gesture's callbacks, and the only real logic left is the `pending`
|
|
48
|
+
* start — the session is told about the press immediately so it can refuse the
|
|
49
|
+
* item, and only activated once the constraint is met.
|
|
50
|
+
*/
|
|
51
|
+
export declare function attachPointerSensor(session: DragSession, element: HTMLElement, options: PointerSensorOptions): () => void;
|
|
52
|
+
/**
|
|
53
|
+
* Esc, and the two things that move a box while a drag is in flight.
|
|
54
|
+
*
|
|
55
|
+
* Window-level because a keypress during a drag does not go to the handle — the
|
|
56
|
+
* handle has pointer capture, not focus — and because a scroll of an ancestor
|
|
57
|
+
* invalidates every rect in the snapshot at once.
|
|
58
|
+
*/
|
|
59
|
+
export declare function attachSessionWindowListeners(session: DragSession): () => void;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { ContainerRegistration, DragId, DragMode, DragSessionCallbacks, DragState, ItemRegistration, LayoutSnapshot, Point } from "./types";
|
|
2
|
+
export interface StartArgs {
|
|
3
|
+
id: DragId;
|
|
4
|
+
mode: DragMode;
|
|
5
|
+
/** Pointer position at pickup. Omitted for keyboard sessions. */
|
|
6
|
+
point?: Point;
|
|
7
|
+
/**
|
|
8
|
+
* `true` for a pointer that is down but has not passed its activation
|
|
9
|
+
* constraint yet. The session holds `pending` until the sensor calls
|
|
10
|
+
* `activate()` — see `DragPhase` in `types.ts` for why that gap exists.
|
|
11
|
+
*/
|
|
12
|
+
pending?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare class DragSession {
|
|
15
|
+
private state;
|
|
16
|
+
private listeners;
|
|
17
|
+
private items;
|
|
18
|
+
private containers;
|
|
19
|
+
private layout;
|
|
20
|
+
private callbacks;
|
|
21
|
+
private observers;
|
|
22
|
+
constructor(callbacks?: DragSessionCallbacks);
|
|
23
|
+
/**
|
|
24
|
+
* The OWNING consumer's callbacks — the one that renders the board and writes
|
|
25
|
+
* the reorder. Replaced rather than passed per-call because a React consumer
|
|
26
|
+
* re-creates its handlers on every render and the session must not be rebuilt;
|
|
27
|
+
* rebuilding it mid-gesture drops the drag.
|
|
28
|
+
*/
|
|
29
|
+
setCallbacks(callbacks: DragSessionCallbacks): void;
|
|
30
|
+
/**
|
|
31
|
+
* Register an ADDITIONAL listener. Returns its teardown.
|
|
32
|
+
*
|
|
33
|
+
* `setCallbacks` is a single slot owned by whoever renders the board, so a
|
|
34
|
+
* second interested party — the live-region announcer, an analytics hook, a
|
|
35
|
+
* test — could not be told anything without clobbering it. And `subscribe`
|
|
36
|
+
* is not a substitute: a drop and a cancel both end at the same idle state,
|
|
37
|
+
* so a state subscriber sees ONE identical transition for two outcomes that
|
|
38
|
+
* must be announced differently.
|
|
39
|
+
*
|
|
40
|
+
* That gap was not theoretical. The announcer worked around it by inferring
|
|
41
|
+
* the cause from whichever DOM event was mid-dispatch — about ninety lines of
|
|
42
|
+
* genuinely careful machinery, defeated once by the microtask checkpoint the
|
|
43
|
+
* HTML spec runs BETWEEN listeners of the same event, so that every cancel
|
|
44
|
+
* announced itself as a drop. Nothing that reads the session should have to
|
|
45
|
+
* guess what the session just did.
|
|
46
|
+
*/
|
|
47
|
+
addObserver(callbacks: DragSessionCallbacks): () => void;
|
|
48
|
+
/**
|
|
49
|
+
* Owner first, then observers, in registration order.
|
|
50
|
+
*
|
|
51
|
+
* The owner goes first because it is the one that mutates the list, and an
|
|
52
|
+
* observer that reads the consumer's state — an announcer reporting "3 of 7"
|
|
53
|
+
* — must see the world after the write, not before.
|
|
54
|
+
*/
|
|
55
|
+
private fan;
|
|
56
|
+
getState: () => DragState;
|
|
57
|
+
subscribe: (fn: () => void) => (() => void);
|
|
58
|
+
private emit;
|
|
59
|
+
registerItem(reg: ItemRegistration): () => void;
|
|
60
|
+
registerContainer(reg: ContainerRegistration): () => void;
|
|
61
|
+
/** Registered order, used by keyboard container stepping. */
|
|
62
|
+
containerIds(): string[];
|
|
63
|
+
/**
|
|
64
|
+
* Re-measure. Called at pickup, and by the sensors on scroll, resize and
|
|
65
|
+
* every auto-scroll frame — the three things that move a box while a drag is
|
|
66
|
+
* in flight without the drag having caused it.
|
|
67
|
+
*/
|
|
68
|
+
remeasure(): LayoutSnapshot;
|
|
69
|
+
getLayout(): LayoutSnapshot | null;
|
|
70
|
+
start(args: StartArgs): boolean;
|
|
71
|
+
/** Promote a `pending` pointer into a real drag once its constraint is met. */
|
|
72
|
+
activate(): void;
|
|
73
|
+
/** Pointer moved. Cheap when the target has not changed, which is most frames. */
|
|
74
|
+
moveTo(point: Point): void;
|
|
75
|
+
/**
|
|
76
|
+
* Step the insertion point within the current container. The keyboard's
|
|
77
|
+
* along-axis movement.
|
|
78
|
+
*
|
|
79
|
+
* Clamped rather than wrapping: wrapping from the bottom of a list to the top
|
|
80
|
+
* is indistinguishable from a missed keypress when you cannot see the list.
|
|
81
|
+
*/
|
|
82
|
+
moveIndex(delta: number): void;
|
|
83
|
+
/**
|
|
84
|
+
* Move to the previous or next container. The keyboard's cross-axis movement.
|
|
85
|
+
*
|
|
86
|
+
* Lands at the index nearest the item's current one rather than at the top,
|
|
87
|
+
* because a card carried sideways across a board should stay roughly where it
|
|
88
|
+
* was vertically — the same thing the pointer does for free.
|
|
89
|
+
*/
|
|
90
|
+
moveContainer(delta: number): void;
|
|
91
|
+
/** Release. Emits `onDragEnd` even for a no-op so consumers can announce it. */
|
|
92
|
+
commit(): void;
|
|
93
|
+
/** Esc, `pointercancel`, or an unmount mid-gesture. Never writes. */
|
|
94
|
+
cancel(): void;
|
|
95
|
+
/** The container the pointer is over right now, or null. */
|
|
96
|
+
containerAtPoint(point: Point): string | null;
|
|
97
|
+
/** How many items a container holds once the carried one is taken out. */
|
|
98
|
+
slotCount(container: string): number;
|
|
99
|
+
}
|