@joewinke/jatui 0.2.11 → 0.2.13

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 (53) hide show
  1. package/dist/actions/attention.js +21 -13
  2. package/dist/actions/collapse.js +15 -29
  3. package/dist/actions/floating.js +29 -37
  4. package/dist/actions/listNav.js +108 -137
  5. package/dist/actions/railNav.js +72 -89
  6. package/dist/actions/staggerEntrance.js +19 -23
  7. package/dist/actions/tooltip.js +63 -51
  8. package/dist/assets/sounds/error.js +1 -1
  9. package/dist/assets/sounds/notify.js +1 -1
  10. package/dist/assets/sounds/pop.js +1 -1
  11. package/dist/assets/sounds/send.js +1 -1
  12. package/dist/assets/sounds/success.js +1 -1
  13. package/dist/assets/sounds/toggle.js +1 -1
  14. package/dist/components/graph/theme.js +26 -36
  15. package/dist/components/markup.js +59 -62
  16. package/dist/components/session-nav/transcriptModel.js +49 -66
  17. package/dist/components/shell/shell.js +14 -15
  18. package/dist/components/table/flexRender.js +2 -2
  19. package/dist/data/emojis.js +4 -4
  20. package/dist/dnd/autoScroll.js +10 -12
  21. package/dist/dnd/createDndBoard.js +104 -184
  22. package/dist/dnd/draggable.js +15 -23
  23. package/dist/dnd/dropTarget.js +15 -29
  24. package/dist/dnd/types.d.ts +9 -0
  25. package/dist/dnd/types.js +2 -14
  26. package/dist/showcase/generative/intent.js +19 -21
  27. package/dist/showcase/generative/manifest.js +27 -80
  28. package/dist/showcase/scroll/scrollProgress.js +20 -22
  29. package/dist/showcase/scroll/scrollReveal.js +17 -20
  30. package/dist/stores/commandPalette.js +18 -46
  31. package/dist/stores/confirmDialog.js +9 -9
  32. package/dist/stores/inputDialog.js +9 -9
  33. package/dist/stores/toast.js +10 -33
  34. package/dist/transitions/glide.js +29 -25
  35. package/dist/types/booking.js +4 -4
  36. package/dist/types/comments.js +2 -2
  37. package/dist/types/messaging.js +3 -3
  38. package/dist/types/pipeline.js +2 -2
  39. package/dist/utils/currency.js +2 -4
  40. package/dist/utils/daisyuiColors.js +25 -27
  41. package/dist/utils/dateFormatters.js +44 -44
  42. package/dist/utils/googleMapsLoader.js +46 -100
  43. package/dist/utils/mentionParser.js +30 -30
  44. package/dist/utils/phone.js +21 -27
  45. package/dist/utils/phoneFormat.js +9 -9
  46. package/dist/utils/sound.js +27 -78
  47. package/dist/utils/splitText.js +15 -26
  48. package/dist/utils/taskUtils.js +1 -1
  49. package/dist/utils/themeWipe.js +27 -72
  50. package/dist/utils/viewTransition.js +6 -51
  51. package/package.json +7 -3
  52. package/dist/dnd/createDndBoard.test.d.ts +0 -1
  53. package/dist/dnd/createDndBoard.test.js +0 -261
@@ -60,17 +60,6 @@
60
60
  * 3. Handle Left/Right in `onAction` and call `rail.bump(host)` on change:
61
61
  * onAction: (id, dir, host) => { formData[id] = cycle(opts[id], …, dir); rail.bump(host); }
62
62
  */
63
- var __assign = (this && this.__assign) || function () {
64
- __assign = Object.assign || function(t) {
65
- for (var s, i = 1, n = arguments.length; i < n; i++) {
66
- s = arguments[i];
67
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
68
- t[p] = s[p];
69
- }
70
- return t;
71
- };
72
- return __assign.apply(this, arguments);
73
- };
74
63
  // ─── Exported helpers ──────────────────────────────────────────────────────────
75
64
  /**
76
65
  * Cycle through `list`, returning the item `dir` steps from `current`.
@@ -84,40 +73,39 @@ var __assign = (this && this.__assign) || function () {
84
73
  export function cycle(list, current, dir) {
85
74
  if (list.length === 0)
86
75
  return current;
87
- var i = list.indexOf(current);
76
+ const i = list.indexOf(current);
88
77
  // When `current` is not in the list, treat it as if we're at position -1
89
78
  // so that `dir=1` lands at index 0 (the first item) and `dir=-1` lands at
90
79
  // the last item — matching the "not found → start from the beginning" idiom.
91
- var base = i === -1 ? -1 : i;
80
+ const base = i === -1 ? -1 : i;
92
81
  return list[(((base + dir) % list.length) + list.length) % list.length];
93
82
  }
94
83
  // ─── Internals ─────────────────────────────────────────────────────────────────
95
- var BUMP_DURATION_MS = 280;
96
- var RAIL_FOCUS_CLASS = 'rail-focus';
97
- var RAIL_CYCLED_CLASS = 'rail-cycled';
84
+ const BUMP_DURATION_MS = 280;
85
+ const RAIL_FOCUS_CLASS = 'rail-focus';
86
+ const RAIL_CYCLED_CLASS = 'rail-cycled';
98
87
  function resolveOrder(opts) {
99
88
  return typeof opts.order === 'function' ? opts.order() : opts.order;
100
89
  }
101
90
  function resolveAttr(opts) {
102
- var _a;
103
- return (_a = opts.attr) !== null && _a !== void 0 ? _a : 'data-rail-id';
91
+ return opts.attr ?? 'data-rail-id';
104
92
  }
105
93
  /** Return all currently-rendered rung hosts in the rail order. */
106
94
  function resolveHosts(optsRef) {
107
- var container = optsRef.current.container;
95
+ const { container } = optsRef.current;
108
96
  if (!container)
109
97
  return [];
110
- var attr = resolveAttr(optsRef.current);
111
- var order = resolveOrder(optsRef.current);
98
+ const attr = resolveAttr(optsRef.current);
99
+ const order = resolveOrder(optsRef.current);
112
100
  return order
113
- .map(function (id) { return container.querySelector("[".concat(attr, "=\"").concat(id, "\"]")); })
101
+ .map((id) => container.querySelector(`[${attr}="${id}"]`))
114
102
  // checkVisibility() correctly returns false for elements inside a closed <details>
115
103
  // (browsers keep offsetParent non-null for those, so that check alone is insufficient).
116
104
  // Where checkVisibility is unavailable (jsdom, older engines) treat the rung as
117
105
  // visible — a rendered element in `order` is navigable by default; only the
118
106
  // closed-<details> case needs the extra exclusion, and that only exists in a
119
107
  // real layout engine.
120
- .filter(function (el) { var _a, _b; return !!el && ((_b = (_a = el.checkVisibility) === null || _a === void 0 ? void 0 : _a.call(el)) !== null && _b !== void 0 ? _b : true); });
108
+ .filter((el) => !!el && (el.checkVisibility?.() ?? true));
121
109
  }
122
110
  /**
123
111
  * Focus the most appropriate control inside a rung host:
@@ -132,17 +120,17 @@ function resolveHosts(optsRef) {
132
120
  * 4. Last resort: focus the host itself (requires tabindex on the host).
133
121
  */
134
122
  function focusRailHost(host) {
135
- var _a;
136
123
  if (host.matches('input,select,textarea,button,[contenteditable="true"],[tabindex]')) {
137
124
  host.focus();
138
125
  return;
139
126
  }
140
- var inner = (_a = host.querySelector('[contenteditable="true"],input,select,textarea')) !== null && _a !== void 0 ? _a : host.querySelector('.sd-trigger,button');
141
- (inner !== null && inner !== void 0 ? inner : host).focus();
127
+ const inner = host.querySelector('[contenteditable="true"],input,select,textarea') ??
128
+ host.querySelector('.sd-trigger,button');
129
+ (inner ?? host).focus();
142
130
  }
143
131
  function makeController(optsRef) {
144
- var _currentRailId = '';
145
- var _lastFocusedHost = null;
132
+ let _currentRailId = '';
133
+ let _lastFocusedHost = null;
146
134
  function applyFocusClass(host) {
147
135
  if (_lastFocusedHost && _lastFocusedHost !== host) {
148
136
  _lastFocusedHost.classList.remove(RAIL_FOCUS_CLASS);
@@ -157,14 +145,14 @@ function makeController(optsRef) {
157
145
  host.classList.remove(RAIL_CYCLED_CLASS);
158
146
  void host.offsetWidth; // reflow so the animation restarts on rapid presses
159
147
  host.classList.add(RAIL_CYCLED_CLASS);
160
- setTimeout(function () { return host.classList.remove(RAIL_CYCLED_CLASS); }, BUMP_DURATION_MS);
148
+ setTimeout(() => host.classList.remove(RAIL_CYCLED_CLASS), BUMP_DURATION_MS);
161
149
  }
162
150
  function focus(id) {
163
- var container = optsRef.current.container;
151
+ const { container } = optsRef.current;
164
152
  if (!container)
165
153
  return;
166
- var attr = resolveAttr(optsRef.current);
167
- var host = container.querySelector("[".concat(attr, "=\"").concat(id, "\"]"));
154
+ const attr = resolveAttr(optsRef.current);
155
+ const host = container.querySelector(`[${attr}="${id}"]`);
168
156
  if (host) {
169
157
  focusRailHost(host);
170
158
  applyFocusClass(host);
@@ -175,21 +163,20 @@ function makeController(optsRef) {
175
163
  }
176
164
  }
177
165
  function moveRung(dir) {
178
- var _a;
179
- var hosts = resolveHosts(optsRef);
166
+ const hosts = resolveHosts(optsRef);
180
167
  if (hosts.length === 0)
181
168
  return;
182
- var attr = resolveAttr(optsRef.current);
183
- var ids = hosts.map(function (h) { return h.getAttribute(attr); });
169
+ const attr = resolveAttr(optsRef.current);
170
+ const ids = hosts.map((h) => h.getAttribute(attr));
184
171
  // Anchor on the actually-focused rung first. Fall back to the last tracked
185
172
  // rung (covers focus parked on the container after an Escape pop-out).
186
- var active = document.activeElement;
187
- var activeFocused = (_a = (active === null || active === void 0 ? void 0 : active.closest("[".concat(attr, "]")))) === null || _a === void 0 ? void 0 : _a.getAttribute(attr);
188
- var fromId = activeFocused && ids.includes(activeFocused) ? activeFocused : _currentRailId;
189
- var pos = fromId ? ids.indexOf(fromId) : -1;
173
+ const active = document.activeElement;
174
+ const activeFocused = (active?.closest(`[${attr}]`))?.getAttribute(attr);
175
+ const fromId = activeFocused && ids.includes(activeFocused) ? activeFocused : _currentRailId;
176
+ let pos = fromId ? ids.indexOf(fromId) : -1;
190
177
  if (pos === -1)
191
178
  pos = dir === 1 ? -1 : hosts.length;
192
- var next = (((pos + dir) % hosts.length) + hosts.length) % hosts.length;
179
+ const next = (((pos + dir) % hosts.length) + hosts.length) % hosts.length;
193
180
  focusRailHost(hosts[next]);
194
181
  applyFocusClass(hosts[next]);
195
182
  _currentRailId = ids[next];
@@ -197,10 +184,9 @@ function makeController(optsRef) {
197
184
  function refresh() {
198
185
  // Re-derive hosts; re-apply focus class if the current rung is still rendered
199
186
  // (DOM may have been reconstructed by Svelte's reactive updates).
200
- var hosts = resolveHosts(optsRef);
201
- var attr = resolveAttr(optsRef.current);
202
- for (var _i = 0, hosts_1 = hosts; _i < hosts_1.length; _i++) {
203
- var h = hosts_1[_i];
187
+ const hosts = resolveHosts(optsRef);
188
+ const attr = resolveAttr(optsRef.current);
189
+ for (const h of hosts) {
204
190
  if (h.getAttribute(attr) === _currentRailId) {
205
191
  applyFocusClass(h);
206
192
  return;
@@ -208,11 +194,10 @@ function makeController(optsRef) {
208
194
  }
209
195
  }
210
196
  function handleFocusin(event) {
211
- var _a;
212
- var attr = resolveAttr(optsRef.current);
213
- var order = resolveOrder(optsRef.current);
214
- var host = (_a = event.target) === null || _a === void 0 ? void 0 : _a.closest("[".concat(attr, "]"));
215
- var id = host === null || host === void 0 ? void 0 : host.getAttribute(attr);
197
+ const attr = resolveAttr(optsRef.current);
198
+ const order = resolveOrder(optsRef.current);
199
+ const host = event.target?.closest(`[${attr}]`);
200
+ const id = host?.getAttribute(attr);
216
201
  // Only track rungs that are in the rail order. Tabbing into an off-rail
217
202
  // control (e.g. a description textarea) leaves the last real rung intact
218
203
  // so Up / Down can resume from it after the user tabs back out.
@@ -222,18 +207,17 @@ function makeController(optsRef) {
222
207
  }
223
208
  }
224
209
  function handleKeydown(event) {
225
- var _a, _b, _c, _d, _e, _f, _g, _h;
226
- var opts = optsRef.current;
227
- var el = document.activeElement;
228
- var tag = el === null || el === void 0 ? void 0 : el.tagName;
229
- var isTextField = !!el &&
210
+ const opts = optsRef.current;
211
+ const el = document.activeElement;
212
+ const tag = el?.tagName;
213
+ const isTextField = !!el &&
230
214
  (tag === 'INPUT' || tag === 'TEXTAREA' || el.isContentEditable === true);
231
- var isMultiline = !!el && (tag === 'TEXTAREA' || el.isContentEditable === true);
232
- var hasMod = event.metaKey || event.ctrlKey || event.altKey;
215
+ const isMultiline = !!el && (tag === 'TEXTAREA' || el.isContentEditable === true);
216
+ const hasMod = event.metaKey || event.ctrlKey || event.altKey;
233
217
  // Modal trap — stop non-text keystrokes from bubbling to window-level page
234
218
  // listeners (e.g., a listNav attached to `window`). Text-field keystrokes
235
219
  // propagate normally so typing in the drawer doesn't interfere.
236
- var trap = opts.trap !== false;
220
+ const trap = opts.trap !== false;
237
221
  if (trap && !isTextField)
238
222
  event.stopPropagation();
239
223
  // Escape cascade:
@@ -241,33 +225,33 @@ function makeController(optsRef) {
241
225
  // 2. focus inside a descendant control → pop back to container
242
226
  // 3. focus already on the container (or just popped) → call onEscape
243
227
  if (event.key === 'Escape' && !hasMod) {
244
- var popoverOpen_1 = (_b = (_a = opts.isPopoverOpen) === null || _a === void 0 ? void 0 : _a.call(opts)) !== null && _b !== void 0 ? _b : false;
245
- if (popoverOpen_1) {
228
+ const popoverOpen = opts.isPopoverOpen?.() ?? false;
229
+ if (popoverOpen) {
246
230
  event.preventDefault();
247
- (_c = opts.onPopoverEscape) === null || _c === void 0 ? void 0 : _c.call(opts);
231
+ opts.onPopoverEscape?.();
248
232
  return true;
249
233
  }
250
- var container = opts.container;
234
+ const { container } = opts;
251
235
  if (container && el && el !== container && container.contains(el)) {
252
236
  event.preventDefault();
253
237
  container.focus();
254
238
  return true;
255
239
  }
256
240
  event.preventDefault();
257
- (_d = opts.onEscape) === null || _d === void 0 ? void 0 : _d.call(opts);
241
+ opts.onEscape?.();
258
242
  return true;
259
243
  }
260
244
  // Rail motion — suppressed when a popover is open or a modifier is held.
261
- var popoverOpen = (_f = (_e = opts.isPopoverOpen) === null || _e === void 0 ? void 0 : _e.call(opts)) !== null && _f !== void 0 ? _f : false;
245
+ const popoverOpen = opts.isPopoverOpen?.() ?? false;
262
246
  if (!hasMod && !popoverOpen) {
263
247
  // Vertical: ArrowDown / j step down; ArrowUp / k step up.
264
248
  // j / k are blocked in ANY text field; arrows are blocked only inside
265
249
  // multiline fields so the caret can still move line-by-line.
266
- var goDown = event.key === 'ArrowDown' || event.key === 'j';
267
- var goUp = event.key === 'ArrowUp' || event.key === 'k';
250
+ const goDown = event.key === 'ArrowDown' || event.key === 'j';
251
+ const goUp = event.key === 'ArrowUp' || event.key === 'k';
268
252
  if (goDown || goUp) {
269
- var isVimKey = event.key === 'j' || event.key === 'k';
270
- var blocked = isVimKey ? isTextField : isMultiline;
253
+ const isVimKey = event.key === 'j' || event.key === 'k';
254
+ const blocked = isVimKey ? isTextField : isMultiline;
271
255
  if (!blocked) {
272
256
  event.preventDefault();
273
257
  moveRung(goDown ? 1 : -1);
@@ -279,14 +263,15 @@ function makeController(optsRef) {
279
263
  if ((event.key === 'ArrowLeft' || event.key === 'ArrowRight') &&
280
264
  !isTextField) {
281
265
  event.preventDefault();
282
- var attr = resolveAttr(opts);
266
+ const attr = resolveAttr(opts);
283
267
  // Prefer the element that actually has DOM focus, then fall back to
284
268
  // the last tracked rung (focus parked on the container after pop-out).
285
- var focusedHost = (_g = (el === null || el === void 0 ? void 0 : el.closest("[".concat(attr, "]")))) !== null && _g !== void 0 ? _g : (opts.container && _currentRailId
286
- ? opts.container.querySelector("[".concat(attr, "=\"").concat(_currentRailId, "\"]"))
287
- : null);
269
+ const focusedHost = (el?.closest(`[${attr}]`)) ??
270
+ (opts.container && _currentRailId
271
+ ? opts.container.querySelector(`[${attr}="${_currentRailId}"]`)
272
+ : null);
288
273
  if (focusedHost && opts.onAction) {
289
- var rungId = (_h = focusedHost.getAttribute(attr)) !== null && _h !== void 0 ? _h : '';
274
+ const rungId = focusedHost.getAttribute(attr) ?? '';
290
275
  opts.onAction(rungId, event.key === 'ArrowRight' ? 1 : -1, focusedHost);
291
276
  }
292
277
  return true;
@@ -295,13 +280,13 @@ function makeController(optsRef) {
295
280
  return false;
296
281
  }
297
282
  return {
298
- handleKeydown: handleKeydown,
299
- handleFocusin: handleFocusin,
300
- moveRung: moveRung,
301
- focus: focus,
302
- refresh: refresh,
303
- currentId: function () { return _currentRailId; },
304
- bump: bump,
283
+ handleKeydown,
284
+ handleFocusin,
285
+ moveRung,
286
+ focus,
287
+ refresh,
288
+ currentId: () => _currentRailId,
289
+ bump,
305
290
  };
306
291
  }
307
292
  // ─── Composable ────────────────────────────────────────────────────────────────
@@ -316,7 +301,7 @@ function makeController(optsRef) {
316
301
  * panel.addEventListener('focusin', (e) => rail.handleFocusin(e));
317
302
  */
318
303
  export function createRailNav(options) {
319
- var ref = { current: options };
304
+ const ref = { current: options };
320
305
  return makeController(ref);
321
306
  }
322
307
  // ─── Action ────────────────────────────────────────────────────────────────────
@@ -331,10 +316,9 @@ export function createRailNav(options) {
331
316
  * <div data-rail-id="priority" tabindex="-1">…</div>
332
317
  * </div>
333
318
  */
334
- export var railNav = function (node, initial) {
335
- if (initial === void 0) { initial = { order: [] }; }
336
- var ref = { current: __assign(__assign({}, initial), { container: node }) };
337
- var controller = makeController(ref);
319
+ export const railNav = (node, initial = { order: [] }) => {
320
+ const ref = { current: { ...initial, container: node } };
321
+ const controller = makeController(ref);
338
322
  function onKeydown(e) {
339
323
  controller.handleKeydown(e);
340
324
  }
@@ -344,12 +328,11 @@ export var railNav = function (node, initial) {
344
328
  node.addEventListener('keydown', onKeydown);
345
329
  node.addEventListener('focusin', onFocusin);
346
330
  return {
347
- update: function (next) {
348
- if (next === void 0) { next = { order: [] }; }
349
- ref.current = __assign(__assign({}, next), { container: node });
331
+ update(next = { order: [] }) {
332
+ ref.current = { ...next, container: node };
350
333
  controller.refresh();
351
334
  },
352
- destroy: function () {
335
+ destroy() {
353
336
  node.removeEventListener('keydown', onKeydown);
354
337
  node.removeEventListener('focusin', onFocusin);
355
338
  },
@@ -15,53 +15,49 @@
15
15
  * {/each}
16
16
  * </ul>
17
17
  */
18
- export function staggerEntrance(node, options) {
19
- if (options === void 0) { options = {}; }
20
- var _a = options.stepMs, stepMs = _a === void 0 ? 35 : _a, _b = options.maxTotalMs, maxTotalMs = _b === void 0 ? 250 : _b, _c = options.rise, rise = _c === void 0 ? 8 : _c;
21
- var prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
22
- var children = Array.from(node.children);
18
+ export function staggerEntrance(node, options = {}) {
19
+ const { stepMs = 35, maxTotalMs = 250, rise = 8 } = options;
20
+ const prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
21
+ const children = Array.from(node.children);
23
22
  if (prefersReduced || children.length === 0) {
24
23
  // Render final state immediately — no animation
25
- return { destroy: function () { } };
24
+ return { destroy() { } };
26
25
  }
27
26
  // Cap the per-item step so total time doesn't exceed maxTotalMs
28
- var effectiveStep = children.length > 1
27
+ const effectiveStep = children.length > 1
29
28
  ? Math.min(stepMs, Math.floor(maxTotalMs / (children.length - 1)))
30
29
  : stepMs;
31
- var duration = 200; // var(--motion-enter) = 200ms
30
+ const duration = 200; // var(--motion-enter) = 200ms
32
31
  // Set all children to their start state (opacity 0, risen)
33
- for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
34
- var child = children_1[_i];
32
+ for (const child of children) {
35
33
  child.style.opacity = '0';
36
- child.style.transform = "translateY(".concat(rise, "px)");
34
+ child.style.transform = `translateY(${rise}px)`;
37
35
  child.style.transition = 'none';
38
36
  }
39
37
  // Trigger entrance in next frame so the start state has been painted
40
- var rafId = requestAnimationFrame(function () {
41
- children.forEach(function (child, i) {
42
- var delay = i * effectiveStep;
43
- child.style.transition = "opacity ".concat(duration, "ms var(--motion-glide) ").concat(delay, "ms, transform ").concat(duration, "ms var(--motion-glide) ").concat(delay, "ms");
38
+ const rafId = requestAnimationFrame(() => {
39
+ children.forEach((child, i) => {
40
+ const delay = i * effectiveStep;
41
+ child.style.transition = `opacity ${duration}ms var(--motion-glide) ${delay}ms, transform ${duration}ms var(--motion-glide) ${delay}ms`;
44
42
  child.style.opacity = '1';
45
43
  child.style.transform = 'translateY(0)';
46
44
  });
47
45
  // Clean up inline styles after all transitions complete
48
- var totalMs = (children.length - 1) * effectiveStep + duration + 50;
49
- var cleanupId = setTimeout(function () {
50
- for (var _i = 0, children_2 = children; _i < children_2.length; _i++) {
51
- var child = children_2[_i];
46
+ const totalMs = (children.length - 1) * effectiveStep + duration + 50;
47
+ const cleanupId = setTimeout(() => {
48
+ for (const child of children) {
52
49
  child.style.opacity = '';
53
50
  child.style.transform = '';
54
51
  child.style.transition = '';
55
52
  }
56
53
  }, totalMs);
57
- return function () { return clearTimeout(cleanupId); };
54
+ return () => clearTimeout(cleanupId);
58
55
  });
59
56
  return {
60
- destroy: function () {
57
+ destroy() {
61
58
  cancelAnimationFrame(rafId);
62
59
  // Ensure children are visible if action is destroyed mid-animation
63
- for (var _i = 0, children_3 = children; _i < children_3.length; _i++) {
64
- var child = children_3[_i];
60
+ for (const child of children) {
65
61
  child.style.opacity = '';
66
62
  child.style.transform = '';
67
63
  child.style.transition = '';
@@ -16,81 +16,93 @@
16
16
  * Escape key hides the active tooltip.
17
17
  * Focus events (focusin/focusout) trigger alongside mouse hover.
18
18
  */
19
- var __assign = (this && this.__assign) || function () {
20
- __assign = Object.assign || function(t) {
21
- for (var s, i = 1, n = arguments.length; i < n; i++) {
22
- s = arguments[i];
23
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
24
- t[p] = s[p];
25
- }
26
- return t;
27
- };
28
- return __assign.apply(this, arguments);
29
- };
30
- var COOL_WINDOW_MS = 500;
31
- var GAP = 8;
32
- var tooltipEl = null;
33
- var lastHideTime = 0;
34
- var idCounter = 0;
19
+ const COOL_WINDOW_MS = 500;
20
+ const GAP = 8;
21
+ let tooltipEl = null;
22
+ let lastHideTime = 0;
23
+ let idCounter = 0;
35
24
  function getOrCreatePortal() {
36
25
  if (tooltipEl)
37
26
  return tooltipEl;
38
27
  tooltipEl = document.createElement('div');
39
28
  tooltipEl.id = 'jatui-tooltip-portal';
40
- tooltipEl.style.cssText = "\n\t\tposition: fixed;\n\t\ttop: 0; left: 0;\n\t\tpointer-events: none;\n\t\tz-index: 9999;\n\t";
29
+ tooltipEl.style.cssText = `
30
+ position: fixed;
31
+ top: 0; left: 0;
32
+ pointer-events: none;
33
+ z-index: 9999;
34
+ `;
41
35
  document.body.appendChild(tooltipEl);
42
36
  return tooltipEl;
43
37
  }
44
38
  function createBubble(text) {
45
- var el = document.createElement('div');
39
+ const el = document.createElement('div');
46
40
  el.role = 'tooltip';
47
41
  el.textContent = text;
48
- el.style.cssText = "\n\t\tposition: absolute;\n\t\tpadding: 4px 10px;\n\t\tborder-radius: 6px;\n\t\tfont-size: 0.8125rem;\n\t\tline-height: 1.4;\n\t\twhite-space: nowrap;\n\t\tmax-width: 240px;\n\t\twhite-space: normal;\n\t\tword-break: break-word;\n\t\tbackground: oklch(var(--b3, 20% 0 0));\n\t\tcolor: oklch(var(--bc, 95% 0 0));\n\t\tbox-shadow: 0 2px 6px oklch(0% 0 0 / 18%);\n\t\topacity: 0;\n\t\ttransform: translateY(4px);\n\t\ttransition:\n\t\t\topacity var(--motion-fast, 150ms) var(--motion-glide, cubic-bezier(0.16, 1, 0.3, 1)),\n\t\t\ttransform var(--motion-fast, 150ms) var(--motion-glide, cubic-bezier(0.16, 1, 0.3, 1));\n\t";
42
+ el.style.cssText = `
43
+ position: absolute;
44
+ padding: 4px 10px;
45
+ border-radius: 6px;
46
+ font-size: 0.8125rem;
47
+ line-height: 1.4;
48
+ white-space: nowrap;
49
+ max-width: 240px;
50
+ white-space: normal;
51
+ word-break: break-word;
52
+ background: oklch(var(--b3, 20% 0 0));
53
+ color: oklch(var(--bc, 95% 0 0));
54
+ box-shadow: 0 2px 6px oklch(0% 0 0 / 18%);
55
+ opacity: 0;
56
+ transform: translateY(4px);
57
+ transition:
58
+ opacity var(--motion-fast, 150ms) var(--motion-glide, cubic-bezier(0.16, 1, 0.3, 1)),
59
+ transform var(--motion-fast, 150ms) var(--motion-glide, cubic-bezier(0.16, 1, 0.3, 1));
60
+ `;
49
61
  // reduced-motion: remove transform, keep opacity fade
50
62
  el.dataset.tooltipBubble = '1';
51
63
  return el;
52
64
  }
53
65
  function positionBubble(bubble, anchor, placement) {
54
- var rect = anchor.getBoundingClientRect();
55
- var bw = bubble.offsetWidth;
56
- var bh = bubble.offsetHeight;
57
- var vw = window.innerWidth;
58
- var vh = window.innerHeight;
59
- var top;
60
- var left;
61
- var resolved = placement;
66
+ const rect = anchor.getBoundingClientRect();
67
+ const bw = bubble.offsetWidth;
68
+ const bh = bubble.offsetHeight;
69
+ const vw = window.innerWidth;
70
+ const vh = window.innerHeight;
71
+ let top;
72
+ let left;
73
+ let resolved = placement;
62
74
  // Compute primary position, then flip if needed
63
- var placements = {
64
- top: function () { return ({ top: rect.top - bh - GAP, left: rect.left + rect.width / 2 - bw / 2 }); },
65
- bottom: function () { return ({ top: rect.bottom + GAP, left: rect.left + rect.width / 2 - bw / 2 }); },
66
- left: function () { return ({ top: rect.top + rect.height / 2 - bh / 2, left: rect.left - bw - GAP }); },
67
- right: function () { return ({ top: rect.top + rect.height / 2 - bh / 2, left: rect.right + GAP }); },
75
+ const placements = {
76
+ top: () => ({ top: rect.top - bh - GAP, left: rect.left + rect.width / 2 - bw / 2 }),
77
+ bottom: () => ({ top: rect.bottom + GAP, left: rect.left + rect.width / 2 - bw / 2 }),
78
+ left: () => ({ top: rect.top + rect.height / 2 - bh / 2, left: rect.left - bw - GAP }),
79
+ right: () => ({ top: rect.top + rect.height / 2 - bh / 2, left: rect.right + GAP }),
68
80
  };
69
- var pos = placements[resolved]();
81
+ const pos = placements[resolved]();
70
82
  top = pos.top;
71
83
  left = pos.left;
72
84
  // Flip on viewport edge
73
85
  if (resolved === 'top' && top < 0) {
74
86
  resolved = 'bottom';
75
- var p = placements.bottom();
87
+ const p = placements.bottom();
76
88
  top = p.top;
77
89
  left = p.left;
78
90
  }
79
91
  else if (resolved === 'bottom' && top + bh > vh) {
80
92
  resolved = 'top';
81
- var p = placements.top();
93
+ const p = placements.top();
82
94
  top = p.top;
83
95
  left = p.left;
84
96
  }
85
97
  else if (resolved === 'left' && left < 0) {
86
98
  resolved = 'right';
87
- var p = placements.right();
99
+ const p = placements.right();
88
100
  top = p.top;
89
101
  left = p.left;
90
102
  }
91
103
  else if (resolved === 'right' && left + bw > vw) {
92
104
  resolved = 'left';
93
- var p = placements.left();
105
+ const p = placements.left();
94
106
  top = p.top;
95
107
  left = p.left;
96
108
  }
@@ -98,21 +110,21 @@ function positionBubble(bubble, anchor, placement) {
98
110
  left = Math.max(GAP, Math.min(left, vw - bw - GAP));
99
111
  top = Math.max(GAP, Math.min(top, vh - bh - GAP));
100
112
  // Rise direction depends on resolved placement
101
- var riseY = resolved === 'bottom' ? -4 : 4;
102
- bubble.style.setProperty('--tooltip-rise-y', "".concat(riseY, "px"));
103
- bubble.style.top = "".concat(top, "px");
104
- bubble.style.left = "".concat(left, "px");
113
+ const riseY = resolved === 'bottom' ? -4 : 4;
114
+ bubble.style.setProperty('--tooltip-rise-y', `${riseY}px`);
115
+ bubble.style.top = `${top}px`;
116
+ bubble.style.left = `${left}px`;
105
117
  }
106
118
  function isWarm() {
107
119
  return Date.now() - lastHideTime < COOL_WINDOW_MS;
108
120
  }
109
121
  export function tooltip(node, options) {
110
- var opts = __assign({ placement: 'top', delayMs: 400 }, options);
111
- var bubble = null;
112
- var showTimer = null;
113
- var tooltipId = "jatui-tt-".concat(++idCounter);
122
+ let opts = { placement: 'top', delayMs: 400, ...options };
123
+ let bubble = null;
124
+ let showTimer = null;
125
+ const tooltipId = `jatui-tt-${++idCounter}`;
114
126
  function show() {
115
- var portal = getOrCreatePortal();
127
+ const portal = getOrCreatePortal();
116
128
  if (bubble) {
117
129
  // Already showing — update text and reposition
118
130
  bubble.textContent = opts.text;
@@ -146,12 +158,12 @@ export function tooltip(node, options) {
146
158
  function scheduleShow() {
147
159
  if (showTimer || bubble)
148
160
  return;
149
- var delay = isWarm() ? 0 : opts.delayMs;
161
+ const delay = isWarm() ? 0 : opts.delayMs;
150
162
  if (delay === 0) {
151
163
  show();
152
164
  }
153
165
  else {
154
- showTimer = setTimeout(function () {
166
+ showTimer = setTimeout(() => {
155
167
  showTimer = null;
156
168
  show();
157
169
  }, delay);
@@ -167,14 +179,14 @@ export function tooltip(node, options) {
167
179
  node.addEventListener('focusout', hide);
168
180
  document.addEventListener('keydown', handleKeydown);
169
181
  return {
170
- update: function (next) {
171
- opts = __assign({ placement: 'top', delayMs: 400 }, next);
182
+ update(next) {
183
+ opts = { placement: 'top', delayMs: 400, ...next };
172
184
  if (bubble) {
173
185
  bubble.textContent = opts.text;
174
186
  positionBubble(bubble, node, opts.placement);
175
187
  }
176
188
  },
177
- destroy: function () {
189
+ destroy() {
178
190
  hide();
179
191
  node.removeEventListener('mouseenter', scheduleShow);
180
192
  node.removeEventListener('mouseleave', hide);
@@ -1,4 +1,4 @@
1
1
  // Source: https://github.com/kapishdima/soundcn/blob/main/registry/soundcn/sounds/error-buzz/error-buzz.ts
2
2
  // License: CC0 — Kenney (kenney.nl/assets/interface-sounds)
3
3
  // Error or destructive action
4
- export var errorSound = "data:audio/mpeg;base64,SUQzBAAAAAAAIlRTU0UAAAAOAAADTGF2ZjYyLjMuMTAwAAAAAAAAAAAAAAD/+1DAAAAAAAAAAAAAAAAAAAAAAABJbmZvAAAADwAAAAUAAATkAFVVVVVVVVVVVVVVVVVVVVVVVVV/f39/f39/f39/f39/f39/f39/f6qqqqqqqqqqqqqqqqqqqqqqqqqq1dXV1dXV1dXV1dXV1dXV1dXV1dX//////////////////////////wAAAABMYXZjNjIuMTEAAAAAAAAAAAAAAAAkAkAAAAAAAAAE5Ct0VKUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//tQxAAABrBja7SRAAHpFK03MPAAAAADpAAQG24rFaPVBQCAYJG5znPz/b6NqcOBgZzv/QIBgYs7/6lBj4Ph///3cuH+c5c//+GAAQHa6AAAAASCUWIBQCyQJZStElAWcc9uAG+mh4XttXtzdiUNiuVScgn20gM5uFsLE6Fxhn+ooJIxfQBCzFUpjz1wPUomKsWXV38+X77GWGKcTC8hH7Co3sLLRijb/OSZ8+EokIpc0wKgoFjAlEQPHQa/EoSES2//LFVoN1sAAAFygDXWUv/7UsQFgArspWW9hAARbhFq6rKwAqVF/AdqejzEmlOy1F5XbkjDHJAIyEgPA+AKAqSGQaGguBULhCkD3qDWeB8DzUNJbb7lrlVWa/rjaIbq/7ygo9INWMicMl4dEirDxb3I3gAAAnMANIK2GREbZA8FCWtPoXkVeZzwrfKGDLmaM47+A5HoEIbi4gyFJy6Lmkkmkkdp1KkjzrddOq2w5zrn//3Nb8JPBk7SoFXc7lVA0eBoqdd2w6VOjw0oNAAAAAUKKBQgQAQAi/uhmyAnxM15//tSxAoADGU5Z5j2gAGGky63mPAAjm0TcAIi5zgBMLwtS483d1dBIkP8lB5jsGA/8YMkx5gGgOZ/+aKWbkcKh//iUBzyXNzyaf//5o0uMgOcvp///+hpqQJc3Bx3//EBlEuHxpKKAdn8DBSAiMlz2HZmqAgCAHn1q11bWu4/1m+IicMtXoeozcJYmSXkwOp65uK0nVEe7qD41qvYsXN5ILFBbn7x2zNszFuDq0bFoVg6sFiOvelwLQEx5WIgKdJSURXEINB2aJcjaCAKTlorySL/+1LEBYAL0Etrp72BUXuPKaqwkAD4DYLuOE5S4k4J4hxEGgahzphEVjuagsILJWXG/d9eq7/vOigiDq0gqDbknASNA0YvDQbJESwUU8kImtSMLJLDGicxMKiQe4VORi841zX1q6GfTvAYEAgAgvgaCLXAQXsZE6LXsnhdaMzDtOVL3drZqkuERpYLEy3TQoclLx9xjGMaRISEysTNRQilEiRbFCAg4DRXKuWCuInh0RA0DR46CoalUc7EUsGv9ySwNBxUis9ztQVJJbJBdbhcBv/7UsQEgAuknU+5iIARao9j256QAAGAgAAIlpEiPnR6OUh6uOfPDAyW+TEqJml80EGSJscj0FieQbVBbINzdM3A8AKYG0QGf80QNEIWLhZwPzBsSFx//wbOBc0IIixkmLI/hcOAmz/SlQBAADMWYATAD4rgqQAkAxJKukNQ0tpcVC9ep1DQ0/+SyJEijkVUKHEQqZWIhUKiaZCKWlUKFnyWayUrVQsuEoaiUNo8qGiwcEQdWCvWdWdg1PXeV///f2f7OJVMQU1FMy4xMDBVVVVV";
4
+ export const errorSound = "data:audio/mpeg;base64,SUQzBAAAAAAAIlRTU0UAAAAOAAADTGF2ZjYyLjMuMTAwAAAAAAAAAAAAAAD/+1DAAAAAAAAAAAAAAAAAAAAAAABJbmZvAAAADwAAAAUAAATkAFVVVVVVVVVVVVVVVVVVVVVVVVV/f39/f39/f39/f39/f39/f39/f6qqqqqqqqqqqqqqqqqqqqqqqqqq1dXV1dXV1dXV1dXV1dXV1dXV1dX//////////////////////////wAAAABMYXZjNjIuMTEAAAAAAAAAAAAAAAAkAkAAAAAAAAAE5Ct0VKUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//tQxAAABrBja7SRAAHpFK03MPAAAAADpAAQG24rFaPVBQCAYJG5znPz/b6NqcOBgZzv/QIBgYs7/6lBj4Ph///3cuH+c5c//+GAAQHa6AAAAASCUWIBQCyQJZStElAWcc9uAG+mh4XttXtzdiUNiuVScgn20gM5uFsLE6Fxhn+ooJIxfQBCzFUpjz1wPUomKsWXV38+X77GWGKcTC8hH7Co3sLLRijb/OSZ8+EokIpc0wKgoFjAlEQPHQa/EoSES2//LFVoN1sAAAFygDXWUv/7UsQFgArspWW9hAARbhFq6rKwAqVF/AdqejzEmlOy1F5XbkjDHJAIyEgPA+AKAqSGQaGguBULhCkD3qDWeB8DzUNJbb7lrlVWa/rjaIbq/7ygo9INWMicMl4dEirDxb3I3gAAAnMANIK2GREbZA8FCWtPoXkVeZzwrfKGDLmaM47+A5HoEIbi4gyFJy6Lmkkmkkdp1KkjzrddOq2w5zrn//3Nb8JPBk7SoFXc7lVA0eBoqdd2w6VOjw0oNAAAAAUKKBQgQAQAi/uhmyAnxM15//tSxAoADGU5Z5j2gAGGky63mPAAjm0TcAIi5zgBMLwtS483d1dBIkP8lB5jsGA/8YMkx5gGgOZ/+aKWbkcKh//iUBzyXNzyaf//5o0uMgOcvp///+hpqQJc3Bx3//EBlEuHxpKKAdn8DBSAiMlz2HZmqAgCAHn1q11bWu4/1m+IicMtXoeozcJYmSXkwOp65uK0nVEe7qD41qvYsXN5ILFBbn7x2zNszFuDq0bFoVg6sFiOvelwLQEx5WIgKdJSURXEINB2aJcjaCAKTlorySL/+1LEBYAL0Etrp72BUXuPKaqwkAD4DYLuOE5S4k4J4hxEGgahzphEVjuagsILJWXG/d9eq7/vOigiDq0gqDbknASNA0YvDQbJESwUU8kImtSMLJLDGicxMKiQe4VORi841zX1q6GfTvAYEAgAgvgaCLXAQXsZE6LXsnhdaMzDtOVL3drZqkuERpYLEy3TQoclLx9xjGMaRISEysTNRQilEiRbFCAg4DRXKuWCuInh0RA0DR46CoalUc7EUsGv9ySwNBxUis9ztQVJJbJBdbhcBv/7UsQEgAuknU+5iIARao9j256QAAGAgAAIlpEiPnR6OUh6uOfPDAyW+TEqJml80EGSJscj0FieQbVBbINzdM3A8AKYG0QGf80QNEIWLhZwPzBsSFx//wbOBc0IIixkmLI/hcOAmz/SlQBAADMWYATAD4rgqQAkAxJKukNQ0tpcVC9ep1DQ0/+SyJEijkVUKHEQqZWIhUKiaZCKWlUKFnyWayUrVQsuEoaiUNo8qGiwcEQdWCvWdWdg1PXeV///f2f7OJVMQU1FMy4xMDBVVVVV";