@gridkitjs/dom 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1320 @@
1
+ // src/announcer.ts
2
+ var NO_BREAK_SPACE = String.fromCodePoint(160);
3
+ function createLiveAnnouncer(container = document.body) {
4
+ const region = document.createElement("div");
5
+ region.className = "gridkit-sr-only";
6
+ region.setAttribute("role", "status");
7
+ region.setAttribute("aria-live", "polite");
8
+ container.append(region);
9
+ let last = "";
10
+ let padded = false;
11
+ return {
12
+ announce(text) {
13
+ padded = text === last && !padded;
14
+ last = text;
15
+ region.textContent = padded ? text + NO_BREAK_SPACE : text;
16
+ },
17
+ destroy() {
18
+ region.remove();
19
+ }
20
+ };
21
+ }
22
+
23
+ // src/bodyTargets.ts
24
+ function rowIndexOf(row) {
25
+ const attribute = row.getAttribute("data-gridkit-row-index");
26
+ return attribute === null ? null : Number(attribute);
27
+ }
28
+ function bodyCellFrom(target) {
29
+ if (!(target instanceof Element)) {
30
+ return null;
31
+ }
32
+ const cell = target.closest("td[data-gridkit-column]");
33
+ const row = cell?.parentElement;
34
+ const columnId = cell?.getAttribute("data-gridkit-column");
35
+ const rowIndex = row === null || row === void 0 ? null : rowIndexOf(row);
36
+ if (!(cell instanceof HTMLTableCellElement) || !(row instanceof HTMLTableRowElement) || columnId === null || columnId === void 0 || rowIndex === null) {
37
+ return null;
38
+ }
39
+ return { rowIndex, columnIndex: cell.cellIndex, columnId };
40
+ }
41
+ function groupRowFrom(target) {
42
+ if (!(target instanceof Element)) {
43
+ return null;
44
+ }
45
+ const row = target.closest("tr[data-gridkit-group]");
46
+ const groupId = row?.getAttribute("data-gridkit-group");
47
+ const rowIndex = row === null ? null : rowIndexOf(row);
48
+ if (!(row instanceof HTMLTableRowElement) || groupId === null || groupId === void 0 || rowIndex === null) {
49
+ return null;
50
+ }
51
+ return { rowIndex, groupId };
52
+ }
53
+ function bodyRowFrom(target) {
54
+ if (!(target instanceof Element)) {
55
+ return null;
56
+ }
57
+ const row = target.closest("tr[data-gridkit-row-index]");
58
+ const rowIndex = row === null ? null : rowIndexOf(row);
59
+ if (rowIndex === null) {
60
+ return null;
61
+ }
62
+ const cell = target.closest("td[data-gridkit-column]");
63
+ return {
64
+ rowIndex,
65
+ columnId: cell?.parentElement === row ? cell.getAttribute("data-gridkit-column") : null
66
+ };
67
+ }
68
+
69
+ // src/contextMenu/attachContextMenuTrigger.ts
70
+ var LONG_PRESS_DELAY = 500;
71
+ var LONG_PRESS_SLOP = 10;
72
+ function isContextMenuKey(event) {
73
+ if (event.ctrlKey || event.altKey || event.metaKey) {
74
+ return false;
75
+ }
76
+ return event.key === "ContextMenu" || event.key === "F10" && event.shiftKey;
77
+ }
78
+ function attachContextMenuTrigger(root, options) {
79
+ let swallowContextMenu = false;
80
+ let swallowClick = false;
81
+ let press = null;
82
+ function ask(event, point, source) {
83
+ const { target } = event;
84
+ return !event.defaultPrevented && target instanceof Element && root.contains(target) && options.onRequest({ target, point, source });
85
+ }
86
+ function request(event, point, source) {
87
+ if (!ask(event, point, source)) {
88
+ return false;
89
+ }
90
+ event.preventDefault();
91
+ return true;
92
+ }
93
+ function cancelPress() {
94
+ if (press !== null) {
95
+ window.clearTimeout(press.timer);
96
+ press = null;
97
+ }
98
+ }
99
+ function onKeyDown2(event) {
100
+ swallowContextMenu = false;
101
+ swallowClick = false;
102
+ if (isContextMenuKey(event) && request(event, null, "keyboard")) {
103
+ swallowContextMenu = true;
104
+ }
105
+ }
106
+ function onPointerDown(event) {
107
+ swallowContextMenu = false;
108
+ swallowClick = false;
109
+ cancelPress();
110
+ if (event.pointerType !== "touch" || !event.isPrimary) {
111
+ return;
112
+ }
113
+ const point = { x: event.clientX, y: event.clientY };
114
+ press = {
115
+ pointerId: event.pointerId,
116
+ ...point,
117
+ timer: window.setTimeout(() => {
118
+ press = null;
119
+ if (ask(event, point, "pointer")) {
120
+ swallowContextMenu = true;
121
+ swallowClick = true;
122
+ }
123
+ }, LONG_PRESS_DELAY)
124
+ };
125
+ }
126
+ function onPointerMove(event) {
127
+ if (press?.pointerId === event.pointerId && Math.hypot(event.clientX - press.x, event.clientY - press.y) > LONG_PRESS_SLOP) {
128
+ cancelPress();
129
+ }
130
+ }
131
+ function onPointerEnd(event) {
132
+ if (press?.pointerId === event.pointerId) {
133
+ cancelPress();
134
+ }
135
+ }
136
+ function onClick(event) {
137
+ if (swallowClick) {
138
+ swallowClick = false;
139
+ event.preventDefault();
140
+ event.stopPropagation();
141
+ }
142
+ }
143
+ function onContextMenu(event) {
144
+ if (swallowContextMenu) {
145
+ swallowContextMenu = false;
146
+ event.preventDefault();
147
+ return;
148
+ }
149
+ const touching = press !== null;
150
+ cancelPress();
151
+ if (request(event, { x: event.clientX, y: event.clientY }, "pointer") && touching) {
152
+ swallowClick = true;
153
+ }
154
+ }
155
+ document.addEventListener("keydown", onKeyDown2);
156
+ document.addEventListener("pointerdown", onPointerDown, true);
157
+ document.addEventListener("pointermove", onPointerMove, true);
158
+ document.addEventListener("pointerup", onPointerEnd, true);
159
+ document.addEventListener("pointercancel", onPointerEnd, true);
160
+ document.addEventListener("click", onClick, true);
161
+ document.addEventListener("contextmenu", onContextMenu);
162
+ return () => {
163
+ cancelPress();
164
+ document.removeEventListener("keydown", onKeyDown2);
165
+ document.removeEventListener("pointerdown", onPointerDown, true);
166
+ document.removeEventListener("pointermove", onPointerMove, true);
167
+ document.removeEventListener("pointerup", onPointerEnd, true);
168
+ document.removeEventListener("pointercancel", onPointerEnd, true);
169
+ document.removeEventListener("click", onClick, true);
170
+ document.removeEventListener("contextmenu", onContextMenu);
171
+ };
172
+ }
173
+
174
+ // src/columnResize.ts
175
+ import { applyColumnResize } from "@gridkitjs/core";
176
+
177
+ // src/pointerGesture.ts
178
+ function isPrimaryPress(press) {
179
+ return press.button === 0 && press.isPrimary;
180
+ }
181
+ function startPointerGesture(element, pointerId, handlers) {
182
+ element.setPointerCapture(pointerId);
183
+ function stop() {
184
+ element.removeEventListener("pointermove", move);
185
+ element.removeEventListener("pointerup", end);
186
+ element.removeEventListener("pointercancel", cancel);
187
+ window.removeEventListener("keydown", onKeyDown2);
188
+ if (element.hasPointerCapture(pointerId)) {
189
+ element.releasePointerCapture(pointerId);
190
+ }
191
+ }
192
+ function move(event) {
193
+ handlers.onMove(event);
194
+ }
195
+ function end() {
196
+ stop();
197
+ handlers.onEnd();
198
+ }
199
+ function cancel() {
200
+ stop();
201
+ handlers.onCancel();
202
+ }
203
+ function onKeyDown2(event) {
204
+ if (event.key === "Escape") {
205
+ cancel();
206
+ }
207
+ }
208
+ element.addEventListener("pointermove", move);
209
+ element.addEventListener("pointerup", end);
210
+ element.addEventListener("pointercancel", cancel);
211
+ window.addEventListener("keydown", onKeyDown2);
212
+ }
213
+
214
+ // src/columnResize.ts
215
+ function startColumnResizeGesture(handle, press, session, handlers) {
216
+ if (!isPrimaryPress(press)) {
217
+ return false;
218
+ }
219
+ press.preventDefault();
220
+ let width = session.startWidth;
221
+ startPointerGesture(handle, press.pointerId, {
222
+ onMove(event) {
223
+ width = applyColumnResize(session, event.clientX);
224
+ handlers.onMove(width);
225
+ },
226
+ onEnd() {
227
+ handlers.onEnd(width === session.startWidth ? null : width);
228
+ },
229
+ onCancel() {
230
+ handlers.onCancel();
231
+ }
232
+ });
233
+ return true;
234
+ }
235
+ function measureColumnContent(table, columnId) {
236
+ const cells = table.querySelectorAll(
237
+ `td[data-gridkit-column="${CSS.escape(columnId)}"]`
238
+ );
239
+ const range = document.createRange();
240
+ let widest = null;
241
+ for (const cell of cells) {
242
+ range.selectNodeContents(cell);
243
+ const style = getComputedStyle(cell);
244
+ const width = range.getBoundingClientRect().width + parseFloat(style.paddingLeft) + parseFloat(style.paddingRight) + parseFloat(style.borderLeftWidth) + parseFloat(style.borderRightWidth);
245
+ if (widest === null || width > widest) {
246
+ widest = width;
247
+ }
248
+ }
249
+ return widest;
250
+ }
251
+
252
+ // src/dragReorder.ts
253
+ var DRAG_THRESHOLD = 4;
254
+ var NO_DRAG = {
255
+ draggedId: null,
256
+ dropTarget: null,
257
+ ghostTransform: null
258
+ };
259
+ function startDragReorder(id, grabElement, press, handlers) {
260
+ if (!isPrimaryPress(press)) {
261
+ return false;
262
+ }
263
+ const { pointerId, clientX: startX } = press;
264
+ const grabX = startX - grabElement.getBoundingClientRect().left;
265
+ let dragging = false;
266
+ let target = null;
267
+ startPointerGesture(grabElement, pointerId, {
268
+ onMove(moveEvent) {
269
+ const { clientX, clientY } = moveEvent;
270
+ if (!dragging) {
271
+ if (Math.abs(clientX - startX) < DRAG_THRESHOLD) {
272
+ return;
273
+ }
274
+ dragging = true;
275
+ }
276
+ target = handlers.resolveTarget(clientX, clientY, id);
277
+ handlers.onState({
278
+ draggedId: id,
279
+ dropTarget: target,
280
+ ghostTransform: `translate(${String(clientX - grabX)}px, ${String(clientY)}px)`
281
+ });
282
+ },
283
+ onEnd() {
284
+ const dropped = target;
285
+ handlers.onState(NO_DRAG);
286
+ if (dragging && dropped !== null) {
287
+ handlers.onDrop(dropped, id);
288
+ }
289
+ },
290
+ onCancel() {
291
+ target = null;
292
+ handlers.onState(NO_DRAG);
293
+ }
294
+ });
295
+ return true;
296
+ }
297
+
298
+ // src/dropTargets.ts
299
+ import {
300
+ movesColumn,
301
+ movesGroupBy,
302
+ resolveDropBefore
303
+ } from "@gridkitjs/core";
304
+ function elementAt(x, y, selector) {
305
+ return document.elementFromPoint(x, y)?.closest(selector) ?? null;
306
+ }
307
+ function sideOf(element, x) {
308
+ const rect = element.getBoundingClientRect();
309
+ return x < rect.left + rect.width / 2 ? "before" : "after";
310
+ }
311
+ function resolveGroupByDropTarget(clientX, clientY, movedId, groupBy) {
312
+ const overBar = elementAt(clientX, clientY, "[data-gridkit-group-by-bar]");
313
+ if (overBar === null) {
314
+ return null;
315
+ }
316
+ const overChip = elementAt(clientX, clientY, "[data-gridkit-group-chip]");
317
+ const chipId = overChip?.getAttribute("data-gridkit-group-chip");
318
+ const beforeColumnId = overChip && chipId ? resolveDropBefore(
319
+ groupBy.map((entry) => entry.columnId),
320
+ chipId,
321
+ sideOf(overChip, clientX)
322
+ ) : null;
323
+ return movesGroupBy(groupBy, movedId, beforeColumnId) ? { kind: "group-by", beforeColumnId } : null;
324
+ }
325
+ function resolveColumnDropTarget(clientX, clientY, movedId, { order, groupBy, groupByDraggableIds }) {
326
+ const over = elementAt(clientX, clientY, "th[data-gridkit-column]");
327
+ const overId = over?.getAttribute("data-gridkit-column");
328
+ const beforeId = over && overId ? resolveDropBefore(order, overId, sideOf(over, clientX)) : void 0;
329
+ if (beforeId !== void 0) {
330
+ return movesColumn(order, movedId, beforeId) ? { kind: "column-order", beforeId } : null;
331
+ }
332
+ const alreadyGrouped = groupBy.some((entry) => entry.columnId === movedId);
333
+ return groupByDraggableIds.has(movedId) && !alreadyGrouped ? resolveGroupByDropTarget(clientX, clientY, movedId, groupBy) : null;
334
+ }
335
+
336
+ // src/elementWidth.ts
337
+ function observeElementWidth(element, onWidth) {
338
+ onWidth(element.clientWidth);
339
+ const observer = new ResizeObserver(() => {
340
+ onWidth(element.clientWidth);
341
+ });
342
+ observer.observe(element);
343
+ return () => {
344
+ observer.disconnect();
345
+ };
346
+ }
347
+
348
+ // src/gridFocus.ts
349
+ import {
350
+ clampFocus,
351
+ HEADER_ROW,
352
+ nextFocusForKey
353
+ } from "@gridkitjs/core";
354
+ var FALLBACK_PAGE = 10;
355
+ function cellIn(row, columnIndex) {
356
+ if (row === null) {
357
+ return null;
358
+ }
359
+ return row.cells[Math.min(columnIndex, row.cells.length - 1)] ?? null;
360
+ }
361
+ function findBodyRow(bodyTable, rowIndex) {
362
+ return bodyTable?.tBodies[0]?.querySelector(
363
+ `:scope > tr[data-gridkit-row-index="${String(rowIndex)}"]`
364
+ ) ?? null;
365
+ }
366
+ function measurePageSize(bodyTable) {
367
+ const firstRow = bodyTable?.tBodies[0]?.rows[0];
368
+ const viewport = bodyTable?.parentElement;
369
+ if (firstRow === void 0 || viewport === null || viewport === void 0 || firstRow.offsetHeight === 0) {
370
+ return FALLBACK_PAGE;
371
+ }
372
+ return Math.max(1, Math.floor(viewport.clientHeight / firstRow.offsetHeight));
373
+ }
374
+ function createGridFocus(initialOptions) {
375
+ let options = initialOptions;
376
+ let rows = null;
377
+ const listeners = /* @__PURE__ */ new Set();
378
+ let stored = { rowIndex: HEADER_ROW, columnIndex: 0 };
379
+ let snapshot = {
380
+ stored,
381
+ rowCount: options.rowCount,
382
+ columnCount: options.columnCount,
383
+ focus: clampFocus(stored, options.rowCount, options.columnCount)
384
+ };
385
+ let pendingMove = null;
386
+ function getFocus() {
387
+ if (snapshot.stored !== stored || snapshot.rowCount !== options.rowCount || snapshot.columnCount !== options.columnCount) {
388
+ snapshot = {
389
+ stored,
390
+ rowCount: options.rowCount,
391
+ columnCount: options.columnCount,
392
+ focus: clampFocus(stored, options.rowCount, options.columnCount)
393
+ };
394
+ }
395
+ return snapshot.focus;
396
+ }
397
+ function focusCell(rowIndex, columnIndex) {
398
+ const next = clampFocus(
399
+ { rowIndex, columnIndex },
400
+ options.rowCount,
401
+ options.columnCount
402
+ );
403
+ const current = getFocus();
404
+ if (next.rowIndex === current.rowIndex && next.columnIndex === current.columnIndex) {
405
+ return;
406
+ }
407
+ pendingMove = next;
408
+ stored = next;
409
+ for (const listener of listeners) {
410
+ listener();
411
+ }
412
+ }
413
+ return {
414
+ getFocus,
415
+ subscribe(listener) {
416
+ listeners.add(listener);
417
+ return () => {
418
+ listeners.delete(listener);
419
+ };
420
+ },
421
+ setOptions(next) {
422
+ options = next;
423
+ },
424
+ focusCell,
425
+ handleKey(key, modifiers, pageSize) {
426
+ const next = nextFocusForKey(
427
+ key,
428
+ modifiers,
429
+ getFocus(),
430
+ options.rowCount,
431
+ options.columnCount,
432
+ pageSize,
433
+ options.isSkippableRow
434
+ );
435
+ if (next === null) {
436
+ return false;
437
+ }
438
+ focusCell(next.rowIndex, next.columnIndex);
439
+ return true;
440
+ },
441
+ attach(next) {
442
+ rows = next;
443
+ return () => {
444
+ if (rows === next) {
445
+ rows = null;
446
+ }
447
+ };
448
+ },
449
+ focusDrawnCell(drawn) {
450
+ if (rows === null || pendingMove === null || snapshot.stored !== pendingMove || snapshot.focus !== drawn) {
451
+ return;
452
+ }
453
+ const cell = cellIn(
454
+ drawn.rowIndex === HEADER_ROW ? rows.getHeaderRow() : rows.getBodyRow(drawn.rowIndex),
455
+ drawn.columnIndex
456
+ );
457
+ if (cell !== null) {
458
+ pendingMove = null;
459
+ cell.focus();
460
+ return;
461
+ }
462
+ const range = options.virtualRange;
463
+ if (range != null && drawn.rowIndex !== HEADER_ROW && (drawn.rowIndex < range.startIndex || drawn.rowIndex > range.endIndex)) {
464
+ range.scrollToIndex(drawn.rowIndex);
465
+ return;
466
+ }
467
+ pendingMove = null;
468
+ }
469
+ };
470
+ }
471
+
472
+ // src/infiniteScroll.ts
473
+ function attachInfiniteScroll(root, options) {
474
+ let latest = options;
475
+ let intersecting = false;
476
+ let fired = false;
477
+ let wasLoading = options.isLoadingMore ?? false;
478
+ let observer = null;
479
+ let observed = null;
480
+ function maybeLoadMore() {
481
+ if (!intersecting || !latest.hasMore || (latest.isLoadingMore ?? false) || fired) {
482
+ return;
483
+ }
484
+ fired = true;
485
+ latest.onLoadMore?.();
486
+ }
487
+ function disconnect() {
488
+ observer?.disconnect();
489
+ observer = null;
490
+ observed = null;
491
+ intersecting = false;
492
+ }
493
+ function observe() {
494
+ const sentinel = latest.hasMore ? latest.sentinel : null;
495
+ const rootMargin = latest.rootMargin ?? "200px";
496
+ if (observed !== null && observed.sentinel === sentinel && observed.rootMargin === rootMargin) {
497
+ return;
498
+ }
499
+ disconnect();
500
+ if (sentinel === null) {
501
+ return;
502
+ }
503
+ observer = new IntersectionObserver(
504
+ (entries) => {
505
+ const entry = entries[entries.length - 1];
506
+ if (entry === void 0) {
507
+ return;
508
+ }
509
+ intersecting = entry.isIntersecting;
510
+ maybeLoadMore();
511
+ },
512
+ { root, rootMargin }
513
+ );
514
+ observer.observe(sentinel);
515
+ observed = { sentinel, rootMargin };
516
+ }
517
+ observe();
518
+ return {
519
+ update(next) {
520
+ latest = next;
521
+ const loading = next.isLoadingMore ?? false;
522
+ if (wasLoading && !loading) {
523
+ fired = false;
524
+ maybeLoadMore();
525
+ }
526
+ wasLoading = loading;
527
+ observe();
528
+ },
529
+ detach: disconnect
530
+ };
531
+ }
532
+
533
+ // src/menu/attachMenu.ts
534
+ import { nextMenuIndex, typeaheadIndex } from "@gridkitjs/core";
535
+ var ITEM = [
536
+ '[role="menuitem"][data-gridkit-menu-item]',
537
+ '[role="menuitemcheckbox"][data-gridkit-menu-item]',
538
+ '[role="menuitemradio"][data-gridkit-menu-item]'
539
+ ].join(", ");
540
+ var HOVER_DELAY = 150;
541
+ var TYPEAHEAD_TIMEOUT = 500;
542
+ var AS_ENTRY = { type: "item" };
543
+ var MOVES = {
544
+ ArrowDown: "next",
545
+ ArrowUp: "previous",
546
+ Home: "first",
547
+ End: "last"
548
+ };
549
+ function idOf(item) {
550
+ return item.getAttribute("data-gridkit-menu-item") ?? "";
551
+ }
552
+ function isDisabled(item) {
553
+ return item.getAttribute("aria-disabled") === "true";
554
+ }
555
+ function opensSubmenu(item) {
556
+ const popup = item.getAttribute("aria-haspopup");
557
+ return popup === "menu" || popup === "true";
558
+ }
559
+ function labelOf(item) {
560
+ return (item.getAttribute("aria-label") ?? item.textContent).trim();
561
+ }
562
+ function isTypeahead(event) {
563
+ return /^\S$/u.test(event.key) && !event.ctrlKey && !event.metaKey && !event.altKey;
564
+ }
565
+ function attachMenu(panel, options) {
566
+ let typed = "";
567
+ let typeaheadTimer;
568
+ let hovered = null;
569
+ let hoverTimer;
570
+ function items() {
571
+ return Array.from(panel.querySelectorAll(ITEM));
572
+ }
573
+ function itemOf(target) {
574
+ const item = target instanceof Element ? target.closest(ITEM) : null;
575
+ return item !== null && panel.contains(item) ? item : null;
576
+ }
577
+ function setTabStop(stop) {
578
+ for (const item of items()) {
579
+ item.tabIndex = item === stop ? 0 : -1;
580
+ }
581
+ }
582
+ function focus(item) {
583
+ setTabStop(item);
584
+ item.focus();
585
+ }
586
+ function openSubmenu(item, focusTo) {
587
+ if (!isDisabled(item)) {
588
+ options.onOpenSubmenu?.(idOf(item), { focus: focusTo });
589
+ }
590
+ }
591
+ function choose(item, focusTo) {
592
+ if (opensSubmenu(item)) {
593
+ openSubmenu(item, focusTo);
594
+ } else if (!isDisabled(item)) {
595
+ options.onActivate(idOf(item));
596
+ }
597
+ }
598
+ function typeahead(key, all, from) {
599
+ typed += key;
600
+ window.clearTimeout(typeaheadTimer);
601
+ typeaheadTimer = window.setTimeout(() => {
602
+ typed = "";
603
+ }, TYPEAHEAD_TIMEOUT);
604
+ const match = all[typeaheadIndex(all.map(labelOf), from, typed)];
605
+ if (match !== void 0) {
606
+ focus(match);
607
+ }
608
+ }
609
+ function onKeyDown2(event) {
610
+ if (event.isComposing) {
611
+ return;
612
+ }
613
+ const all = items();
614
+ const item = itemOf(event.target);
615
+ const from = item === null ? -1 : all.indexOf(item);
616
+ const move = MOVES[event.key];
617
+ if (move !== void 0) {
618
+ const next = all[nextMenuIndex(
619
+ all.map(() => AS_ENTRY),
620
+ from,
621
+ move
622
+ )];
623
+ if (next !== void 0) {
624
+ focus(next);
625
+ }
626
+ } else if (event.key === "Enter" || event.key === " ") {
627
+ if (item !== null) {
628
+ choose(item, "first");
629
+ }
630
+ } else if (event.key === "ArrowRight") {
631
+ if (item !== null && opensSubmenu(item)) {
632
+ openSubmenu(item, "first");
633
+ }
634
+ } else if (event.key === "ArrowLeft") {
635
+ options.onCloseSubmenu?.();
636
+ } else if (event.key === "Tab") {
637
+ options.onClose("tab");
638
+ } else if (isTypeahead(event)) {
639
+ typeahead(event.key, all, from);
640
+ } else {
641
+ return;
642
+ }
643
+ event.preventDefault();
644
+ }
645
+ function onFocusIn(event) {
646
+ const item = itemOf(event.target);
647
+ if (item !== null) {
648
+ setTabStop(item);
649
+ }
650
+ }
651
+ function onClick(event) {
652
+ const item = itemOf(event.target);
653
+ if (item !== null) {
654
+ choose(item, "none");
655
+ }
656
+ }
657
+ function onPointerMove(event) {
658
+ if (event.pointerType === "touch") {
659
+ return;
660
+ }
661
+ const item = itemOf(event.target);
662
+ if (item !== null && document.activeElement !== item) {
663
+ focus(item);
664
+ }
665
+ if (item === hovered) {
666
+ return;
667
+ }
668
+ hovered = item;
669
+ window.clearTimeout(hoverTimer);
670
+ if (item !== null) {
671
+ hoverTimer = window.setTimeout(() => {
672
+ if (opensSubmenu(item) && !isDisabled(item)) {
673
+ openSubmenu(item, "none");
674
+ } else {
675
+ options.onCollapseSubmenu?.();
676
+ }
677
+ }, HOVER_DELAY);
678
+ }
679
+ }
680
+ function onPointerLeave() {
681
+ hovered = null;
682
+ window.clearTimeout(hoverTimer);
683
+ }
684
+ const focused = itemOf(document.activeElement);
685
+ setTabStop(focused ?? items()[0]);
686
+ panel.addEventListener("keydown", onKeyDown2);
687
+ panel.addEventListener("focusin", onFocusIn);
688
+ panel.addEventListener("click", onClick);
689
+ panel.addEventListener("pointermove", onPointerMove);
690
+ panel.addEventListener("pointerleave", onPointerLeave);
691
+ return {
692
+ focusItem(which) {
693
+ const all = items();
694
+ const item = typeof which === "number" ? all[which] : all.find((candidate) => idOf(candidate) === which);
695
+ if (item !== void 0) {
696
+ focus(item);
697
+ }
698
+ },
699
+ detach() {
700
+ window.clearTimeout(typeaheadTimer);
701
+ window.clearTimeout(hoverTimer);
702
+ panel.removeEventListener("keydown", onKeyDown2);
703
+ panel.removeEventListener("focusin", onFocusIn);
704
+ panel.removeEventListener("click", onClick);
705
+ panel.removeEventListener("pointermove", onPointerMove);
706
+ panel.removeEventListener("pointerleave", onPointerLeave);
707
+ }
708
+ };
709
+ }
710
+
711
+ // src/overlay/overlayStack.ts
712
+ var stack = [];
713
+ function onKeyDown(event) {
714
+ const topmost = stack.at(-1);
715
+ if (event.key !== "Escape" || event.isComposing || topmost === void 0) {
716
+ return;
717
+ }
718
+ event.preventDefault();
719
+ event.stopPropagation();
720
+ topmost.onEscape();
721
+ }
722
+ function pushOverlay(overlay) {
723
+ if (stack.length === 0) {
724
+ window.addEventListener("keydown", onKeyDown, true);
725
+ }
726
+ stack.push(overlay);
727
+ }
728
+ function removeOverlay(overlay) {
729
+ const index = stack.indexOf(overlay);
730
+ if (index === -1) {
731
+ return;
732
+ }
733
+ const above = stack.splice(index).slice(1).reverse();
734
+ for (const child of above) {
735
+ child.onParentDetached();
736
+ }
737
+ if (stack.length === 0) {
738
+ window.removeEventListener("keydown", onKeyDown, true);
739
+ }
740
+ }
741
+ function isInsideOverlayAbove(overlay, target) {
742
+ const index = stack.indexOf(overlay);
743
+ return index !== -1 && stack.slice(index + 1).some((above) => above.panel.contains(target));
744
+ }
745
+
746
+ // src/overlay/placeOverlay.ts
747
+ var OPPOSITE_SIDE = {
748
+ top: "bottom",
749
+ bottom: "top",
750
+ left: "right",
751
+ right: "left"
752
+ };
753
+ function isVertical(side) {
754
+ return side === "top" || side === "bottom";
755
+ }
756
+ function roomBeside(side, anchor, viewport) {
757
+ switch (side) {
758
+ case "top":
759
+ return anchor.top;
760
+ case "bottom":
761
+ return viewport.height - (anchor.top + anchor.height);
762
+ case "left":
763
+ return anchor.left;
764
+ case "right":
765
+ return viewport.width - (anchor.left + anchor.width);
766
+ }
767
+ }
768
+ function chooseSide(preferred, needed, anchor, viewport) {
769
+ const opposite = OPPOSITE_SIDE[preferred];
770
+ const room = roomBeside(preferred, anchor, viewport);
771
+ const oppositeRoom = roomBeside(opposite, anchor, viewport);
772
+ if (room >= needed) {
773
+ return preferred;
774
+ }
775
+ return oppositeRoom >= needed || oppositeRoom > room ? opposite : preferred;
776
+ }
777
+ function chooseAlign(preferred, fitsAtStart, fitsAtEnd) {
778
+ if (preferred === "start") {
779
+ return fitsAtStart || !fitsAtEnd ? "start" : "end";
780
+ }
781
+ return fitsAtEnd || !fitsAtStart ? "end" : "start";
782
+ }
783
+ function offsetBeside(side, anchor, panel, gap) {
784
+ switch (side) {
785
+ case "top":
786
+ return anchor.top - gap - panel.height;
787
+ case "bottom":
788
+ return anchor.top + anchor.height + gap;
789
+ case "left":
790
+ return anchor.left - gap - panel.width;
791
+ case "right":
792
+ return anchor.left + anchor.width + gap;
793
+ }
794
+ }
795
+ function clampIntoView(value, limit) {
796
+ return Math.max(0, Math.min(value, limit));
797
+ }
798
+ function placeOverlay(anchor, panel, viewport, options = {}) {
799
+ const [preferredSide, preferredAlign] = (options.placement ?? "bottom-start").split("-");
800
+ const gap = options.gap ?? 0;
801
+ const offset = options.offset ?? 0;
802
+ const vertical = isVertical(preferredSide);
803
+ const side = chooseSide(
804
+ preferredSide,
805
+ (vertical ? panel.height : panel.width) + gap,
806
+ anchor,
807
+ viewport
808
+ );
809
+ const anchorStart = (vertical ? anchor.left : anchor.top) + offset;
810
+ const anchorEnd = anchorStart + (vertical ? anchor.width : anchor.height);
811
+ const extent = vertical ? panel.width : panel.height;
812
+ const room = vertical ? viewport.width : viewport.height;
813
+ const align = chooseAlign(
814
+ preferredAlign,
815
+ anchorStart + extent <= room,
816
+ anchorEnd - extent >= 0
817
+ );
818
+ const along = align === "start" ? anchorStart : anchorEnd - extent;
819
+ const away = offsetBeside(side, anchor, panel, gap);
820
+ return {
821
+ top: clampIntoView(vertical ? away : along, viewport.height - panel.height),
822
+ left: clampIntoView(vertical ? along : away, viewport.width - panel.width),
823
+ placement: `${side}-${align}`
824
+ };
825
+ }
826
+
827
+ // src/overlay/attachOverlay.ts
828
+ var FOCUSABLE = "a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]";
829
+ function anchorRect(anchor) {
830
+ if (anchor instanceof Element) {
831
+ const { top, left, width, height } = anchor.getBoundingClientRect();
832
+ return { top, left, width, height };
833
+ }
834
+ return { top: anchor.y, left: anchor.x, width: 0, height: 0 };
835
+ }
836
+ function initialFocusTarget(panel, initialFocus) {
837
+ if (initialFocus === "none") {
838
+ return null;
839
+ }
840
+ if (initialFocus instanceof HTMLElement) {
841
+ return initialFocus;
842
+ }
843
+ const first = initialFocus === "first" ? panel.querySelector(FOCUSABLE) : null;
844
+ if (first !== null) {
845
+ return first;
846
+ }
847
+ if (!panel.hasAttribute("tabindex")) {
848
+ panel.tabIndex = -1;
849
+ }
850
+ return panel;
851
+ }
852
+ function attachOverlay(anchor, panel, options) {
853
+ const { onDismiss } = options;
854
+ const returnFocusTo = options.returnFocusTo === void 0 ? document.activeElement instanceof HTMLElement ? document.activeElement : null : options.returnFocusTo;
855
+ const stacked = {
856
+ panel,
857
+ onEscape: () => {
858
+ onDismiss("escape");
859
+ },
860
+ onParentDetached: () => {
861
+ onDismiss("parent");
862
+ detach();
863
+ }
864
+ };
865
+ function inside(target) {
866
+ return target instanceof Node && (panel.contains(target) || isInsideOverlayAbove(stacked, target));
867
+ }
868
+ function belongs(target) {
869
+ return inside(target) || anchor instanceof Element && target instanceof Node && anchor.contains(target);
870
+ }
871
+ function onPointerDown(event) {
872
+ if (!belongs(event.target)) {
873
+ onDismiss("outside");
874
+ }
875
+ }
876
+ let settlingFrame = null;
877
+ function onInput() {
878
+ if (settlingFrame !== null) {
879
+ cancelAnimationFrame(settlingFrame);
880
+ }
881
+ settlingFrame = requestAnimationFrame(() => {
882
+ settlingFrame = requestAnimationFrame(() => {
883
+ settlingFrame = null;
884
+ });
885
+ });
886
+ }
887
+ function onScroll(event) {
888
+ if (!inside(event.target) && settlingFrame === null) {
889
+ onDismiss("scroll");
890
+ }
891
+ }
892
+ function onResize() {
893
+ onDismiss("resize");
894
+ }
895
+ function onFocusOut(event) {
896
+ if (event.relatedTarget !== null && !belongs(event.relatedTarget)) {
897
+ onDismiss("blur");
898
+ }
899
+ }
900
+ function onWindowBlur() {
901
+ onDismiss("blur");
902
+ }
903
+ let lastAnchorBox = null;
904
+ function anchorBox() {
905
+ if (lastAnchorBox === null || !(anchor instanceof Element) || anchor.isConnected) {
906
+ lastAnchorBox = anchorRect(anchor);
907
+ }
908
+ return lastAnchorBox;
909
+ }
910
+ function place() {
911
+ panel.style.top = "0px";
912
+ panel.style.left = "0px";
913
+ const { width, height } = panel.getBoundingClientRect();
914
+ const position = placeOverlay(
915
+ anchorBox(),
916
+ { width, height },
917
+ {
918
+ width: document.documentElement.clientWidth,
919
+ height: document.documentElement.clientHeight
920
+ },
921
+ options
922
+ );
923
+ panel.style.top = `${String(position.top)}px`;
924
+ panel.style.left = `${String(position.left)}px`;
925
+ panel.setAttribute("data-gridkit-placement", position.placement);
926
+ }
927
+ panel.style.position = "fixed";
928
+ place();
929
+ const resizeObserver = new ResizeObserver(place);
930
+ resizeObserver.observe(panel);
931
+ pushOverlay(stacked);
932
+ initialFocusTarget(panel, options.initialFocus ?? "first")?.focus({
933
+ preventScroll: true
934
+ });
935
+ document.addEventListener("pointerdown", onPointerDown, true);
936
+ window.addEventListener("scroll", onScroll, { capture: true, passive: true });
937
+ window.addEventListener("resize", onResize);
938
+ window.addEventListener("blur", onWindowBlur);
939
+ panel.addEventListener("focusout", onFocusOut);
940
+ if (options.ignoreScrollAfterInput === true) {
941
+ panel.addEventListener("input", onInput);
942
+ panel.addEventListener("change", onInput);
943
+ }
944
+ let attached = true;
945
+ function detach() {
946
+ if (!attached) {
947
+ return;
948
+ }
949
+ attached = false;
950
+ const active = document.activeElement;
951
+ const focusInside = active === null || active === document.body || inside(active);
952
+ removeOverlay(stacked);
953
+ resizeObserver.disconnect();
954
+ document.removeEventListener("pointerdown", onPointerDown, true);
955
+ window.removeEventListener("scroll", onScroll, { capture: true });
956
+ window.removeEventListener("resize", onResize);
957
+ window.removeEventListener("blur", onWindowBlur);
958
+ panel.removeEventListener("focusout", onFocusOut);
959
+ panel.removeEventListener("input", onInput);
960
+ panel.removeEventListener("change", onInput);
961
+ if (settlingFrame !== null) {
962
+ cancelAnimationFrame(settlingFrame);
963
+ }
964
+ if (returnFocusTo !== null && focusInside) {
965
+ returnFocusTo.focus({ preventScroll: true });
966
+ }
967
+ }
968
+ return detach;
969
+ }
970
+
971
+ // src/rowVirtualizer.ts
972
+ import { visibleRange } from "@gridkitjs/core";
973
+ function sameRange(a, b) {
974
+ return a.startIndex === b.startIndex && a.endIndex === b.endIndex && a.offsetBefore === b.offsetBefore && a.offsetAfter === b.offsetAfter;
975
+ }
976
+ function createRowVirtualizer(scrollElement, options) {
977
+ const { estimatedRowHeight, overscan, onRange } = options;
978
+ let heights = [];
979
+ let scrollTop = scrollElement.scrollTop;
980
+ let viewportHeight = scrollElement.clientHeight;
981
+ let range = null;
982
+ let destroyed = false;
983
+ let pendingScroll;
984
+ const elements = /* @__PURE__ */ new Map();
985
+ const indexByElement = /* @__PURE__ */ new Map();
986
+ const refCallbacks = /* @__PURE__ */ new Map();
987
+ function recompute() {
988
+ if (destroyed) {
989
+ return;
990
+ }
991
+ const next = visibleRange(
992
+ heights,
993
+ estimatedRowHeight,
994
+ scrollTop,
995
+ viewportHeight,
996
+ overscan
997
+ );
998
+ if (range !== null && sameRange(range, next)) {
999
+ return;
1000
+ }
1001
+ range = next;
1002
+ onRange(next);
1003
+ }
1004
+ const rowObserver = new ResizeObserver((entries) => {
1005
+ let changed = false;
1006
+ for (const entry of entries) {
1007
+ const index = indexByElement.get(entry.target);
1008
+ if (index === void 0) continue;
1009
+ const height = entry.target.getBoundingClientRect().height;
1010
+ if (heights[index] !== height) {
1011
+ heights[index] = height;
1012
+ changed = true;
1013
+ }
1014
+ }
1015
+ if (changed) {
1016
+ recompute();
1017
+ }
1018
+ });
1019
+ const viewportObserver = new ResizeObserver(() => {
1020
+ viewportHeight = scrollElement.clientHeight;
1021
+ recompute();
1022
+ });
1023
+ viewportObserver.observe(scrollElement);
1024
+ function handleScroll() {
1025
+ scrollTop = scrollElement.scrollTop;
1026
+ recompute();
1027
+ }
1028
+ scrollElement.addEventListener("scroll", handleScroll, { passive: true });
1029
+ function estimateOffsetBefore(index) {
1030
+ let total = 0;
1031
+ for (let current = 0; current < index; current++) {
1032
+ total += heights[current] ?? estimatedRowHeight;
1033
+ }
1034
+ return total;
1035
+ }
1036
+ recompute();
1037
+ return {
1038
+ setRowCount(count) {
1039
+ heights = Array.from({ length: count }, (_, index) => heights[index]);
1040
+ recompute();
1041
+ },
1042
+ resetHeights() {
1043
+ heights = new Array(heights.length).fill(void 0);
1044
+ recompute();
1045
+ },
1046
+ measureRow(index) {
1047
+ let callback = refCallbacks.get(index);
1048
+ if (callback === void 0) {
1049
+ callback = (element) => {
1050
+ const previous = elements.get(index);
1051
+ if (previous !== void 0) {
1052
+ rowObserver.unobserve(previous);
1053
+ indexByElement.delete(previous);
1054
+ elements.delete(index);
1055
+ }
1056
+ if (element === null || destroyed) {
1057
+ return;
1058
+ }
1059
+ elements.set(index, element);
1060
+ indexByElement.set(element, index);
1061
+ rowObserver.observe(element);
1062
+ if (pendingScroll?.index === index) {
1063
+ element.scrollIntoView(pendingScroll.options);
1064
+ pendingScroll = void 0;
1065
+ }
1066
+ };
1067
+ refCallbacks.set(index, callback);
1068
+ }
1069
+ return callback;
1070
+ },
1071
+ scrollToIndex(index, scrollOptions) {
1072
+ if (heights.length === 0) {
1073
+ return;
1074
+ }
1075
+ const clamped = Math.max(0, Math.min(index, heights.length - 1));
1076
+ const mounted = elements.get(clamped);
1077
+ if (mounted !== void 0) {
1078
+ mounted.scrollIntoView(scrollOptions);
1079
+ return;
1080
+ }
1081
+ pendingScroll = { index: clamped, options: scrollOptions };
1082
+ scrollElement.scrollTop = estimateOffsetBefore(clamped);
1083
+ },
1084
+ destroy() {
1085
+ destroyed = true;
1086
+ pendingScroll = void 0;
1087
+ scrollElement.removeEventListener("scroll", handleScroll);
1088
+ viewportObserver.disconnect();
1089
+ rowObserver.disconnect();
1090
+ elements.clear();
1091
+ indexByElement.clear();
1092
+ }
1093
+ };
1094
+ }
1095
+
1096
+ // src/toolbar/attachToolbar.ts
1097
+ import { nextMenuIndex as nextMenuIndex2 } from "@gridkitjs/core";
1098
+ var ENTRY = "[data-gridkit-toolbar-item]";
1099
+ var FOCUSABLE2 = [
1100
+ "button:not(:disabled)",
1101
+ "input:not(:disabled)",
1102
+ "select:not(:disabled)",
1103
+ "textarea:not(:disabled)",
1104
+ "a[href]",
1105
+ "[tabindex]"
1106
+ ].join(", ");
1107
+ var MOVES2 = {
1108
+ ArrowRight: "next",
1109
+ ArrowLeft: "previous",
1110
+ Home: "first",
1111
+ End: "last"
1112
+ };
1113
+ var AS_ENTRY2 = { type: "item" };
1114
+ var CARETLESS_INPUTS = /* @__PURE__ */ new Set([
1115
+ "button",
1116
+ "checkbox",
1117
+ "color",
1118
+ "file",
1119
+ "image",
1120
+ "radio",
1121
+ "range",
1122
+ "reset",
1123
+ "submit"
1124
+ ]);
1125
+ function targetOf(entry) {
1126
+ return entry.matches(FOCUSABLE2) ? entry : entry.querySelector(FOCUSABLE2);
1127
+ }
1128
+ function textFieldOf(target) {
1129
+ return target instanceof HTMLTextAreaElement || target instanceof HTMLInputElement && !CARETLESS_INPUTS.has(target.type) ? target : null;
1130
+ }
1131
+ function belongsToField(target, move) {
1132
+ if (target instanceof HTMLElement && target.isContentEditable) {
1133
+ return true;
1134
+ }
1135
+ const field = textFieldOf(target);
1136
+ if (field === null) {
1137
+ return false;
1138
+ }
1139
+ const { selectionStart, selectionEnd, value } = field;
1140
+ if (move === "first" || move === "last" || selectionStart === null || selectionStart !== selectionEnd) {
1141
+ return true;
1142
+ }
1143
+ return move === "previous" ? selectionStart > 0 : selectionStart < value.length;
1144
+ }
1145
+ function attachToolbar(toolbar) {
1146
+ let stop;
1147
+ function controls() {
1148
+ return Array.from(toolbar.querySelectorAll(ENTRY)).flatMap(
1149
+ (entry) => {
1150
+ const target = targetOf(entry);
1151
+ return target === null ? [] : [{ entry, target }];
1152
+ }
1153
+ );
1154
+ }
1155
+ function indexOf(all2, node) {
1156
+ return node instanceof Node ? all2.findIndex((control) => control.entry.contains(node)) : -1;
1157
+ }
1158
+ function setTabStop(next) {
1159
+ stop = next;
1160
+ for (const { target } of controls()) {
1161
+ target.tabIndex = target === next ? 0 : -1;
1162
+ }
1163
+ }
1164
+ function onKeyDown2(event) {
1165
+ const move = MOVES2[event.key];
1166
+ if (move === void 0 || event.isComposing || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey || belongsToField(event.target, move)) {
1167
+ return;
1168
+ }
1169
+ const all2 = controls();
1170
+ const from = indexOf(all2, event.target);
1171
+ if (from === -1) {
1172
+ return;
1173
+ }
1174
+ const next = all2[nextMenuIndex2(
1175
+ all2.map(() => AS_ENTRY2),
1176
+ from,
1177
+ move
1178
+ )];
1179
+ if (next !== void 0) {
1180
+ event.preventDefault();
1181
+ setTabStop(next.target);
1182
+ next.target.focus();
1183
+ }
1184
+ }
1185
+ function onFocusIn(event) {
1186
+ const all2 = controls();
1187
+ const control = all2[indexOf(all2, event.target)];
1188
+ if (control !== void 0) {
1189
+ setTabStop(control.target);
1190
+ }
1191
+ }
1192
+ const observer = new MutationObserver(() => {
1193
+ const all2 = controls();
1194
+ setTabStop(
1195
+ all2.find(({ target }) => target === stop)?.target ?? all2[0]?.target
1196
+ );
1197
+ });
1198
+ const all = controls();
1199
+ setTabStop(
1200
+ all[indexOf(all, document.activeElement)]?.target ?? all[0]?.target
1201
+ );
1202
+ toolbar.addEventListener("keydown", onKeyDown2);
1203
+ toolbar.addEventListener("focusin", onFocusIn);
1204
+ observer.observe(toolbar, { childList: true, subtree: true });
1205
+ return () => {
1206
+ observer.disconnect();
1207
+ toolbar.removeEventListener("keydown", onKeyDown2);
1208
+ toolbar.removeEventListener("focusin", onFocusIn);
1209
+ };
1210
+ }
1211
+
1212
+ // src/toolbar/observeToolbarOverflow.ts
1213
+ import {
1214
+ fitToolbarItems,
1215
+ isPinnedToolbarItem
1216
+ } from "@gridkitjs/core";
1217
+ var ENTRY_ATTRIBUTE = "data-gridkit-toolbar-item";
1218
+ var MORE_ATTRIBUTE = "data-gridkit-toolbar-more";
1219
+ function pixels(value) {
1220
+ return Number.parseFloat(value) || 0;
1221
+ }
1222
+ function outerWidth(element) {
1223
+ const style = getComputedStyle(element);
1224
+ return element.getBoundingClientRect().width + pixels(style.marginLeft) + pixels(style.marginRight);
1225
+ }
1226
+ function observeToolbarOverflow(toolbar, options) {
1227
+ let current = options;
1228
+ const widths = /* @__PURE__ */ new Map();
1229
+ let moreWidth = 0;
1230
+ let reported;
1231
+ function drawnEntries() {
1232
+ return Array.from(
1233
+ toolbar.querySelectorAll(`[${ENTRY_ATTRIBUTE}]`)
1234
+ );
1235
+ }
1236
+ function measure() {
1237
+ for (const element of drawnEntries()) {
1238
+ if (element.hasAttribute(MORE_ATTRIBUTE)) {
1239
+ moreWidth = outerWidth(element);
1240
+ } else {
1241
+ widths.set(
1242
+ element.getAttribute(ENTRY_ATTRIBUTE) ?? "",
1243
+ outerWidth(element)
1244
+ );
1245
+ }
1246
+ }
1247
+ const style = getComputedStyle(toolbar);
1248
+ const gap = pixels(style.columnGap);
1249
+ const fit = fitToolbarItems({
1250
+ widths: current.items.map(
1251
+ (item) => (item.type === "spacer" ? 0 : widths.get(item.key) ?? 0) + gap
1252
+ ),
1253
+ available: toolbar.clientWidth - pixels(style.paddingLeft) - pixels(style.paddingRight) + gap,
1254
+ moreWidth: moreWidth + gap,
1255
+ pinned: current.items.map(isPinnedToolbarItem)
1256
+ });
1257
+ if (fit !== reported) {
1258
+ reported = fit;
1259
+ current.onChange(fit);
1260
+ }
1261
+ }
1262
+ const resizes = new ResizeObserver(measure);
1263
+ function observeSizes() {
1264
+ resizes.disconnect();
1265
+ resizes.observe(toolbar);
1266
+ for (const element of drawnEntries()) {
1267
+ resizes.observe(element);
1268
+ }
1269
+ }
1270
+ const draws = new MutationObserver(() => {
1271
+ observeSizes();
1272
+ measure();
1273
+ });
1274
+ observeSizes();
1275
+ draws.observe(toolbar, { childList: true, subtree: true });
1276
+ measure();
1277
+ return {
1278
+ update(next) {
1279
+ const labels = new Map(
1280
+ current.items.map((item) => [item.key, item.label])
1281
+ );
1282
+ for (const item of next.items) {
1283
+ if (labels.has(item.key) && labels.get(item.key) !== item.label) {
1284
+ widths.delete(item.key);
1285
+ }
1286
+ }
1287
+ current = next;
1288
+ measure();
1289
+ },
1290
+ detach() {
1291
+ resizes.disconnect();
1292
+ draws.disconnect();
1293
+ }
1294
+ };
1295
+ }
1296
+ export {
1297
+ NO_DRAG,
1298
+ attachContextMenuTrigger,
1299
+ attachInfiniteScroll,
1300
+ attachMenu,
1301
+ attachOverlay,
1302
+ attachToolbar,
1303
+ bodyCellFrom,
1304
+ bodyRowFrom,
1305
+ createGridFocus,
1306
+ createLiveAnnouncer,
1307
+ createRowVirtualizer,
1308
+ findBodyRow,
1309
+ groupRowFrom,
1310
+ measureColumnContent,
1311
+ measurePageSize,
1312
+ observeElementWidth,
1313
+ observeToolbarOverflow,
1314
+ placeOverlay,
1315
+ resolveColumnDropTarget,
1316
+ resolveGroupByDropTarget,
1317
+ startColumnResizeGesture,
1318
+ startDragReorder
1319
+ };
1320
+ //# sourceMappingURL=index.js.map