@antadesign/anta 0.3.26 → 0.3.28

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 (133) hide show
  1. package/README.md +26 -28
  2. package/dist/anta_helpers.d.ts +8 -0
  3. package/dist/anta_helpers.js +18 -0
  4. package/dist/box-types.d.ts +1 -1
  5. package/dist/bundle.css +1 -1
  6. package/dist/bundle.js +36 -42
  7. package/dist/capture-types.d.ts +156 -0
  8. package/dist/components/Banner.js +2 -2
  9. package/dist/components/Box.d.ts +15 -0
  10. package/dist/components/Box.js +3 -11
  11. package/dist/components/Button.js +2 -2
  12. package/dist/components/Capture.d.ts +39 -0
  13. package/dist/components/Capture.js +36 -0
  14. package/dist/components/Card.js +2 -2
  15. package/dist/components/Checkbox.d.ts +10 -11
  16. package/dist/components/Checkbox.js +5 -13
  17. package/dist/components/Expander.js +2 -2
  18. package/dist/components/Input.js +2 -2
  19. package/dist/components/InputTime.js +2 -2
  20. package/dist/components/Loader.js +2 -1
  21. package/dist/components/MenuItem.d.ts +7 -8
  22. package/dist/components/MenuItem.js +4 -4
  23. package/dist/components/Progress.js +2 -2
  24. package/dist/components/RadioGroup.d.ts +12 -13
  25. package/dist/components/RadioGroup.js +7 -23
  26. package/dist/components/Select.d.ts +12 -7
  27. package/dist/components/Select.js +4 -3
  28. package/dist/components/SelectFaceted.d.ts +7 -5
  29. package/dist/components/SelectFaceted.js +4 -3
  30. package/dist/components/Slider.js +3 -3
  31. package/dist/components/Steps.css +1 -1
  32. package/dist/components/Switch.d.ts +7 -8
  33. package/dist/components/Switch.js +3 -11
  34. package/dist/components/Tabs.js +2 -2
  35. package/dist/components/Tag.d.ts +7 -9
  36. package/dist/components/Tag.js +2 -2
  37. package/dist/components/Text.js +2 -2
  38. package/dist/components/Title.js +2 -2
  39. package/dist/components/capture-props.d.ts +30 -0
  40. package/dist/components/capture-props.js +44 -0
  41. package/dist/elements/a-avatar.css +1 -1
  42. package/dist/elements/a-banner.css +1 -1
  43. package/dist/elements/a-box.d.ts +1 -1
  44. package/dist/elements/a-box.js +11 -3
  45. package/dist/elements/a-button.css +1 -1
  46. package/dist/elements/a-button.d.ts +7 -9
  47. package/dist/elements/a-calendar.css +1 -1
  48. package/dist/elements/a-capture.css +1 -0
  49. package/dist/elements/a-capture.d.ts +10 -0
  50. package/dist/elements/a-capture.js +24 -0
  51. package/dist/elements/a-card.css +1 -1
  52. package/dist/elements/a-checkbox.css +1 -1
  53. package/dist/elements/a-checkbox.js +4 -4
  54. package/dist/elements/a-dialog.css +1 -1
  55. package/dist/elements/a-expander.css +1 -1
  56. package/dist/elements/a-expander.js +1 -0
  57. package/dist/elements/a-input-time.css +1 -1
  58. package/dist/elements/a-input-time.js +5 -7
  59. package/dist/elements/a-input.css +1 -1
  60. package/dist/elements/a-input.js +4 -6
  61. package/dist/elements/a-menu-item.css +1 -1
  62. package/dist/elements/a-menu.css +1 -1
  63. package/dist/elements/a-progress.css +1 -1
  64. package/dist/elements/a-radio.css +1 -1
  65. package/dist/elements/a-slider.css +1 -1
  66. package/dist/elements/a-slider.js +6 -9
  67. package/dist/elements/a-switch.css +1 -1
  68. package/dist/elements/a-tab.css +1 -1
  69. package/dist/elements/a-tabs.css +1 -1
  70. package/dist/elements/a-tag.css +1 -1
  71. package/dist/elements/a-text.css +1 -1
  72. package/dist/elements/a-text.js +1 -0
  73. package/dist/elements/a-title.css +1 -1
  74. package/dist/elements/a-tooltip.css +1 -1
  75. package/dist/elements/a-tooltip.d.ts +3 -4
  76. package/dist/elements/a-tooltip.js +0 -1
  77. package/dist/elements/capture-input.d.ts +5 -0
  78. package/dist/elements/capture-input.js +609 -0
  79. package/dist/elements/index.d.ts +1 -0
  80. package/dist/elements/index.js +3 -0
  81. package/dist/general_types.d.ts +56 -23
  82. package/dist/index.d.ts +4 -1
  83. package/dist/index.js +2 -0
  84. package/dist/jsx-runtime.d.ts +2 -1
  85. package/dist/reset.css +1 -1
  86. package/dist/theme-antithesis.css +1 -0
  87. package/dist/theme-antune.css +1 -0
  88. package/dist/tokens.css +1 -1
  89. package/docs/accessibility.md +24 -0
  90. package/docs/changelog.md +79 -0
  91. package/docs/colors.md +141 -0
  92. package/docs/comparison.md +463 -28
  93. package/docs/components/avatar.md +13 -17
  94. package/docs/components/banner.md +13 -27
  95. package/docs/components/box.md +226 -154
  96. package/docs/components/breadcrumbs.md +49 -12
  97. package/docs/components/button.md +48 -37
  98. package/docs/components/capture.md +345 -0
  99. package/docs/components/card.md +17 -38
  100. package/docs/components/checkbox.md +27 -50
  101. package/docs/components/dialog.md +14 -36
  102. package/docs/components/expander.md +15 -40
  103. package/docs/components/icon.md +111 -9
  104. package/docs/components/input-autocomplete.md +9 -11
  105. package/docs/components/input-date.md +33 -23
  106. package/docs/components/input-time.md +15 -23
  107. package/docs/components/input.md +27 -76
  108. package/docs/components/loader.md +7 -5
  109. package/docs/components/menu.md +75 -80
  110. package/docs/components/progress.md +10 -14
  111. package/docs/components/radio.md +28 -46
  112. package/docs/components/select-faceted.md +8 -25
  113. package/docs/components/select.md +33 -105
  114. package/docs/components/slider.md +16 -21
  115. package/docs/components/steps.md +38 -8
  116. package/docs/components/switch.md +16 -19
  117. package/docs/components/tabs.md +52 -40
  118. package/docs/components/tag.md +15 -24
  119. package/docs/components/text.md +10 -23
  120. package/docs/components/title.md +7 -8
  121. package/docs/components/toaster.md +6 -3
  122. package/docs/components/tooltip.md +13 -23
  123. package/docs/index.md +3 -1
  124. package/docs/install-config.md +42 -8
  125. package/docs/normalization.md +48 -3
  126. package/docs/packages/stickers.md +56 -0
  127. package/docs/theming.md +362 -14
  128. package/package.json +7 -4
  129. package/dist/components/InputDate.module.css +0 -1
  130. package/dist/components/Select.module.css +0 -1
  131. package/dist/components/SelectFaceted.module.css +0 -1
  132. package/dist/theme-anta.css +0 -1
  133. /package/dist/{search-index.json → capture-types.js} +0 -0
@@ -0,0 +1,609 @@
1
+ import { finiteNumber } from "../anta_helpers";
2
+ const CAPTURE_INPUT_ATTRIBUTES = [
3
+ "wheel-capture",
4
+ "wheel-activation",
5
+ "wheel-modifier",
6
+ "wheel-delay",
7
+ "wheel-tolerance",
8
+ "wheel-reset-on-move",
9
+ "pointer-capture",
10
+ "pointer-buttons",
11
+ "pointer-threshold",
12
+ "pointer-modifier",
13
+ "pointer-include-interactive",
14
+ "pan",
15
+ "pan-pointer-types",
16
+ "pan-threshold",
17
+ "pan-directions",
18
+ "pan-inertia",
19
+ "pan-time-constant",
20
+ "pan-min-velocity"
21
+ ];
22
+ const inputs = /* @__PURE__ */ new WeakMap();
23
+ const documents = /* @__PURE__ */ new WeakMap();
24
+ const DIRECTIONS = { up: 1, down: 2, left: 4, right: 8 };
25
+ const POINTER_TYPES = { mouse: 1, pen: 2, touch: 4 };
26
+ const WHEEL_CONTROLS = 'textarea, select, input[type="number"], input[type="range"], a-menu';
27
+ const INTERACTIVE = [
28
+ 'input, textarea, select, button, summary, a[href], [contenteditable]:not([contenteditable="false"])',
29
+ ...[
30
+ "button",
31
+ "checkbox",
32
+ "combobox",
33
+ "link",
34
+ "menuitem",
35
+ "menuitemcheckbox",
36
+ "menuitemradio",
37
+ "option",
38
+ "radio",
39
+ "scrollbar",
40
+ "searchbox",
41
+ "slider",
42
+ "spinbutton",
43
+ "switch",
44
+ "tab",
45
+ "textbox",
46
+ "treeitem"
47
+ ].map((role) => `[role~="${role}"]`),
48
+ "a-input, a-button, a-slider, a-checkbox, a-switch, a-radio, a-menu, a-menu-item, a-tab"
49
+ ].join(", ");
50
+ function mask(value, values, fallback) {
51
+ if (value === null || value === "") return fallback;
52
+ if (value === "all") return Object.values(values).reduce((result, bit) => result | bit, 0);
53
+ return value.trim().split(/\s+/).reduce((result, key) => result | (values[key] ?? 0), 0);
54
+ }
55
+ function numberAttr(surface, name, fallback, min = 0) {
56
+ return Math.max(min, finiteNumber(surface.getAttribute(name)?.trim() ?? null, fallback));
57
+ }
58
+ function modifierAttr(surface, name, fallback) {
59
+ const value = surface.getAttribute(name);
60
+ return value === "any" || value === "none" || value === "alt" || value === "ctrl" || value === "meta" || value === "shift" ? value : fallback;
61
+ }
62
+ function readWheel(surface) {
63
+ if (!surface.hasAttribute("wheel-capture")) return;
64
+ const directions = mask(surface.getAttribute("wheel-capture"), DIRECTIONS, 15);
65
+ const activation = surface.getAttribute("wheel-activation");
66
+ return {
67
+ directions,
68
+ activation: activation === "hover" || activation === "focus" || activation === "settled-or-focus" ? activation : "settled",
69
+ modifier: modifierAttr(surface, "wheel-modifier", "none"),
70
+ delay: numberAttr(surface, "wheel-delay", 150),
71
+ tolerance: numberAttr(surface, "wheel-tolerance", 5),
72
+ resetOnMove: surface.hasAttribute("wheel-reset-on-move")
73
+ };
74
+ }
75
+ function readPointer(surface) {
76
+ if (!surface.hasAttribute("pointer-capture")) return;
77
+ const types = mask(surface.getAttribute("pointer-capture"), POINTER_TYPES, 7);
78
+ if (!types) return;
79
+ const buttonAttribute = surface.getAttribute("pointer-buttons");
80
+ const buttons = buttonAttribute === null ? 1 : buttonAttribute.split(/\s+/).reduce((bits, button) => {
81
+ const n = Number(button);
82
+ return Number.isInteger(n) && n >= 0 && n <= 5 ? bits | 1 << n : bits;
83
+ }, 0);
84
+ if (!buttons) return;
85
+ return {
86
+ types,
87
+ buttons,
88
+ threshold: numberAttr(surface, "pointer-threshold", 0),
89
+ modifier: modifierAttr(surface, "pointer-modifier", "any"),
90
+ interactive: surface.hasAttribute("pointer-include-interactive")
91
+ };
92
+ }
93
+ function readPan(surface) {
94
+ if (!surface.hasAttribute("pan")) return;
95
+ const axis = surface.getAttribute("pan");
96
+ if (axis !== "" && axis !== "both" && axis !== "x" && axis !== "y") return;
97
+ const types = mask(surface.getAttribute("pan-pointer-types"), POINTER_TYPES, 4);
98
+ if (!types) return;
99
+ return {
100
+ types,
101
+ axis: axis || "both",
102
+ threshold: numberAttr(surface, "pan-threshold", 3),
103
+ directions: mask(surface.getAttribute("pan-directions"), DIRECTIONS, 15),
104
+ inertia: surface.hasAttribute("pan-inertia"),
105
+ tau: numberAttr(surface, "pan-time-constant", 325, 1),
106
+ minVelocity: numberAttr(surface, "pan-min-velocity", 0.02, 1e-3)
107
+ };
108
+ }
109
+ function inputStore(surface) {
110
+ const doc = surface.ownerDocument;
111
+ let store = documents.get(doc);
112
+ if (store) return store;
113
+ const view = doc.defaultView;
114
+ store = { doc, view, states: /* @__PURE__ */ new Set(), dwell: /* @__PURE__ */ new Map(), sessions: /* @__PURE__ */ new Map(), momenta: /* @__PURE__ */ new Set(), tracking: false, listening: false };
115
+ documents.set(doc, store);
116
+ view.addEventListener("blur", onWindowBlur);
117
+ doc.addEventListener("visibilitychange", onVisibilityChange);
118
+ return store;
119
+ }
120
+ function syncCaptureInput(surface, attribute) {
121
+ if (!surface.isConnected || !surface.ownerDocument.defaultView) return;
122
+ let state = inputs.get(surface);
123
+ if (!state && !surface.hasAttribute("wheel-capture") && !surface.hasAttribute("pointer-capture") && !surface.hasAttribute("pan")) return;
124
+ const wheel = readWheel(surface);
125
+ const pointer = readPointer(surface);
126
+ const pan = readPan(surface);
127
+ if (!wheel && !pointer && !pan) {
128
+ disconnectCaptureInput(surface, "disabled");
129
+ return;
130
+ }
131
+ if (!state) {
132
+ state = { surface, store: inputStore(surface) };
133
+ inputs.set(surface, state);
134
+ state.store.states.add(state);
135
+ }
136
+ const hadWheel = !!state.wheel;
137
+ const hadPointer = !!(state.pointer || state.pan);
138
+ state.wheel = wheel;
139
+ state.pointer = pointer;
140
+ state.pan = pan;
141
+ if (hadWheel !== !!wheel) {
142
+ if (wheel) surface.addEventListener("wheel", onWheel, { passive: false });
143
+ else surface.removeEventListener("wheel", onWheel);
144
+ }
145
+ if (hadPointer !== !!(pointer || pan)) {
146
+ if (pointer || pan) {
147
+ surface.addEventListener("pointerdown", onPointerDown);
148
+ surface.addEventListener("lostpointercapture", onLostCapture);
149
+ surface.addEventListener("click", onClick, true);
150
+ surface.addEventListener("dragstart", onDragStart);
151
+ } else removePointerListeners(surface);
152
+ }
153
+ if (!wheel || attribute?.startsWith("wheel-") && attribute !== "wheel-capture") state.store.dwell.delete(surface);
154
+ if (state.session && attribute && (attribute.startsWith("pointer-") || attribute === "pan" || attribute === "pan-pointer-types" || attribute === "pan-threshold")) {
155
+ finishSession(state.session, null, "disabled");
156
+ }
157
+ if (state.momentum && (!pan?.inertia || !pan.directions)) stopMomentum(state.momentum, "disabled");
158
+ syncDwellTracking(state.store);
159
+ }
160
+ function disconnectCaptureInput(surface, reason = "disconnected") {
161
+ const state = inputs.get(surface);
162
+ if (!state) return;
163
+ inputs.delete(surface);
164
+ state.wheel = void 0;
165
+ state.pointer = void 0;
166
+ state.pan = void 0;
167
+ surface.removeEventListener("wheel", onWheel);
168
+ removePointerListeners(surface);
169
+ if (state.session) finishSession(state.session, null, reason);
170
+ if (state.momentum) stopMomentum(state.momentum, reason);
171
+ const store = state.store;
172
+ store.dwell.delete(surface);
173
+ store.states.delete(state);
174
+ syncDwellTracking(store);
175
+ if (store.states.size) return;
176
+ store.view.removeEventListener("blur", onWindowBlur);
177
+ store.doc.removeEventListener("visibilitychange", onVisibilityChange);
178
+ if (documents.get(store.doc) === store) documents.delete(store.doc);
179
+ }
180
+ function removePointerListeners(surface) {
181
+ surface.removeEventListener("pointerdown", onPointerDown);
182
+ surface.removeEventListener("lostpointercapture", onLostCapture);
183
+ surface.removeEventListener("click", onClick, true);
184
+ surface.removeEventListener("dragstart", onDragStart);
185
+ }
186
+ function needsDwell(options) {
187
+ return options?.activation === "settled" || options?.activation === "settled-or-focus";
188
+ }
189
+ function syncDwellTracking(store) {
190
+ const tracking = Array.from(store.states).some((state) => needsDwell(state.wheel));
191
+ if (tracking === store.tracking) return;
192
+ store.tracking = tracking;
193
+ if (tracking) {
194
+ store.doc.addEventListener("pointermove", onDwellMove, { passive: true, capture: true });
195
+ store.doc.addEventListener("pointerout", onDwellOut, { passive: true, capture: true });
196
+ store.doc.addEventListener("wheel", onDwellWheel, { passive: true, capture: true });
197
+ } else {
198
+ store.doc.removeEventListener("pointermove", onDwellMove, true);
199
+ store.doc.removeEventListener("pointerout", onDwellOut, true);
200
+ store.doc.removeEventListener("wheel", onDwellWheel, true);
201
+ store.dwell.clear();
202
+ }
203
+ }
204
+ function onDwellMove(event) {
205
+ const store = documents.get(this);
206
+ if (!store || event.pointerType === "touch") return;
207
+ const path = event.composedPath();
208
+ for (const surface of store.dwell.keys()) {
209
+ if (!path.includes(surface) || event.buttons && !geometry(surface, event.clientX, event.clientY).inside) {
210
+ store.dwell.delete(surface);
211
+ }
212
+ }
213
+ for (const target of path) {
214
+ const state = inputs.get(target);
215
+ const options = state?.wheel;
216
+ if (!state || !options || !needsDwell(options)) continue;
217
+ let dwell = store.dwell.get(state.surface);
218
+ if (!dwell) {
219
+ if (event.buttons) continue;
220
+ store.dwell.set(state.surface, { x: event.clientX, y: event.clientY, time: event.timeStamp });
221
+ continue;
222
+ }
223
+ if (event.clientX === dwell.x && event.clientY === dwell.y) continue;
224
+ if (event.timeStamp - dwell.time >= options.delay && !options.resetOnMove) continue;
225
+ if (Math.abs(event.clientX - dwell.x) > options.tolerance || Math.abs(event.clientY - dwell.y) > options.tolerance) {
226
+ dwell = { x: event.clientX, y: event.clientY, time: event.timeStamp };
227
+ store.dwell.set(state.surface, dwell);
228
+ }
229
+ }
230
+ }
231
+ function onDwellOut(event) {
232
+ if (event.pointerType === "touch") return;
233
+ if (event.relatedTarget === null) documents.get(this)?.dwell.clear();
234
+ }
235
+ function onDwellWheel(event) {
236
+ const store = documents.get(this);
237
+ if (!store) return;
238
+ const path = event.composedPath();
239
+ for (const surface of store.dwell.keys()) if (!path.includes(surface)) store.dwell.delete(surface);
240
+ }
241
+ function matchesModifier(event, modifier) {
242
+ if (modifier === "any") return true;
243
+ if (modifier === "none") return !event.altKey && !event.ctrlKey && !event.metaKey && !event.shiftKey;
244
+ return event[`${modifier}Key`];
245
+ }
246
+ function ignoredTarget(surface, event, controls) {
247
+ const view = surface.ownerDocument.defaultView;
248
+ for (const target of event.composedPath()) {
249
+ if (target === surface) break;
250
+ if (target instanceof view.Element && (target.hasAttribute("data-capture-ignore") || controls && target.matches(controls))) return true;
251
+ }
252
+ return surface.hasAttribute("data-capture-ignore");
253
+ }
254
+ function allows(directions, delta, horizontal) {
255
+ return delta !== 0 && !!(directions & (horizontal ? delta < 0 ? 4 : 8 : delta < 0 ? 1 : 2));
256
+ }
257
+ function geometry(surface, x, y) {
258
+ const rect = surface.getBoundingClientRect();
259
+ return {
260
+ localX: x - rect.left,
261
+ localY: y - rect.top,
262
+ boxWidth: rect.width,
263
+ boxHeight: rect.height,
264
+ inside: x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom,
265
+ focusWithin: surface.matches(":focus-within")
266
+ };
267
+ }
268
+ function serializeMouse(event) {
269
+ return {
270
+ type: event.type,
271
+ timeStamp: event.timeStamp,
272
+ isTrusted: event.isTrusted,
273
+ cancelable: event.cancelable,
274
+ defaultPrevented: event.defaultPrevented,
275
+ altKey: event.altKey,
276
+ ctrlKey: event.ctrlKey,
277
+ metaKey: event.metaKey,
278
+ shiftKey: event.shiftKey,
279
+ button: event.button,
280
+ buttons: event.buttons,
281
+ clientX: event.clientX,
282
+ clientY: event.clientY,
283
+ pageX: event.pageX,
284
+ pageY: event.pageY,
285
+ screenX: event.screenX,
286
+ screenY: event.screenY,
287
+ offsetX: event.offsetX,
288
+ offsetY: event.offsetY
289
+ };
290
+ }
291
+ function serializePointer(event) {
292
+ return {
293
+ ...serializeMouse(event),
294
+ pointerId: event.pointerId,
295
+ pointerType: event.pointerType,
296
+ isPrimary: event.isPrimary,
297
+ width: event.width,
298
+ height: event.height,
299
+ pressure: event.pressure,
300
+ tangentialPressure: event.tangentialPressure,
301
+ tiltX: event.tiltX,
302
+ tiltY: event.tiltY,
303
+ twist: event.twist
304
+ };
305
+ }
306
+ function emit(state, type, detail) {
307
+ state.surface.dispatchEvent(new state.store.view.CustomEvent(type, { detail }));
308
+ }
309
+ function onWheel(event) {
310
+ const state = inputs.get(this);
311
+ const options = state?.wheel;
312
+ if (!state || !options || !options.directions || event.defaultPrevented || !event.cancelable || !matchesModifier(event, options.modifier)) return;
313
+ const deltaMode = event.deltaMode;
314
+ const deltaX = event.deltaX, deltaY = event.deltaY;
315
+ const horizontal = Math.abs(deltaX) > Math.abs(deltaY);
316
+ if (!allows(options.directions, horizontal ? deltaX : deltaY, horizontal)) return;
317
+ let activationReason;
318
+ if ((options.activation === "focus" || options.activation === "settled-or-focus") && this.matches(":focus-within")) activationReason = "focus";
319
+ else if (options.activation === "hover") activationReason = "immediate";
320
+ else {
321
+ const dwell = state.store.dwell.get(this);
322
+ if (!needsDwell(options) || !dwell || event.timeStamp - dwell.time < options.delay) return;
323
+ activationReason = "settled";
324
+ }
325
+ if (ignoredTarget(this, event, WHEEL_CONTROLS)) return;
326
+ const bounds = geometry(this, event.clientX, event.clientY);
327
+ if (!bounds.inside) return;
328
+ event.preventDefault();
329
+ if (!event.defaultPrevented) return;
330
+ event.stopPropagation();
331
+ const wheelEvent = { ...serializeMouse(event), deltaMode, deltaX, deltaY, deltaZ: event.deltaZ };
332
+ if (state.momentum) stopMomentum(state.momentum, "interrupted");
333
+ emit(state, "wheelinput", { wheelEvent, ...bounds, activationReason });
334
+ }
335
+ function point(event) {
336
+ return { x: event.clientX, y: event.clientY, time: event.timeStamp };
337
+ }
338
+ function onPointerDown(event) {
339
+ const state = inputs.get(this);
340
+ if (!state) return;
341
+ state.suppressClickUntil = void 0;
342
+ if (state.momentum) stopMomentum(state.momentum, "interrupted");
343
+ if (event.defaultPrevented || !event.isPrimary || state.session || state.store.sessions.has(event.pointerId)) return;
344
+ const type = POINTER_TYPES[event.pointerType] ?? 0;
345
+ const options = state.pointer;
346
+ const pointer = !!options && !!(options.types & type) && !!(options.buttons & 1 << event.button) && matchesModifier(event, options.modifier) && !ignoredTarget(this, event, options.interactive ? "" : INTERACTIVE);
347
+ const pan = !!state.pan && !!(state.pan.types & type) && event.button === 0 && state.pan.directions !== 0 && !ignoredTarget(this, event, INTERACTIVE);
348
+ if (!pointer && !pan) return;
349
+ const snapshot = serializePointer(event);
350
+ const origin = point(snapshot);
351
+ const session = {
352
+ state,
353
+ id: event.pointerId,
354
+ start: { pointerEvent: snapshot, ...geometry(this, event.clientX, event.clientY) },
355
+ current: snapshot,
356
+ pointer,
357
+ pan,
358
+ pointerStarted: false,
359
+ panStarted: false,
360
+ captured: false,
361
+ pointerReason: options?.threshold ? "drag-threshold" : "pointer-down",
362
+ panReason: state.pan?.threshold ? "drag-threshold" : "pointer-down",
363
+ pointerLast: origin,
364
+ panLast: origin,
365
+ samples: pan ? [origin] : [],
366
+ lastMoveTime: event.timeStamp
367
+ };
368
+ state.session = session;
369
+ state.store.sessions.set(session.id, session);
370
+ syncSessionListeners(state.store);
371
+ updateSession(session, event, true);
372
+ }
373
+ function syncSessionListeners(store) {
374
+ const listening = store.sessions.size > 0;
375
+ if (listening === store.listening) return;
376
+ store.listening = listening;
377
+ if (listening) {
378
+ store.doc.addEventListener("pointermove", onSessionMove, { capture: true, passive: false });
379
+ store.doc.addEventListener("pointerup", onSessionUp, { capture: true, passive: false });
380
+ store.doc.addEventListener("pointercancel", onSessionCancel, true);
381
+ } else {
382
+ store.doc.removeEventListener("pointermove", onSessionMove, true);
383
+ store.doc.removeEventListener("pointerup", onSessionUp, true);
384
+ store.doc.removeEventListener("pointercancel", onSessionCancel, true);
385
+ }
386
+ }
387
+ function onSessionMove(event) {
388
+ const session = documents.get(this)?.sessions.get(event.pointerId);
389
+ if (session) updateSession(session, event);
390
+ }
391
+ function onSessionUp(event) {
392
+ const session = documents.get(this)?.sessions.get(event.pointerId);
393
+ if (session) finishSession(session, event);
394
+ }
395
+ function onSessionCancel(event) {
396
+ const session = documents.get(this)?.sessions.get(event.pointerId);
397
+ if (session) finishSession(session, event, "pointer-cancel");
398
+ }
399
+ function onLostCapture(event) {
400
+ const session = inputs.get(this)?.session;
401
+ if (session?.id === event.pointerId && session.captured) finishSession(session, event, "lost-capture");
402
+ }
403
+ function consumePointer(event) {
404
+ if (event.cancelable) event.preventDefault();
405
+ }
406
+ function recordSample(session, event) {
407
+ if (!session.pan) return;
408
+ const last = session.samples.at(-1);
409
+ if (!last || last.x !== event.clientX || last.y !== event.clientY) session.lastMoveTime = event.timeStamp;
410
+ session.samples.push(point(event));
411
+ while (session.samples.length > 8 || session.samples.length > 2 && event.timeStamp - session.samples[0].time > 100) session.samples.shift();
412
+ }
413
+ function velocity(session, time) {
414
+ if (time - session.lastMoveTime > 80) return { x: 0, y: 0 };
415
+ const last = session.samples.at(-1);
416
+ const first = session.samples.find((sample) => last && last.time - sample.time <= 100);
417
+ const dt = last && first ? last.time - first.time : 0;
418
+ return dt > 0 && first && last ? { x: (first.x - last.x) / dt, y: (first.y - last.y) / dt } : { x: 0, y: 0 };
419
+ }
420
+ function panDelta(options, x, y) {
421
+ return {
422
+ x: options.axis !== "y" && allows(options.directions, x, true) ? x : 0,
423
+ y: options.axis !== "x" && allows(options.directions, y, false) ? y : 0
424
+ };
425
+ }
426
+ function updateSession(session, event, down = false) {
427
+ const state = session.state;
428
+ const x = event.clientX - session.start.pointerEvent.clientX;
429
+ const y = event.clientY - session.start.pointerEvent.clientY;
430
+ const distance = Math.hypot(x, y);
431
+ const pointerStarts = session.pointer && !session.pointerStarted && !!state.pointer && distance >= state.pointer.threshold;
432
+ const panDistance = state.pan?.axis === "x" ? Math.abs(x) : state.pan?.axis === "y" ? Math.abs(y) : distance;
433
+ const panStarts = session.pan && !session.panStarted && !!state.pan && panDistance >= state.pan.threshold;
434
+ if (pointerStarts || panStarts || session.captured) {
435
+ if (!session.captured) {
436
+ try {
437
+ state.surface.setPointerCapture(session.id);
438
+ } catch {
439
+ finishSession(session, event, "lost-capture");
440
+ return;
441
+ }
442
+ session.captured = true;
443
+ }
444
+ consumePointer(event);
445
+ }
446
+ session.current = serializePointer(event);
447
+ if (down) session.start.pointerEvent = session.current;
448
+ if (!down) recordSample(session, event);
449
+ if (pointerStarts) {
450
+ session.pointerStarted = true;
451
+ emitPointer(session, "start", session.start.pointerEvent);
452
+ if (state.session !== session) return;
453
+ }
454
+ if (panStarts) {
455
+ session.panStarted = true;
456
+ emitPan(session, "start", session.start.pointerEvent);
457
+ if (state.session !== session) return;
458
+ }
459
+ if (down) return;
460
+ if (session.pointerStarted) {
461
+ emitPointer(session, "move", session.current);
462
+ if (state.session !== session) return;
463
+ }
464
+ if (session.panStarted && state.pan) {
465
+ const delta = panDelta(state.pan, session.panLast.x - event.clientX, session.panLast.y - event.clientY);
466
+ const v = velocity(session, event.timeStamp);
467
+ const speed = panDelta(state.pan, v.x, v.y);
468
+ session.panLast = point(event);
469
+ emitPan(session, "move", session.current, { deltaX: delta.x, deltaY: delta.y, velocityX: speed.x, velocityY: speed.y });
470
+ }
471
+ }
472
+ function emitPointer(session, phase, event, cancelReason) {
473
+ const current = event ?? session.current;
474
+ const start = session.start.pointerEvent;
475
+ const first = phase === "start";
476
+ const deltaX = first ? 0 : current.clientX - session.pointerLast.x;
477
+ const deltaY = first ? 0 : current.clientY - session.pointerLast.y;
478
+ session.pointerLast = point(current);
479
+ emit(session.state, "pointerinput", {
480
+ phase,
481
+ pointerEvent: event ? { ...event } : null,
482
+ start: snapshotStart(session),
483
+ ...geometry(session.state.surface, current.clientX, current.clientY),
484
+ deltaX,
485
+ deltaY,
486
+ movementX: current.clientX - start.clientX,
487
+ movementY: current.clientY - start.clientY,
488
+ activationReason: session.pointerReason,
489
+ ...cancelReason ? { cancelReason } : {}
490
+ });
491
+ }
492
+ function emitPan(session, phase, event, motion) {
493
+ const current = event ?? session.current;
494
+ emit(session.state, "paninput", {
495
+ phase,
496
+ pointerEvent: event ? { ...event } : null,
497
+ start: snapshotStart(session),
498
+ ...geometry(session.state.surface, current.clientX, current.clientY),
499
+ deltaX: 0,
500
+ deltaY: 0,
501
+ velocityX: 0,
502
+ velocityY: 0,
503
+ activationReason: session.panReason,
504
+ ...motion
505
+ });
506
+ }
507
+ function snapshotStart(session) {
508
+ return { ...session.start, pointerEvent: { ...session.start.pointerEvent } };
509
+ }
510
+ function finishSession(session, event, reason) {
511
+ const state = session.state;
512
+ if (state.session !== session) return;
513
+ state.session = void 0;
514
+ state.store.sessions.delete(session.id);
515
+ syncSessionListeners(state.store);
516
+ if (event) {
517
+ if (session.captured && !reason) consumePointer(event);
518
+ recordSample(session, event);
519
+ session.current = serializePointer(event);
520
+ }
521
+ if (state.surface.hasPointerCapture(session.id)) state.surface.releasePointerCapture(session.id);
522
+ if (session.captured) state.suppressClickUntil = state.store.view.performance.now() + 400;
523
+ if (session.pointerStarted) emitPointer(session, reason ? "cancel" : "end", event ? session.current : null, reason);
524
+ if (!session.panStarted) return;
525
+ if (reason || inputs.get(state.surface) !== state || !state.pan) {
526
+ emitPan(session, "cancel", event ? session.current : null, { cancelReason: reason ?? "disabled" });
527
+ return;
528
+ }
529
+ const finalDelta = panDelta(state.pan, session.panLast.x - session.current.clientX, session.panLast.y - session.current.clientY);
530
+ const v = velocity(session, session.current.timeStamp);
531
+ const speed = panDelta(state.pan, v.x, v.y);
532
+ emitPan(session, "release", session.current, { deltaX: finalDelta.x, deltaY: finalDelta.y, velocityX: speed.x, velocityY: speed.y });
533
+ const options = state.pan;
534
+ if (inputs.get(state.surface) !== state || !options || state.session) {
535
+ emitPan(session, "cancel", null, { cancelReason: "disabled" });
536
+ return;
537
+ }
538
+ if (options.inertia && (Math.abs(speed.x) >= options.minVelocity || Math.abs(speed.y) >= options.minVelocity)) {
539
+ const momentum = { state, session, vx: speed.x, vy: speed.y, time: state.store.view.performance.now() };
540
+ state.momentum = momentum;
541
+ state.store.momenta.add(momentum);
542
+ scheduleMomentum(state.store);
543
+ } else emitPan(session, "end", session.current);
544
+ }
545
+ function scheduleMomentum(store) {
546
+ if (store.frame !== void 0 || !store.momenta.size) return;
547
+ store.animate ??= (time) => advanceMomentum(store, time);
548
+ store.frame = store.view.requestAnimationFrame(store.animate);
549
+ }
550
+ function advanceMomentum(store, time) {
551
+ store.frame = void 0;
552
+ for (const motion of Array.from(store.momenta)) {
553
+ const options = motion.state.pan;
554
+ if (!options?.inertia || !motion.state.surface.isConnected) {
555
+ stopMomentum(motion, "disabled");
556
+ continue;
557
+ }
558
+ const dt = Math.min(50, Math.max(0, time - motion.time));
559
+ motion.time = time;
560
+ const decay = Math.exp(-dt / options.tau);
561
+ const delta = panDelta(options, motion.vx * options.tau * (1 - decay), motion.vy * options.tau * (1 - decay));
562
+ const speed = panDelta(options, motion.vx * decay, motion.vy * decay);
563
+ motion.vx = speed.x;
564
+ motion.vy = speed.y;
565
+ if (delta.x || delta.y) emitPan(motion.session, "inertia", null, { deltaX: delta.x, deltaY: delta.y, velocityX: speed.x, velocityY: speed.y });
566
+ if (!store.momenta.has(motion)) continue;
567
+ if (Math.abs(speed.x) < options.minVelocity && Math.abs(speed.y) < options.minVelocity) stopMomentum(motion);
568
+ }
569
+ scheduleMomentum(store);
570
+ }
571
+ function stopMomentum(motion, reason) {
572
+ const state = motion.state;
573
+ if (state.momentum !== motion) return;
574
+ state.momentum = void 0;
575
+ state.store.momenta.delete(motion);
576
+ if (!state.store.momenta.size && state.store.frame !== void 0) {
577
+ state.store.view.cancelAnimationFrame(state.store.frame);
578
+ state.store.frame = void 0;
579
+ }
580
+ emitPan(motion.session, reason ? "cancel" : "end", null, reason ? { cancelReason: reason } : void 0);
581
+ }
582
+ function onClick(event) {
583
+ const state = inputs.get(this);
584
+ if (!state?.suppressClickUntil || event.detail === 0 || state.store.view.performance.now() > state.suppressClickUntil) return;
585
+ state.suppressClickUntil = void 0;
586
+ event.preventDefault();
587
+ event.stopPropagation();
588
+ }
589
+ function onDragStart(event) {
590
+ if (inputs.get(this)?.session) event.preventDefault();
591
+ }
592
+ function cancelStore(store) {
593
+ store.dwell.clear();
594
+ for (const session of Array.from(store.sessions.values())) finishSession(session, null, "blur");
595
+ for (const motion of Array.from(store.momenta)) stopMomentum(motion, "blur");
596
+ }
597
+ function onWindowBlur() {
598
+ const store = documents.get(this.document);
599
+ if (store) cancelStore(store);
600
+ }
601
+ function onVisibilityChange() {
602
+ const store = documents.get(this);
603
+ if (store && this.hidden) cancelStore(store);
604
+ }
605
+ export {
606
+ CAPTURE_INPUT_ATTRIBUTES,
607
+ disconnectCaptureInput,
608
+ syncCaptureInput
609
+ };
@@ -18,6 +18,7 @@ export { AProgressElement, register_a_progress } from './a-progress';
18
18
  export { ALoaderElement, register_a_loader } from './a-loader';
19
19
  export { ATextElement, register_a_text } from './a-text';
20
20
  export { ABoxElement, register_a_box } from './a-box';
21
+ export { ACaptureElement, register_a_capture } from './a-capture';
21
22
  export { AIconElement, register_a_icon } from './a-icon';
22
23
  export { AButtonElement, register_a_button } from './a-button';
23
24
  export { ACopyElement, register_a_copy } from './a-copy';
@@ -3,6 +3,7 @@ import { AProgressElement, register_a_progress } from "./a-progress";
3
3
  import { ALoaderElement, register_a_loader } from "./a-loader";
4
4
  import { ATextElement, register_a_text } from "./a-text";
5
5
  import { ABoxElement, register_a_box } from "./a-box";
6
+ import { ACaptureElement, register_a_capture } from "./a-capture";
6
7
  import { AIconElement, register_a_icon } from "./a-icon";
7
8
  import { AButtonElement, register_a_button } from "./a-button";
8
9
  import { ACopyElement, register_a_copy } from "./a-copy";
@@ -36,6 +37,7 @@ export {
36
37
  ABoxElement,
37
38
  AButtonElement,
38
39
  ACalendarElement,
40
+ ACaptureElement,
39
41
  ACardElement,
40
42
  ACheckboxElement,
41
43
  ACopyElement,
@@ -66,6 +68,7 @@ export {
66
68
  register_a_box,
67
69
  register_a_button,
68
70
  register_a_calendar,
71
+ register_a_capture,
69
72
  register_a_card,
70
73
  register_a_checkbox,
71
74
  register_a_copy,