elements-kit 0.27.4 → 0.27.6

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.
Files changed (103) hide show
  1. package/README.md +1 -0
  2. package/dist/attributes.d.mts +1 -1
  3. package/dist/await.d.mts +1 -1
  4. package/dist/await.mjs +1 -1
  5. package/dist/{children-_cMdyX7Q.d.mts → children-CjlmAzxx.d.mts} +3 -3
  6. package/dist/chunk-CfYAbeIz.mjs +13 -0
  7. package/dist/{custom-elements-C7oiqw-y.d.mts → custom-elements-CTqSkWI7.d.mts} +1 -1
  8. package/dist/custom-elements.d.mts +1 -1
  9. package/dist/direction-EwIAAn1f.d.mts +29 -0
  10. package/dist/{element-DgQvp-49.mjs → element-bMvwF1ue.mjs} +2 -2
  11. package/dist/for.d.mts +1 -1
  12. package/dist/for.mjs +2 -2
  13. package/dist/{fragment-BJfcQdsL.mjs → fragment-DV0hrE_A.mjs} +2 -2
  14. package/dist/{hot-Zl0s17uq.mjs → hot-kRKLQS6B.mjs} +2 -2
  15. package/dist/hydrate/index.mjs +1 -1
  16. package/dist/{hydrate-ICXw1FIY.mjs → hydrate-Vx_iBMqJ.mjs} +3 -3
  17. package/dist/integrations/astro-client.mjs +2 -2
  18. package/dist/integrations/astro-server.mjs +3 -3
  19. package/dist/integrations/astro-slots.mjs +2 -2
  20. package/dist/integrations/hmr-runtime.mjs +2 -2
  21. package/dist/integrations/react.d.mts +1 -1
  22. package/dist/integrations/react.mjs +2 -2
  23. package/dist/jsx-runtime/dev.d.mts +2 -2
  24. package/dist/jsx-runtime/dev.mjs +2 -2
  25. package/dist/jsx-runtime/index.d.mts +2 -2
  26. package/dist/jsx-runtime/index.mjs +2 -2
  27. package/dist/render.mjs +1 -1
  28. package/dist/{scope-C1vELXqP.mjs → scope-B1kDu4YX.mjs} +1 -1
  29. package/dist/server/index.mjs +1 -1
  30. package/dist/{server-Qm9JTZ-J.mjs → server-DxiXDjQU.mjs} +3 -3
  31. package/dist/signals/index.d.mts +1 -1
  32. package/dist/signals/index.mjs +2 -2
  33. package/dist/slot.mjs +1 -1
  34. package/dist/ui/otp-input/index.d.mts +2 -2
  35. package/dist/ui/otp-input/index.mjs +1 -1
  36. package/dist/ui/overlay/handle.css +134 -0
  37. package/dist/ui/overlay/index.css +13 -88
  38. package/dist/ui/overlay/index.d.mts +232 -347
  39. package/dist/ui/overlay/index.mjs +676 -1550
  40. package/dist/ui/overlay/overlay.css +74 -135
  41. package/dist/utilities/_observe.mjs +1 -1
  42. package/dist/utilities/active-element.d.mts +1 -1
  43. package/dist/utilities/active-element.mjs +1 -1
  44. package/dist/utilities/async.d.mts +7 -1
  45. package/dist/utilities/async.mjs +13 -1
  46. package/dist/utilities/context.mjs +1 -1
  47. package/dist/utilities/debounced.d.mts +1 -1
  48. package/dist/utilities/debounced.mjs +1 -1
  49. package/dist/utilities/direction.d.mts +2 -0
  50. package/dist/utilities/direction.mjs +42 -0
  51. package/dist/utilities/dom-lifecycle.bench.mjs +2 -2
  52. package/dist/utilities/dom-lifecycle.d.mts +1 -1
  53. package/dist/utilities/dom-lifecycle.mjs +1 -1
  54. package/dist/utilities/element-rect.d.mts +1 -1
  55. package/dist/utilities/element-rect.mjs +1 -1
  56. package/dist/utilities/element-scroll.d.mts +1 -1
  57. package/dist/utilities/environment.d.mts +1 -1
  58. package/dist/utilities/event-driven.d.mts +1 -1
  59. package/dist/utilities/event-driven.mjs +1 -1
  60. package/dist/utilities/event-listener.d.mts +1 -1
  61. package/dist/utilities/event-listener.mjs +1 -1
  62. package/dist/utilities/focus-within.d.mts +1 -1
  63. package/dist/utilities/focus-within.mjs +1 -1
  64. package/dist/utilities/hover.d.mts +1 -1
  65. package/dist/utilities/hover.mjs +1 -1
  66. package/dist/utilities/interval.d.mts +1 -1
  67. package/dist/utilities/interval.mjs +1 -1
  68. package/dist/utilities/location.d.mts +1 -1
  69. package/dist/utilities/location.mjs +1 -1
  70. package/dist/utilities/media-devices.d.mts +1 -1
  71. package/dist/utilities/media-devices.mjs +1 -1
  72. package/dist/utilities/media-player.d.mts +1 -1
  73. package/dist/utilities/media-query.d.mts +1 -1
  74. package/dist/utilities/media-query.mjs +1 -1
  75. package/dist/utilities/network.d.mts +1 -1
  76. package/dist/utilities/network.mjs +1 -1
  77. package/dist/utilities/orientation.d.mts +1 -1
  78. package/dist/utilities/orientation.mjs +1 -1
  79. package/dist/utilities/previous.d.mts +1 -1
  80. package/dist/utilities/previous.mjs +1 -1
  81. package/dist/utilities/promise.d.mts +1 -1
  82. package/dist/utilities/promise.mjs +1 -1
  83. package/dist/utilities/retry.mjs +1 -1
  84. package/dist/utilities/routing.d.mts +1 -1
  85. package/dist/utilities/routing.mjs +1 -1
  86. package/dist/utilities/search-params.d.mts +1 -1
  87. package/dist/utilities/storage.d.mts +1 -1
  88. package/dist/utilities/storage.mjs +1 -1
  89. package/dist/utilities/throttled.d.mts +1 -1
  90. package/dist/utilities/throttled.mjs +1 -1
  91. package/dist/utilities/timeout.d.mts +1 -1
  92. package/dist/utilities/timeout.mjs +1 -1
  93. package/dist/utilities/window-focus.d.mts +1 -1
  94. package/dist/utilities/window-focus.mjs +1 -1
  95. package/dist/utilities/window-size.d.mts +1 -1
  96. package/dist/utilities/window-size.mjs +1 -1
  97. package/package.json +9 -6
  98. /package/dist/{attributes-3r7Diua4.d.mts → attributes-YQZNO15D.d.mts} +0 -0
  99. /package/dist/{environment-c2ftMYT0.d.mts → environment-EQugnOcg.d.mts} +0 -0
  100. /package/dist/{index-BrVMftR8.d.mts → index-BSAqa0-0.d.mts} +0 -0
  101. /package/dist/{lib-DYypKhxk.mjs → lib-Dw0g-vex.mjs} +0 -0
  102. /package/dist/{polyfill-CdZVCxdo.mjs → polyfill-B1lNNcum.mjs} +0 -0
  103. /package/dist/{polyfill-BVNd6ogU.d.mts → polyfill-_7qvybvt.d.mts} +0 -0
@@ -1,383 +1,268 @@
1
- import { Placement } from "@floating-ui/dom";
1
+ import { r as MaybeReactive } from "../../index-BSAqa0-0.mjs";
2
+ import { t as Direction } from "../../direction-EwIAAn1f.mjs";
2
3
 
3
- //#region src/ui/overlay/constraint.d.ts
4
- /**
5
- * The constraint — one of the two spatial primitives (with the anchor).
6
- * A `Region` is a reactive rect; `constraint()` builds one from an
7
- * element, a plain rect, or nothing (the live viewport). `confine()`
8
- * applies a region to an overlay by syncing it into the
9
- * `--overlay-constraint-top/-left/-width/-height` channels every location
10
- * clamp and gesture bound derives from (declared in index.css with
11
- * viewport defaults). Derived values build on regions — `detents()`
12
- * quantizes one, `rubber()` resists at its edges.
13
- */
14
- /** A reactive rect. `createElementRect` returns one reactive `DOMRect`,
15
- * so the element branch projects its fields onto this shape; custom
16
- * rects (a static region, a virtual area) can be supplied too. */
17
- interface Region {
18
- top(): number;
19
- left(): number;
20
- width(): number;
21
- height(): number;
4
+ //#region src/ui/overlay/box.d.ts
5
+ /** The channel axes a box value moves along. */
6
+ type Axis = keyof ReadonlyBox;
7
+ interface IDirection {
8
+ readonly direction: "ltr" | "rtl";
22
9
  }
23
- /** A plain rect a `Region` can be built from. */
24
- interface RectInit {
25
- top: number;
26
- left: number;
27
- width: number;
28
- height: number;
10
+ interface ReadonlyBox {
11
+ readonly x: number;
12
+ readonly y: number;
13
+ readonly w: number;
14
+ readonly h: number;
29
15
  }
30
- /**
31
- * Builds a {@link Region}: from an `Element` (observed via
32
- * `ResizeObserver` through `createElementRect`; cleanup routes through
33
- * the current scope), from a plain rect (static), or with no argument —
34
- * the live viewport (read at call time, not observed).
35
- */
36
- declare function constraint(source?: Element | RectInit): Region;
37
- interface OverlayConstraint {
38
- dispose(): void;
16
+ interface Box extends ReadonlyBox {
17
+ x: number;
18
+ y: number;
19
+ w: number;
20
+ h: number;
21
+ }
22
+ declare class WindowBox implements ReadonlyBox, IDirection {
23
+ get x(): number;
24
+ get y(): number;
25
+ get w(): number;
26
+ get h(): number;
27
+ get direction(): Direction;
28
+ }
29
+ declare const WINDOW_BOX: WindowBox;
30
+ declare class ElementBox implements ReadonlyBox {
31
+ #private;
32
+ constructor(el: MaybeReactive<Element>);
39
33
  [Symbol.dispose](): void;
34
+ get x(): number;
35
+ get y(): number;
36
+ get w(): number;
37
+ get h(): number;
40
38
  }
41
- /**
42
- * Resolves a custom property holding a length to pixels. Plain `px` values
43
- * parse directly; anything else (`svh` / `calc()` / fractions of the
44
- * constraint) resolves natively by measuring a hidden probe. `fallback` is
45
- * a CSS length expression used when the property is unset.
46
- */
47
- declare function resolveVarPx(overlay: HTMLElement, name: string, axis: "height" | "width", fallback?: string): number;
48
- /** Resolves the constraint rect every gesture bound derives from. */
49
- declare function resolveConstraint(overlay: HTMLElement): {
39
+ //#endregion
40
+ //#region src/ui/overlay/area.d.ts
41
+ /** Which of a box's points sits on a pin: its lo edge, hi edge, or middle. */
42
+ type Align = "start" | "end" | "center";
43
+ /** One axis of a region: a coordinate and the box point that sits on it,
44
+ * or `null` — the axis is free and the box keeps its own coordinate. */
45
+ type Pin = {
46
+ readonly align: Align;
47
+ readonly at: number;
48
+ } | null;
49
+ /** A pinned block edge and its coordinate. */
50
+ type BlockEdge = {
50
51
  top: number;
52
+ bottom?: never;
53
+ } | {
54
+ bottom: number;
55
+ top?: never;
56
+ };
57
+ /** A pinned inline edge and its coordinate. */
58
+ type InlineEdge = {
51
59
  left: number;
52
- width: number;
53
- height: number;
60
+ right?: never;
61
+ } | {
62
+ right: number;
63
+ left?: never;
64
+ };
65
+ /** Neither block edge pinned — the axis is free. */
66
+ type NoBlock = {
67
+ top?: never;
68
+ bottom?: never;
69
+ };
70
+ /** Neither inline edge pinned — the axis is free. */
71
+ type NoInline = {
72
+ left?: never;
73
+ right?: never;
54
74
  };
55
75
  /**
56
- * Confines an overlay to a {@link Region} by syncing it into the
57
- * `--overlay-constraint-*` variables. Every location clamp and gesture
58
- * bound derives from those variables, so the overlay re-clamps when the
59
- * region changes.
60
- *
61
- * Caveat: an element region observes size changes (`ResizeObserver`) — a
62
- * container that moves without resizing (e.g. page scroll) does not
63
- * retrigger the sync.
64
- *
65
- * Registers its cleanup with the current scope (`onCleanup`) and also
66
- * returns it as `dispose` / `Symbol.dispose`; disposing removes the
67
- * variables, restoring the viewport constraint.
68
- *
69
- * @example
70
- * ```ts
71
- * import { constraint, confine } from "elements-kit/ui/overlay";
72
- *
73
- * const panel = document.querySelector("dialog.x-overlay")!;
74
- * confine(panel, constraint(document.querySelector("main")!));
75
- * ```
76
- */
77
- declare function confine(overlay: HTMLElement, region: Region): OverlayConstraint;
78
- //#endregion
79
- //#region src/ui/overlay/anchor.d.ts
80
- /**
81
- * The anchor — one of the two spatial primitives (with the constraint).
82
- * `anchor(overlay, follow?)` gives the overlay an anchor ELEMENT it
83
- * follows for its whole life; the anchor element follows `follow` until
84
- * something else moves it (a `draggable()` service, author code). The
85
- * overlay itself has no states — dragging, tearing off, re-pinning are
86
- * all things that happen to the anchor.
87
- *
88
- * Two engines, chosen once at wire time, never switched:
89
- *
90
- * - Native CSS anchor positioning (compound gate, no `within`/`arrow`):
91
- * the overlay's `position-anchor` points at the anchor element; when
92
- * `follow` is an element the anchor pins itself to it through a second
93
- * native hop (`[data-follow]` rule in index.css mirrors the followed
94
- * box via `anchor()`/`anchor-size()`). Placement, flip and scroll
95
- * tracking are compositor-side through both hops — zero JS.
96
- * - Floating UI (below the gate, or `within`/`arrow` requested — native
97
- * CSS has no boundary control and no flip signal): `autoUpdate` writes
98
- * the box center into the `--overlay-x`/`-y` channels while the
99
- * overlay is open; a `dragmove` event from the drag service triggers
100
- * an immediate reposition. The initial positioning write is instant;
101
- * geometry transitions re-enable after it (Base UI's `data-instant`
102
- * semantics), so re-pins and live area changes morph by the
103
- * stylesheet. During an anchor drag, writes suppress geometry
104
- * transitions again — the overlay must not ease behind the finger.
105
- *
106
- * `data-anchor="element"` is a static wiring marker (stamped here,
107
- * removed on dispose, never toggled). `data-placed` is output state —
108
- * the settled side, feeding the arrow and `transform-origin` (a hint
109
- * from `--overlay-area` under the native engine, the real side under
110
- * Floating UI). A first pointer-down from `draggable()` tears the
111
- * follow pin (the `data-follow` contract); a fresh open re-pins.
112
- */
113
- interface AnchorOptions {
114
- /** Flip/shift boundary — placement confined to this region instead of
115
- * the viewport. Forces the Floating UI engine. */
116
- within?: Region;
117
- /** Caret pointing at the anchor (`.x-overlay-arrow`, injected when not
118
- * authored; a number sets `--overlay-arrow-size` in px). Forces the
119
- * Floating UI engine. */
120
- arrow?: number | boolean;
121
- }
122
- /**
123
- * Maps a `position-area` value to the Floating UI placement. Spanning
124
- * toward an edge leaves the box flush with the *opposite* edge, so
125
- * `span-*-end` is a `-start` alignment (and vice versa) — Floating UI
126
- * resolves `-start`/`-end` logically, so the span tokens need no dir
127
- * check; only the physical inline sides do. Unknown values fall back to
128
- * `bottom` (the CSS default, `block-end`).
76
+ * A corner (one edge pinned on each axis: a tooltip, a popover) or a side
77
+ * (one edge, the other axis free: a bottom sheet). Never empty, and never
78
+ * both edges of one axis.
129
79
  */
130
- declare function areaToPlacement(area: string, rtl?: boolean): Placement;
80
+ type Boundary = (BlockEdge & InlineEdge) | (BlockEdge & NoInline) | (NoBlock & InlineEdge);
131
81
  /**
132
- * Gives `overlay` its anchor element and returns it. The overlay follows
133
- * the anchor for life; the anchor follows `follow` (element or rect)
134
- * until something moves it. Pass the returned element to `draggable()`
135
- * to make the composition tearable dragging moves the anchor.
136
- *
137
- * `follow` may be a getter reading a signal — re-pinning on change is
138
- * how a shared popover slides between nav triggers: the native chain
139
- * glides there on the anchor element's CSS transition; the channel
140
- * engine lets that one write animate.
141
- *
142
- * Registers all cleanup with the current scope (`onCleanup`): the anchor
143
- * element, the wiring, and the stamped attributes are removed together.
144
- *
145
- * @example
146
- * ```ts
147
- * import { anchor, draggable, rubber } from "elements-kit/ui/overlay";
82
+ * Somewhere a box may go: a semi-bounded plane, each axis pinned or free.
83
+ * `place` is the only operation: it never writes, so the caller picks which
84
+ * channels to take — `box.x = region.place(box).x` moves one axis and leaves
85
+ * the rest. The box is placed as given: one larger than its room overflows
86
+ * rather than shrinks, as CSS does.
148
87
  *
149
- * const a = anchor(panel, trigger);
150
- * draggable(a, undefined, rubber()).attach(panel);
151
- *
152
- * // shared nav popover — re-anchors (and glides) when the signal changes
153
- * const active = signal(firstTrigger);
154
- * anchor(menu, () => active(), { arrow: true });
155
- * ```
156
- */
157
- declare function anchor(overlay: HTMLElement, follow?: Element | RectInit | (() => Element | RectInit | null | undefined), opts?: AnchorOptions): HTMLElement;
158
- //#endregion
159
- //#region src/ui/overlay/resize-strategy.d.ts
160
- /**
161
- * Resize strategies — pluggable policy for a resize drag's live bounds
162
- * and resting size. Pure (no DOM); the gesture injects the context.
163
- * Built-in: `freeResize` (default). `detents()` (detents.ts) quantizes a
164
- * constraint region and doubles as a strategy.
88
+ * The four insets read back as CSS would want them: the pinned edge's
89
+ * coordinate, `null` for the other three (`auto`). A centred axis is not an
90
+ * inset — both its edges are `null`.
165
91
  */
166
- /** How far (ms) a release velocity is projected when picking a rest. */
167
- declare const PROJECTION_MS = 160;
168
- /** Clamp `value` into `[min, max]`. */
169
- declare function clamp(value: number, min: number, max: number): number;
170
- /**
171
- * The release context a `ResizeStrategy` decides against. The gesture
172
- * builds it per drag; `resolve` turns a step value into pixels.
173
- */
174
- interface ResizeContext {
175
- /** Dragged size along the axis (px, before clamping). */
176
- size: number;
177
- /** Size at the gesture's start (px). */
178
- startSize: number;
179
- /** Release velocity along the axis (px/ms; positive = shrinking). */
180
- velocity: number;
181
- /** Resize axis. */
182
- axis: "width" | "height";
183
- /** Hard room the surface may occupy on the axis (px). */
184
- min: number;
185
- max: number;
186
- /** Whether a drag/flick past the minimum may dismiss. */
187
- dismissible: boolean;
188
- /** Release velocity (px/ms) past which a sub-minimum release dismisses. */
189
- velocityThreshold: number;
190
- /** Resolves a step to px — a number is a fraction of the constraint
191
- * along the axis; a string is any CSS length. */
192
- resolve(value: number | string): number;
92
+ interface Region {
93
+ readonly left: number | null;
94
+ readonly right: number | null;
95
+ readonly top: number | null;
96
+ readonly bottom: number | null;
97
+ place(box: ReadonlyBox): Box;
193
98
  }
99
+ /** One axis of a {@link Region.place}: where a box `n` long, currently at
100
+ * `own`, starts once `pin` is honoured. */
101
+ declare function placeAxis(pin: Pin, own: number, n: number): number;
102
+ /** The inset a pin yields on one edge: its coordinate if it pins that edge. */
103
+ declare function inset(pin: Pin, edge: "start" | "end"): number | null;
194
104
  /**
195
- * Decides where a resize drag rests. The gesture calls `bounds()` for the
196
- * live rubber-band and `rest()` on release (the resting size, or `null`
197
- * to dismiss). Built-ins: `freeResize` (default), `detents`.
105
+ * A {@link Region} driven by writes for gestures, where the box grows away
106
+ * from the edge the user is not dragging. Assigning an inset pins that edge
107
+ * and releases its opposite; assigning `null` frees the axis.
198
108
  */
199
- interface ResizeStrategy {
200
- /** Soft `[lo, hi]` bounds for the live drag — rubber-band past these.
201
- * Defaults to the hard room when omitted. */
202
- bounds?(ctx: ResizeContext): [number, number];
203
- /** Resting size (px) on release, or `null` to dismiss. */
204
- rest(ctx: ResizeContext): number | null;
109
+ declare class MutableRegion implements Region {
110
+ #private;
111
+ constructor(boundary: Boundary);
112
+ get left(): number | null;
113
+ get right(): number | null;
114
+ get top(): number | null;
115
+ get bottom(): number | null;
116
+ set left(v: number | null);
117
+ set right(v: number | null);
118
+ set top(v: number | null);
119
+ set bottom(v: number | null);
120
+ place(box: ReadonlyBox): Box;
205
121
  }
206
- /**
207
- * Picks the index of the detent closest to the released size, projected
208
- * along the release velocity (px/ms, positive = shrinking). Returns `-1`
209
- * when the gesture should dismiss instead.
210
- */
211
- declare function closestDetent(sizePx: number, detentsPx: readonly number[], velocityPxPerMs?: number, dismissible?: boolean, velocityThreshold?: number): number;
212
- /**
213
- * Free resize: drag to any size within the room; a flick or shrink past
214
- * the minimum dismisses. The default strategy.
215
- */
216
- declare function freeResize(opts?: {
217
- min?: number;
218
- }): ResizeStrategy;
219
122
  //#endregion
220
- //#region src/ui/overlay/detents.d.ts
221
- /**
222
- * Detents — a customization of the constraint: the region, quantized.
223
- * One snapping concept for both services: `resize()` (and the markup
224
- * gestures) snap extents to the stops; `draggable()` snaps positions to
225
- * them. A bottom sheet's size detents and its top-edge position detents
226
- * were always the same thing — here they are literally the same object.
227
- */
228
- /** A {@link Region} with quantized stops. Doubles as a `ResizeStrategy`
229
- * (the stops resolve per axis through the gesture's `ResizeContext`). */
230
- interface Space extends ResizeStrategy {
231
- readonly region: Region;
232
- readonly stops: readonly (number | string)[];
233
- /** The numeric stops resolved against a region axis (px, sorted) —
234
- * position snapping for `draggable()`. String stops (CSS lengths) need
235
- * an element context and only apply to resizes. */
236
- positions(axis: "width" | "height"): number[];
237
- }
123
+ //#region src/ui/overlay/anchor.d.ts
238
124
  /**
239
- * Quantizes a region: each stop is a fraction of the region along the
240
- * axis (number `0–1`) or a CSS length (string, resize-only). Flick-aware
241
- * on release; shrinking past the smallest stop dismisses (when the
242
- * consumer allows dismissal).
125
+ * The anchor-side vocabulary of the CSS `anchor()` function, reimplemented
126
+ * reactively the JS tier speaks the same words as the native one:
243
127
  *
244
- * @example
245
- * ```ts
246
- * import { constraint, detents } from "elements-kit/ui/overlay";
128
+ * overlay.y = anchor_length(a, "top", "bottom") ≡ top: anchor(bottom)
247
129
  *
248
- * const d = detents(constraint(), [0.25, 0.6, 0.9]); // of the viewport
249
- * ```
130
+ * Horizontal writing modes only: the block axis always starts at the top;
131
+ * only the inline axis consults `direction`.
250
132
  */
251
- declare function detents(region: Region, stops: readonly (number | string)[]): Space;
252
- //#endregion
253
- //#region src/ui/overlay/rubber.d.ts
133
+ /** Sides valid in a block-axis inset (`top` / `bottom`). */
134
+ type BlockSide = "top" | "bottom" | "inside" | "outside" | "start" | "end" | "self-start" | "self-end" | "center";
135
+ /** Sides valid in an inline-axis inset (`left` / `right`). */
136
+ type InlineSide = "left" | "right" | "inside" | "outside" | "start" | "end" | "self-start" | "self-end" | "center";
137
+ /** The physical inset longhands. */
138
+ type PhysicalInset = "top" | "right" | "bottom" | "left";
139
+ /** Every inset property `anchor()` may sit in. */
140
+ type Inset = PhysicalInset | "inset-block-start" | "inset-block-end" | "inset-inline-start" | "inset-inline-end";
254
141
  /**
255
- * Effects composable physics for motion through a space. Services
256
- * (`draggable`, `resize`) run each axis value through the effect chain:
257
- * `during` on every move, `settle` on release (`null` = dismiss signal).
258
- * `rubber()` is the built-in; custom effects are just objects.
142
+ * The reactive `anchor()` function: the viewport coordinate of an anchor line
143
+ * on `box`, in the context of the inset property being computed. Reads the
144
+ * box's reactive geometry, so calling it inside an `effect` tracks the anchor.
259
145
  */
260
- interface Effect {
261
- /** Transform a live value (px on one axis) against the axis bounds. */
262
- during?(value: number, bounds: readonly [number, number]): number;
263
- /** Pick the resting value on release, or `null` to signal dismissal. */
264
- settle?(value: number, velocity: number, bounds: readonly [number, number]): number | null;
265
- }
146
+ declare function anchor_length(box: Box & Partial<IDirection>, inset: Inset, side: BlockSide | InlineSide | number): number;
266
147
  /**
267
- * Edge resistance values past the bounds move at a fraction of the
268
- * pointer (the iOS rubber band). Pure `resist()` under the hood; no
269
- * channels involved, so it applies to anything a service moves.
270
- */
271
- declare function rubber(): Effect;
272
- //#endregion
273
- //#region src/ui/overlay/draggable.d.ts
274
- /**
275
- * The drag service — moves a target element through a space. Generic by
276
- * design: drag any positioned element by any handle. For overlays, the
277
- * target is the anchor element from `anchor()` dragging the anchor
278
- * drags the overlay, with no overlay state involved.
148
+ * The reactive `position-area` property: the region of the viewport an
149
+ * overlay anchored to `anchor` may occupy, with the region's default
150
+ * self-alignment as {@link Region.place} outward regions hug the anchor,
151
+ * spans go flush against its far edge, center is `anchor-center`. Nothing is
152
+ * written; the caller takes what it wants from `place`:
153
+ *
154
+ * const area = new PositionArea(a, "top span-left");
155
+ * effect(() => { overlay.x = area.place(overlay).x; });
156
+ *
157
+ * The value is parsed once, at construction; the geometry reads the anchor
158
+ * and window on every access, so reading it inside an `effect` tracks both.
279
159
  *
280
- * The pipeline runs per axis: live values go through each effect's
281
- * `during` (e.g. `rubber()` resistance at the space edges); on release
282
- * the value goes through each `settle`, then snaps to the space's
283
- * numeric stops when a `detents()` space is given (`null` from a settle
284
- * = dismiss signal, surfaced on the `dragend` detail). Events on the
285
- * target: `dragmove` (`{x, y}`) every move, `dragend`
286
- * (`{x, y, velocity, rest}`) on release.
160
+ * Bounded by the window. A tighter bound (a `Constraint`, a scroll container)
161
+ * is an intersection with the region, so it composes afterwards rather than
162
+ * being a parameter here.
287
163
  *
288
- * First pointer-down tears a `data-follow` pin (the `anchor()` contract):
289
- * the target freezes at its current rect and the pointer takes over.
164
+ * There is no gap parameter, for the same reason CSS has none: the offset off
165
+ * the anchor is the overlay's own `margin`.
290
166
  */
291
- interface DragService {
292
- /** Move the target programmatically (through the `during` effects). */
293
- update(point: {
294
- x: number;
295
- y: number;
296
- }): void;
297
- /** Wire the pointer plumbing to a handle. */
298
- attach(handle: Element): {
299
- dispose(): void;
300
- };
301
- dispose(): void;
302
- [Symbol.dispose](): void;
167
+ declare class PositionArea implements Region, ReadonlyBox {
168
+ #private;
169
+ readonly anchor: ReadonlyBox;
170
+ constructor(anchor: ReadonlyBox, area: string);
171
+ get x(): number;
172
+ get y(): number;
173
+ get w(): number;
174
+ get h(): number;
175
+ get left(): number | null;
176
+ get right(): number | null;
177
+ get top(): number | null;
178
+ get bottom(): number | null;
179
+ place(box: ReadonlyBox): Box;
303
180
  }
304
- declare function draggable(target: HTMLElement, space?: Region | Space, ...effects: Effect[]): DragService;
305
181
  //#endregion
306
- //#region src/ui/overlay/gestures.d.ts
307
- interface OverlayGestureOptions {
308
- /** How a resize drag rests. Default: `freeResize()`. */
309
- resize?: ResizeStrategy;
310
- /** Allow a drag/flick past the minimum to close. Default `true`. */
311
- dismissible?: boolean;
312
- /** Release velocity (px/ms, shrinking) that dismisses. Default `0.5`. */
313
- velocityThreshold?: number;
182
+ //#region src/ui/overlay/overlay.d.ts
183
+ declare class PartialBox implements Partial<Box> {
184
+ x: number | undefined;
185
+ y: number | undefined;
186
+ w: number | undefined;
187
+ h: number | undefined;
188
+ constructor(x?: number | undefined, y?: number | undefined, w?: number | undefined, h?: number | undefined);
189
+ }
190
+ declare class TransformableBox implements ReadonlyBox, Transformable {
191
+ readonly transform: PartialBox;
192
+ readonly displacement: Displacement;
193
+ constructor(transform?: PartialBox);
194
+ get x(): number;
195
+ set x(value: number);
196
+ get y(): number;
197
+ set y(value: number);
198
+ get w(): number;
199
+ set w(value: number);
200
+ get h(): number;
201
+ set h(value: number);
202
+ }
203
+ declare class Displacement extends PartialBox {
204
+ readonly box: TransformableBox;
205
+ constructor(box: TransformableBox);
206
+ apply(): void;
207
+ clear(): void;
314
208
  }
315
- interface OverlayGestures {
316
- /** Resize to a size (px) along the resize axis — animated by CSS. */
317
- resize(size: number): void;
318
- dispose(): void;
209
+ declare class OverlayBox extends TransformableBox implements IDirection {
210
+ #private;
211
+ readonly element: HTMLElement;
212
+ constructor(element: HTMLElement);
213
+ get w(): number;
214
+ set w(value: number);
215
+ get h(): number;
216
+ set h(value: number);
217
+ get x(): number;
218
+ set x(value: number);
219
+ get y(): number;
220
+ set y(value: number);
221
+ /** The element's computed direction, read at call time. */
222
+ get direction(): "ltr" | "rtl";
223
+ dispose: () => void;
319
224
  [Symbol.dispose](): void;
320
225
  }
321
- /**
322
- * Opt-in pointer gestures for `.x-overlay`, dispatched by the gesture
323
- * attributes (structure stays in markup; policy is options):
324
- *
325
- * - An edge word (`block-*` / `inline-*`) is a whole-surface size drag
326
- * along that axis — block drags the height (sheets), inline the width
327
- * (drawers), `:dir(rtl)` flips the inline sign. The side names the
328
- * handle; the opposite edge stays put.
329
- * - A corner word (`start-start` / block side first) is a desktop-
330
- * window resize from a square zone at that corner, anchored at the
331
- * opposite corner so the surface never grows past the constraint. The
332
- * width follows the `resize` strategy; the height is a free clamp.
333
- * - `data-draggable` moves the surface in x/y from the top strip,
334
- * rubber-banding at the edges; flinging it off the constraint dismisses
335
- * (when `dismissible`).
336
- *
337
- * Layered for testability: `gesture-model` owns the pure mode reducers +
338
- * math, and `overlay-dom` owns all DOM contact (pointer plumbing + channel
339
- * I/O). This function is the wiring — it picks a pure `Session` from
340
- * `detectEngagement` and adapts it to the recognizer through the io.
341
- * The `resize` strategy (`freeResize` by default, or `detents`) decides the
342
- * rested size, written to the public `--overlay-w`/`--overlay-h` channels;
343
- * CSS renders and animates them. JS never touches `translate`/`top`/`left`.
344
- *
345
- * Registers its cleanup with the current scope (`onCleanup`) and also
346
- * returns it as `dispose` / `Symbol.dispose`.
347
- *
348
- * @example
349
- * ```ts
350
- * import { constraint, createOverlayGestures, detents } from "elements-kit/ui/overlay";
351
- *
352
- * const el = document.querySelector("dialog.x-overlay")!;
353
- * createOverlayGestures(el, { resize: detents(constraint(), [0.25, 0.6, 0.9]) });
354
- * el.addEventListener("resizechange", (e) => console.log(e.detail));
355
- * ```
356
- */
357
- declare function createOverlayGestures(overlay: HTMLElement, options?: OverlayGestureOptions): OverlayGestures;
226
+ interface Transformable {
227
+ displacement: Displacement;
228
+ }
229
+ declare namespace gestures_d_exports {
230
+ export { Modifier, detent, nearest, rubber, snap };
231
+ }
232
+ /** A pure display-time shaper: raw scalar constrained scalar. */
233
+ type Modifier = (value: number) => number;
234
+ /** Elastic resistance past `[min, max]`. The true value stays in `Motion`, so
235
+ * release settles back cleanly. `dimension` = axis extent; `constant` = iOS
236
+ * tension (higher = looser). */
237
+ declare function rubber(min: number, max: number, dimension: number, constant?: number): Modifier;
238
+ /** The nearest detent to `value`. */
239
+ declare function nearest(value: number, points: number[]): number;
240
+ /** Magnetic pull toward the nearest detent during a drag (0 = free, 1 = snap). */
241
+ declare function detent(points: number[], strength?: number): Modifier;
242
+ /** Release target: project by velocity (`reach` ms of carry), then nearest detent. */
243
+ declare function snap(value: number, velocity: number, points: number[], reach?: number): number;
358
244
  //#endregion
359
- //#region src/ui/overlay/resize.d.ts
360
- /**
361
- * The resize service — sizes a target through a space. The handle you
362
- * `attach()` is the whole gesture zone (unlike the markup gestures,
363
- * which zone-detect on the overlay surface); the side comes from the
364
- * target's `data-resize` value, same vocabulary as the stylesheet.
365
- *
366
- * The space is any `ResizeStrategy` — pass a `detents()` space to snap,
367
- * omit for `freeResize()`. Effects apply on release: each `settle` runs
368
- * over the strategy's rested size (`null` = dismiss). Live rubber past
369
- * the strategy bounds is built into the sessions.
370
- */
371
- interface ResizeService {
372
- /** Resize to a size (px) along the resize axis — animated by CSS. */
373
- update(size: number): void;
374
- /** Wire the pointer plumbing to a handle. */
375
- attach(handle: Element): {
376
- dispose(): void;
377
- };
378
- dispose(): void;
379
- [Symbol.dispose](): void;
245
+ //#region src/ui/overlay/motion.d.ts
246
+ interface IMotion {
247
+ value: number;
248
+ readonly displacement: number;
249
+ readonly delta: number;
250
+ readonly velocity: number;
251
+ abort(): void;
252
+ }
253
+ declare class Motion implements IMotion {
254
+ #private;
255
+ constructor(value?: number);
256
+ get value(): number;
257
+ set value(value: number);
258
+ get delta(): number;
259
+ get velocity(): number;
260
+ /** How far the value has moved from its initial (seed) — reactive.
261
+ * The displacement column: `value − initial`, starts at 0. */
262
+ get displacement(): number;
263
+ /** Nudge the value by a displacement — delta/velocity fall out of the setter. */
264
+ move(delta: number): void;
265
+ abort(initial?: number): void;
380
266
  }
381
- declare function resize(target: HTMLElement, space?: ResizeStrategy, ...effects: Effect[]): ResizeService;
382
267
  //#endregion
383
- export { AnchorOptions, DragService, Effect, OverlayConstraint, OverlayGestureOptions, OverlayGestures, PROJECTION_MS, RectInit, Region, ResizeContext, ResizeService, ResizeStrategy, Space, anchor, areaToPlacement, clamp, closestDetent, confine, constraint, createOverlayGestures, detents, draggable, freeResize, resize, resolveConstraint, resolveVarPx, rubber };
268
+ export { type Align, type Axis, type BlockSide, type Boundary, ElementBox, gestures_d_exports as Gestures, type IDirection, type IMotion, type InlineSide, type Inset, Motion, MutableRegion, OverlayBox, type PhysicalInset, type Pin, PositionArea, type ReadonlyBox, type Region, WINDOW_BOX, WindowBox, anchor_length, inset, placeAxis };