@joewinke/jatui 0.1.28 → 0.1.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Joe Winke
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -58,34 +58,22 @@
58
58
  * state (e.g. a `SvelteSet` of ids, with the id interpolating the row's own id) —
59
59
  * one action instance attaches per row element.
60
60
  */
61
- var __assign = (this && this.__assign) || function () {
62
- __assign = Object.assign || function(t) {
63
- for (var s, i = 1, n = arguments.length; i < n; i++) {
64
- s = arguments[i];
65
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
66
- t[p] = s[p];
67
- }
68
- return t;
69
- };
70
- return __assign.apply(this, arguments);
71
- };
72
- var DEFAULTS = { threshold: 120, expanded: false, fadeStart: 55, epsilon: 4 };
73
- export function collapse(node, options) {
74
- if (options === void 0) { options = {}; }
75
- var opts = __assign(__assign({}, DEFAULTS), options);
76
- var collapsible = false;
77
- var rafId = 0;
78
- var applied = false;
61
+ const DEFAULTS = { threshold: 120, expanded: false, fadeStart: 55, epsilon: 4 };
62
+ export function collapse(node, options = {}) {
63
+ let opts = { ...DEFAULTS, ...options };
64
+ let collapsible = false;
65
+ let rafId = 0;
66
+ let applied = false;
79
67
  function gradient() {
80
- return "linear-gradient(to bottom, black ".concat(opts.fadeStart, "%, transparent 100%)");
68
+ return `linear-gradient(to bottom, black ${opts.fadeStart}%, transparent 100%)`;
81
69
  }
82
70
  function apply() {
83
- var shouldCollapse = collapsible && !opts.expanded;
71
+ const shouldCollapse = collapsible && !opts.expanded;
84
72
  if (shouldCollapse === applied)
85
73
  return; // idempotent — avoids RO feedback loops
86
74
  applied = shouldCollapse;
87
75
  if (shouldCollapse) {
88
- node.style.maxHeight = "".concat(opts.threshold, "px");
76
+ node.style.maxHeight = `${opts.threshold}px`;
89
77
  node.style.overflow = 'hidden';
90
78
  node.style.maskImage = gradient();
91
79
  node.style.webkitMaskImage = gradient();
@@ -98,12 +86,11 @@ export function collapse(node, options) {
98
86
  }
99
87
  }
100
88
  function measure() {
101
- var _a;
102
89
  // scrollHeight is the full content height even while collapsed.
103
- var next = node.scrollHeight > opts.threshold + opts.epsilon;
90
+ const next = node.scrollHeight > opts.threshold + opts.epsilon;
104
91
  if (next !== collapsible) {
105
92
  collapsible = next;
106
- (_a = opts.onCollapsible) === null || _a === void 0 ? void 0 : _a.call(opts, collapsible);
93
+ opts.onCollapsible?.(collapsible);
107
94
  }
108
95
  apply();
109
96
  }
@@ -112,13 +99,12 @@ export function collapse(node, options) {
112
99
  rafId = requestAnimationFrame(measure);
113
100
  }
114
101
  // Re-measure when the content's natural size changes (streaming, {@html}, lazy images).
115
- var ro = new ResizeObserver(scheduleMeasure);
102
+ const ro = new ResizeObserver(scheduleMeasure);
116
103
  ro.observe(node);
117
104
  scheduleMeasure();
118
105
  return {
119
- update: function (next) {
120
- if (next === void 0) { next = {}; }
121
- opts = __assign(__assign({}, DEFAULTS), next);
106
+ update(next = {}) {
107
+ opts = { ...DEFAULTS, ...next };
122
108
  // expanded/threshold/fade may have changed — re-measure and let
123
109
  // apply() compare the freshly computed shouldCollapse against the
124
110
  // real last-applied state. (Force-flipping `applied` here used to make
@@ -126,7 +112,7 @@ export function collapse(node, options) {
126
112
  // silently skipping the style update.)
127
113
  scheduleMeasure();
128
114
  },
129
- destroy: function () {
115
+ destroy() {
130
116
  cancelAnimationFrame(rafId);
131
117
  ro.disconnect();
132
118
  },
@@ -56,32 +56,21 @@
56
56
  * // ...page-specific shortcuts
57
57
  * }
58
58
  */
59
- var __assign = (this && this.__assign) || function () {
60
- __assign = Object.assign || function(t) {
61
- for (var s, i = 1, n = arguments.length; i < n; i++) {
62
- s = arguments[i];
63
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
64
- t[p] = s[p];
65
- }
66
- return t;
67
- };
68
- return __assign.apply(this, arguments);
69
- };
70
59
  /** How long a half-typed motion (count prefix, pending `g`, pending `z`) waits
71
60
  * for its completion before resetting. Matches Vim's default `timeoutlen`. */
72
- var MOTION_BUFFER_TIMEOUT_MS = 1500;
61
+ const MOTION_BUFFER_TIMEOUT_MS = 1500;
73
62
  /** Upper cap so `99999j` can't produce pathological math. Above any list size
74
63
  * you'd reasonably navigate with j/k. */
75
- var MAX_COUNT = 99999;
64
+ const MAX_COUNT = 99999;
76
65
  /** Fallback half-page size when we can't measure the viewport (SSR, jsdom
77
66
  * without layout, items not yet attached). */
78
- var DEFAULT_HALF_PAGE = 5;
67
+ const DEFAULT_HALF_PAGE = 5;
79
68
  function isTypingTarget(target) {
80
69
  if (typeof HTMLElement === 'undefined')
81
70
  return false;
82
71
  if (!(target instanceof HTMLElement))
83
72
  return false;
84
- var tag = target.tagName;
73
+ const tag = target.tagName;
85
74
  if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT')
86
75
  return true;
87
76
  return target.isContentEditable;
@@ -90,10 +79,10 @@ function hasModifier(e) {
90
79
  return e.ctrlKey || e.metaKey || e.altKey;
91
80
  }
92
81
  function resolveItems(optsRef) {
93
- var getItems = optsRef.current.getItems;
82
+ const getItems = optsRef.current.getItems;
94
83
  if (!getItems)
95
84
  return [];
96
- var result = getItems();
85
+ const result = getItems();
97
86
  return Array.isArray(result) ? result : Array.from(result);
98
87
  }
99
88
  function wrapIndex(next, length, wrap) {
@@ -111,17 +100,16 @@ function wrapIndex(next, length, wrap) {
111
100
  * when layout isn't available (SSR, jsdom, detached elements).
112
101
  */
113
102
  function getHalfPageSize(items, currentIdx) {
114
- var _a, _b;
115
103
  if (items.length === 0)
116
104
  return 0;
117
105
  try {
118
- var pivot = (_a = items[Math.max(0, Math.min(items.length - 1, currentIdx))]) !== null && _a !== void 0 ? _a : items[0];
106
+ const pivot = items[Math.max(0, Math.min(items.length - 1, currentIdx))] ?? items[0];
119
107
  if (!pivot || typeof window === 'undefined')
120
108
  return DEFAULT_HALF_PAGE;
121
109
  // Walk up looking for an ancestor that is actually scrolling.
122
- var scroller = pivot.parentElement;
110
+ let scroller = pivot.parentElement;
123
111
  while (scroller) {
124
- var cs = window.getComputedStyle(scroller);
112
+ const cs = window.getComputedStyle(scroller);
125
113
  if ((cs.overflowY === 'auto' || cs.overflowY === 'scroll') &&
126
114
  scroller.clientHeight > 0 &&
127
115
  scroller.clientHeight < scroller.scrollHeight) {
@@ -129,34 +117,34 @@ function getHalfPageSize(items, currentIdx) {
129
117
  }
130
118
  scroller = scroller.parentElement;
131
119
  }
132
- var viewportHeight = (_b = scroller === null || scroller === void 0 ? void 0 : scroller.clientHeight) !== null && _b !== void 0 ? _b : window.innerHeight;
133
- var itemHeight = pivot.getBoundingClientRect().height;
120
+ const viewportHeight = scroller?.clientHeight ?? window.innerHeight;
121
+ const itemHeight = pivot.getBoundingClientRect().height;
134
122
  if (viewportHeight > 0 && itemHeight > 0) {
135
- var fullPage = Math.max(1, Math.floor(viewportHeight / itemHeight));
123
+ const fullPage = Math.max(1, Math.floor(viewportHeight / itemHeight));
136
124
  return Math.max(1, Math.floor(fullPage / 2));
137
125
  }
138
126
  }
139
- catch (_c) {
127
+ catch {
140
128
  // Fall through to default.
141
129
  }
142
130
  return DEFAULT_HALF_PAGE;
143
131
  }
144
132
  function makeController(optsRef) {
145
- var focused = -1;
146
- var lastEl = null;
133
+ let focused = -1;
134
+ let lastEl = null;
147
135
  // Motion-buffer state. A motion is 'pending' until its follow-up key
148
136
  // arrives (e.g. the second `g` in `gg`) or the buffer times out.
149
- var pendingCount = null;
150
- var pendingG = false;
151
- var pendingZ = false;
152
- var bufferTimer = null;
137
+ let pendingCount = null;
138
+ let pendingG = false;
139
+ let pendingZ = false;
140
+ let bufferTimer = null;
153
141
  // Selection state. `selected` holds stable ids (from getItemId / data-nav-id)
154
142
  // rather than indices, since list filters can shift indices but ids persist.
155
143
  // `visualMode` flips on/off via V; while on, j/k extends the range from
156
144
  // `visualAnchor` (the index where V was first pressed) to current focus.
157
- var selected = new Set();
158
- var visualMode = false;
159
- var visualAnchor = -1;
145
+ const selected = new Set();
146
+ let visualMode = false;
147
+ let visualAnchor = -1;
160
148
  function clearBufferTimer() {
161
149
  if (bufferTimer !== null) {
162
150
  clearTimeout(bufferTimer);
@@ -176,25 +164,22 @@ function makeController(optsRef) {
176
164
  }
177
165
  }
178
166
  function focusedClass() {
179
- var _a;
180
- return (_a = optsRef.current.focusedClass) !== null && _a !== void 0 ? _a : 'jk-focused';
167
+ return optsRef.current.focusedClass ?? 'jk-focused';
181
168
  }
182
169
  function selectedClass() {
183
- var _a;
184
- return (_a = optsRef.current.selectedClass) !== null && _a !== void 0 ? _a : 'jk-selected';
170
+ return optsRef.current.selectedClass ?? 'jk-selected';
185
171
  }
186
172
  function getId(el) {
187
173
  if (!el)
188
174
  return null;
189
- var resolver = optsRef.current.getItemId;
190
- var raw = resolver ? resolver(el) : el.dataset.navId;
175
+ const resolver = optsRef.current.getItemId;
176
+ const raw = resolver ? resolver(el) : el.dataset.navId;
191
177
  return raw == null ? null : String(raw);
192
178
  }
193
179
  function applySelectionClasses(items) {
194
- var cls = selectedClass();
195
- for (var _i = 0, items_1 = items; _i < items_1.length; _i++) {
196
- var el = items_1[_i];
197
- var id = getId(el);
180
+ const cls = selectedClass();
181
+ for (const el of items) {
182
+ const id = getId(el);
198
183
  if (id !== null && selected.has(id))
199
184
  el.classList.add(cls);
200
185
  else
@@ -202,23 +187,21 @@ function makeController(optsRef) {
202
187
  }
203
188
  }
204
189
  function emitSelectionChange() {
205
- var _a, _b;
206
190
  applySelectionClasses(resolveItems(optsRef));
207
- (_b = (_a = optsRef.current).onSelectionChange) === null || _b === void 0 ? void 0 : _b.call(_a, new Set(selected));
191
+ optsRef.current.onSelectionChange?.(new Set(selected));
208
192
  }
209
193
  function apply(items, idx) {
210
- var _a, _b, _c, _d;
211
- var cls = focusedClass();
212
- var next = (_a = items[idx]) !== null && _a !== void 0 ? _a : null;
194
+ const cls = focusedClass();
195
+ const next = items[idx] ?? null;
213
196
  if (lastEl && lastEl !== next)
214
197
  lastEl.classList.remove(cls);
215
198
  if (next) {
216
199
  next.classList.add(cls);
217
- (_b = next.scrollIntoView) === null || _b === void 0 ? void 0 : _b.call(next, { block: 'nearest', inline: 'nearest' });
200
+ next.scrollIntoView?.({ block: 'nearest', inline: 'nearest' });
218
201
  }
219
202
  lastEl = next;
220
203
  focused = next ? idx : -1;
221
- (_d = (_c = optsRef.current).onFocusChange) === null || _d === void 0 ? void 0 : _d.call(_c, next, focused);
204
+ optsRef.current.onFocusChange?.(next, focused);
222
205
  }
223
206
  /**
224
207
  * Re-derive the selected set from the inclusive range [anchor..focus] while
@@ -226,16 +209,15 @@ function makeController(optsRef) {
226
209
  * V was pressed are preserved (additive — Vim's `V` extends, doesn't reset).
227
210
  */
228
211
  function extendVisualRange(items) {
229
- var _a;
230
212
  if (!visualMode || visualAnchor < 0 || focused < 0)
231
213
  return;
232
- var lo = Math.min(visualAnchor, focused);
233
- var hi = Math.max(visualAnchor, focused);
214
+ const lo = Math.min(visualAnchor, focused);
215
+ const hi = Math.max(visualAnchor, focused);
234
216
  // Add every id in [lo..hi]. Items outside the range are left alone so
235
217
  // existing pre-V selections survive moving the anchor to a new region.
236
- var mutated = false;
237
- for (var i = lo; i <= hi; i++) {
238
- var id = getId((_a = items[i]) !== null && _a !== void 0 ? _a : null);
218
+ let mutated = false;
219
+ for (let i = lo; i <= hi; i++) {
220
+ const id = getId(items[i] ?? null);
239
221
  if (id !== null && !selected.has(id)) {
240
222
  selected.add(id);
241
223
  mutated = true;
@@ -247,7 +229,7 @@ function makeController(optsRef) {
247
229
  applySelectionClasses(items);
248
230
  }
249
231
  function focus(idx) {
250
- var items = resolveItems(optsRef);
232
+ const items = resolveItems(optsRef);
251
233
  if (items.length === 0)
252
234
  return;
253
235
  apply(items, Math.max(0, Math.min(items.length - 1, idx)));
@@ -256,28 +238,27 @@ function makeController(optsRef) {
256
238
  focus(0);
257
239
  }
258
240
  function focusLast() {
259
- var items = resolveItems(optsRef);
241
+ const items = resolveItems(optsRef);
260
242
  if (items.length)
261
243
  apply(items, items.length - 1);
262
244
  }
263
245
  function clear() {
264
- var _a, _b;
265
246
  if (lastEl)
266
247
  lastEl.classList.remove(focusedClass());
267
248
  lastEl = null;
268
249
  focused = -1;
269
250
  clearPending();
270
- (_b = (_a = optsRef.current).onFocusChange) === null || _b === void 0 ? void 0 : _b.call(_a, null, -1);
251
+ optsRef.current.onFocusChange?.(null, -1);
271
252
  }
272
253
  function refresh() {
273
- var items = resolveItems(optsRef);
254
+ const items = resolveItems(optsRef);
274
255
  if (items.length === 0) {
275
256
  clear();
276
257
  return;
277
258
  }
278
259
  // Re-home the focused element if the old node has been removed.
279
260
  if (lastEl && !items.includes(lastEl)) {
280
- var newIdx = Math.min(focused, items.length - 1);
261
+ const newIdx = Math.min(focused, items.length - 1);
281
262
  apply(items, Math.max(0, newIdx));
282
263
  }
283
264
  else if (focused >= 0 && focused < items.length) {
@@ -288,8 +269,7 @@ function makeController(optsRef) {
288
269
  applySelectionClasses(items);
289
270
  }
290
271
  function toggleSelectionByIndex(items, idx) {
291
- var _a;
292
- var id = getId((_a = items[idx]) !== null && _a !== void 0 ? _a : null);
272
+ const id = getId(items[idx] ?? null);
293
273
  if (id === null)
294
274
  return;
295
275
  if (selected.has(id))
@@ -303,15 +283,14 @@ function makeController(optsRef) {
303
283
  visualAnchor = -1;
304
284
  }
305
285
  function handleKeydown(e) {
306
- var _a, _b, _c, _d, _e, _f, _g;
307
- var opts = optsRef.current;
286
+ const opts = optsRef.current;
308
287
  if (opts.enabled === false)
309
288
  return false;
310
289
  if (isTypingTarget(e.target))
311
290
  return false;
312
- var items = resolveItems(optsRef);
313
- var wrap = (_a = opts.wraparound) !== null && _a !== void 0 ? _a : true;
314
- var selectable = opts.selectable === true;
291
+ const items = resolveItems(optsRef);
292
+ const wrap = opts.wraparound ?? true;
293
+ const selectable = opts.selectable === true;
315
294
  // --- Selection layer (opt-in) ----------------------------------------
316
295
  // These keys are only owned by the controller when `selectable` is true,
317
296
  // so existing pages without a selection model keep their bindings.
@@ -334,7 +313,7 @@ function makeController(optsRef) {
334
313
  toggleSelectionByIndex(items, focused);
335
314
  // If the toggle deselected the anchor, re-add it — entering
336
315
  // visual mode should always include the anchor.
337
- var anchorId = getId((_b = items[focused]) !== null && _b !== void 0 ? _b : null);
316
+ const anchorId = getId(items[focused] ?? null);
338
317
  if (anchorId !== null && !selected.has(anchorId)) {
339
318
  selected.add(anchorId);
340
319
  emitSelectionChange();
@@ -357,25 +336,20 @@ function makeController(optsRef) {
357
336
  if (items.length === 0)
358
337
  return false;
359
338
  e.preventDefault();
360
- var allIds = [];
361
- for (var _i = 0, items_2 = items; _i < items_2.length; _i++) {
362
- var el = items_2[_i];
363
- var id = getId(el);
339
+ const allIds = [];
340
+ for (const el of items) {
341
+ const id = getId(el);
364
342
  if (id !== null)
365
343
  allIds.push(id);
366
344
  }
367
- var allSelected = allIds.length > 0 && allIds.every(function (id) { return selected.has(id); });
345
+ const allSelected = allIds.length > 0 && allIds.every((id) => selected.has(id));
368
346
  if (allSelected) {
369
- for (var _h = 0, allIds_1 = allIds; _h < allIds_1.length; _h++) {
370
- var id = allIds_1[_h];
347
+ for (const id of allIds)
371
348
  selected.delete(id);
372
- }
373
349
  }
374
350
  else {
375
- for (var _j = 0, allIds_2 = allIds; _j < allIds_2.length; _j++) {
376
- var id = allIds_2[_j];
351
+ for (const id of allIds)
377
352
  selected.add(id);
378
- }
379
353
  }
380
354
  emitSelectionChange();
381
355
  clearPending();
@@ -388,14 +362,14 @@ function makeController(optsRef) {
388
362
  if (items.length === 0)
389
363
  return false;
390
364
  e.preventDefault();
391
- var dir = e.key === 'J' ? 1 : -1;
392
- var before = focused < 0 ? (dir > 0 ? 0 : items.length - 1) : focused;
393
- var beforeId = getId((_c = items[before]) !== null && _c !== void 0 ? _c : null);
365
+ const dir = e.key === 'J' ? 1 : -1;
366
+ const before = focused < 0 ? (dir > 0 ? 0 : items.length - 1) : focused;
367
+ const beforeId = getId(items[before] ?? null);
394
368
  if (beforeId !== null)
395
369
  selected.add(beforeId);
396
- var afterIdx = Math.max(0, Math.min(items.length - 1, before + dir));
370
+ const afterIdx = Math.max(0, Math.min(items.length - 1, before + dir));
397
371
  apply(items, afterIdx);
398
- var afterId = getId((_d = items[afterIdx]) !== null && _d !== void 0 ? _d : null);
372
+ const afterId = getId(items[afterIdx] ?? null);
399
373
  if (afterId !== null)
400
374
  selected.add(afterId);
401
375
  emitSelectionChange();
@@ -407,14 +381,14 @@ function makeController(optsRef) {
407
381
  // Ctrl/Meta/Alt bailout so vim half-page works; every other modifier
408
382
  // combination still falls through untouched.
409
383
  if (e.ctrlKey && !e.metaKey && !e.altKey && !e.shiftKey) {
410
- var lower = e.key.toLowerCase();
384
+ const lower = e.key.toLowerCase();
411
385
  if (lower === 'd' || lower === 'u') {
412
386
  if (items.length === 0)
413
387
  return false;
414
388
  e.preventDefault();
415
- var half = getHalfPageSize(items, focused);
416
- var dir = lower === 'd' ? 1 : -1;
417
- var start = focused < 0 ? (dir > 0 ? 0 : items.length - 1) : focused;
389
+ const half = getHalfPageSize(items, focused);
390
+ const dir = lower === 'd' ? 1 : -1;
391
+ const start = focused < 0 ? (dir > 0 ? 0 : items.length - 1) : focused;
418
392
  apply(items, wrapIndex(start + dir * half, items.length, wrap));
419
393
  clearPending();
420
394
  return true;
@@ -429,7 +403,7 @@ function makeController(optsRef) {
429
403
  if (pendingCount === null && e.key === '0')
430
404
  return false;
431
405
  e.preventDefault();
432
- pendingCount = (pendingCount !== null && pendingCount !== void 0 ? pendingCount : 0) * 10 + Number(e.key);
406
+ pendingCount = (pendingCount ?? 0) * 10 + Number(e.key);
433
407
  if (pendingCount > MAX_COUNT)
434
408
  pendingCount = MAX_COUNT;
435
409
  pendingG = false;
@@ -445,7 +419,7 @@ function makeController(optsRef) {
445
419
  }
446
420
  e.preventDefault();
447
421
  if (pendingG) {
448
- var target = pendingCount !== null
422
+ const target = pendingCount !== null
449
423
  ? Math.max(0, Math.min(items.length - 1, pendingCount - 1))
450
424
  : 0;
451
425
  apply(items, target);
@@ -465,7 +439,7 @@ function makeController(optsRef) {
465
439
  return false;
466
440
  }
467
441
  e.preventDefault();
468
- var target = pendingCount !== null
442
+ const target = pendingCount !== null
469
443
  ? Math.max(0, Math.min(items.length - 1, pendingCount - 1))
470
444
  : items.length - 1;
471
445
  apply(items, target);
@@ -476,8 +450,8 @@ function makeController(optsRef) {
476
450
  if (e.key === 'z' && !e.shiftKey) {
477
451
  e.preventDefault();
478
452
  if (pendingZ) {
479
- var el = (_e = lastEl !== null && lastEl !== void 0 ? lastEl : items[focused]) !== null && _e !== void 0 ? _e : null;
480
- (_f = el === null || el === void 0 ? void 0 : el.scrollIntoView) === null || _f === void 0 ? void 0 : _f.call(el, { block: 'center', inline: 'nearest' });
453
+ const el = lastEl ?? items[focused] ?? null;
454
+ el?.scrollIntoView?.({ block: 'center', inline: 'nearest' });
481
455
  clearPending();
482
456
  }
483
457
  else {
@@ -493,10 +467,10 @@ function makeController(optsRef) {
493
467
  if (items.length === 0)
494
468
  return false;
495
469
  e.preventDefault();
496
- var step = pendingCount !== null && pendingCount !== void 0 ? pendingCount : 1;
470
+ const step = pendingCount ?? 1;
497
471
  // From an unfocused state, `{n}j` selects the n-th item
498
472
  // (1-indexed) so it mirrors `{n}G` from the top.
499
- var target = focused < 0 ? step - 1 : focused + step;
473
+ const target = focused < 0 ? step - 1 : focused + step;
500
474
  apply(items, wrapIndex(target, items.length, wrap));
501
475
  clearPending();
502
476
  if (selectable && visualMode)
@@ -508,8 +482,8 @@ function makeController(optsRef) {
508
482
  if (items.length === 0)
509
483
  return false;
510
484
  e.preventDefault();
511
- var step = pendingCount !== null && pendingCount !== void 0 ? pendingCount : 1;
512
- var target = focused < 0 ? items.length - step : focused - step;
485
+ const step = pendingCount ?? 1;
486
+ const target = focused < 0 ? items.length - step : focused - step;
513
487
  apply(items, wrapIndex(target, items.length, wrap));
514
488
  clearPending();
515
489
  if (selectable && visualMode)
@@ -520,12 +494,12 @@ function makeController(optsRef) {
520
494
  case ' ': {
521
495
  if (focused < 0)
522
496
  return false;
523
- var el = items[focused];
497
+ const el = items[focused];
524
498
  if (!el)
525
499
  return false;
526
500
  e.preventDefault();
527
501
  clearPending();
528
- (_g = opts.onSelect) === null || _g === void 0 ? void 0 : _g.call(opts, el, focused);
502
+ opts.onSelect?.(el, focused);
529
503
  return true;
530
504
  }
531
505
  case 'Escape': {
@@ -567,16 +541,16 @@ function makeController(optsRef) {
567
541
  return false;
568
542
  }
569
543
  return {
570
- handleKeydown: handleKeydown,
571
- focusedIndex: function () { return focused; },
572
- focus: focus,
573
- focusFirst: focusFirst,
574
- focusLast: focusLast,
575
- clear: clear,
576
- refresh: refresh,
577
- selectedIds: function () { return new Set(selected); },
578
- toggleSelection: function (navId) {
579
- var items = resolveItems(optsRef);
544
+ handleKeydown,
545
+ focusedIndex: () => focused,
546
+ focus,
547
+ focusFirst,
548
+ focusLast,
549
+ clear,
550
+ refresh,
551
+ selectedIds: () => new Set(selected),
552
+ toggleSelection: (navId) => {
553
+ const items = resolveItems(optsRef);
580
554
  if (navId === undefined) {
581
555
  if (focused < 0)
582
556
  return;
@@ -589,32 +563,29 @@ function makeController(optsRef) {
589
563
  selected.add(navId);
590
564
  emitSelectionChange();
591
565
  },
592
- setSelection: function (ids) {
566
+ setSelection: (ids) => {
593
567
  selected.clear();
594
- for (var _i = 0, ids_1 = ids; _i < ids_1.length; _i++) {
595
- var id = ids_1[_i];
568
+ for (const id of ids)
596
569
  selected.add(id);
597
- }
598
570
  emitSelectionChange();
599
571
  },
600
- clearSelection: function () {
572
+ clearSelection: () => {
601
573
  if (selected.size === 0 && !visualMode)
602
574
  return;
603
575
  selected.clear();
604
576
  exitVisualMode();
605
577
  emitSelectionChange();
606
578
  },
607
- selectAll: function () {
608
- var items = resolveItems(optsRef);
609
- for (var _i = 0, items_3 = items; _i < items_3.length; _i++) {
610
- var el = items_3[_i];
611
- var id = getId(el);
579
+ selectAll: () => {
580
+ const items = resolveItems(optsRef);
581
+ for (const el of items) {
582
+ const id = getId(el);
612
583
  if (id !== null)
613
584
  selected.add(id);
614
585
  }
615
586
  emitSelectionChange();
616
587
  },
617
- isSelecting: function () { return visualMode; },
588
+ isSelecting: () => visualMode,
618
589
  };
619
590
  }
620
591
  /**
@@ -622,18 +593,17 @@ function makeController(optsRef) {
622
593
  * listNav to decide whether to consume the event.
623
594
  */
624
595
  export function createListNav(options) {
625
- var ref = { current: options };
596
+ const ref = { current: options };
626
597
  return makeController(ref);
627
598
  }
628
599
  /**
629
600
  * Svelte action — attaches a keydown listener (window by default) and handles
630
601
  * j/k/ArrowDown/ArrowUp/Enter/Space/Escape navigation over children of `node`.
631
602
  */
632
- export var listNav = function (node, initial) {
633
- if (initial === void 0) { initial = {}; }
634
- var ref = { current: withDefaultGetItems(node, initial) };
635
- var controller = makeController(ref);
636
- var target = ref.current.global === false ? node : window;
603
+ export const listNav = (node, initial = {}) => {
604
+ const ref = { current: withDefaultGetItems(node, initial) };
605
+ const controller = makeController(ref);
606
+ let target = ref.current.global === false ? node : window;
637
607
  function onKeydown(e) {
638
608
  controller.handleKeydown(e);
639
609
  }
@@ -646,27 +616,28 @@ export var listNav = function (node, initial) {
646
616
  }
647
617
  attach();
648
618
  return {
649
- update: function (next) {
650
- if (next === void 0) { next = {}; }
651
- var wasGlobal = ref.current.global !== false;
619
+ update(next = {}) {
620
+ const wasGlobal = ref.current.global !== false;
652
621
  ref.current = withDefaultGetItems(node, next);
653
- var isGlobal = ref.current.global !== false;
622
+ const isGlobal = ref.current.global !== false;
654
623
  if (wasGlobal !== isGlobal) {
655
624
  detach();
656
625
  attach();
657
626
  }
658
627
  controller.refresh();
659
628
  },
660
- destroy: function () {
629
+ destroy() {
661
630
  detach();
662
631
  controller.clear();
663
632
  },
664
633
  };
665
634
  };
666
635
  function withDefaultGetItems(node, options) {
667
- var _a;
668
636
  if (options.getItems)
669
637
  return options;
670
- var selector = (_a = options.itemSelector) !== null && _a !== void 0 ? _a : '[data-nav-id]';
671
- return __assign(__assign({}, options), { getItems: function () { return Array.from(node.querySelectorAll(selector)); } });
638
+ const selector = options.itemSelector ?? '[data-nav-id]';
639
+ return {
640
+ ...options,
641
+ getItems: () => Array.from(node.querySelectorAll(selector)),
642
+ };
672
643
  }