data-navigator 3.0.0 → 3.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 CHANGED
@@ -80,9 +80,9 @@ var defaultKeyBindings = {
80
80
  Escape: "drill-out",
81
81
  Enter: "drill-in"
82
82
  };
83
- var TypicallyUnreservedKeys = ["KeyW", "KeyJ", "LeftBracket", "RightBracket", "Slash", "Backslash"];
83
+ var TypicallyUnreservedKeys = ["KeyW", "KeyJ", "BracketLeft", "BracketRight", "Slash", "Backslash"];
84
84
  var TypicallyUnreservedKeyPairs = [
85
- ["LeftBracket", "RightBracket"],
85
+ ["BracketLeft", "BracketRight"],
86
86
  ["Slash", "Backslash"]
87
87
  ];
88
88
  var GenericFullNavigationRules = {
@@ -209,6 +209,27 @@ var NodeElementDefaults = {
209
209
  spatialProperties: void 0
210
210
  }
211
211
  };
212
+ var KeyLabels = {
213
+ ArrowLeft: "\u2190",
214
+ ArrowRight: "\u2192",
215
+ ArrowUp: "\u2191",
216
+ ArrowDown: "\u2193",
217
+ Enter: "Enter",
218
+ Backspace: "Backspace",
219
+ Escape: "Esc",
220
+ Space: "Space",
221
+ Tab: "Tab",
222
+ BracketLeft: "[",
223
+ BracketRight: "]",
224
+ Backslash: "\\",
225
+ Slash: "/",
226
+ Comma: ",",
227
+ Period: ".",
228
+ Semicolon: ";",
229
+ Quote: "'",
230
+ Minus: "-",
231
+ Equal: "="
232
+ };
212
233
  var GenericNavigationRuleCommands = {
213
234
  "drill-in": { label: "Enter", description: "Drill in" },
214
235
  "drill-out": { label: "Backspace", description: "Drill out" },
@@ -243,13 +264,423 @@ var describeNode = (d, descriptionOptions) => {
243
264
  var createValidId = (s) => {
244
265
  return "_" + s.replace(/[^a-zA-Z0-9_-]+/g, "_");
245
266
  };
246
- function getGenericCommandsFromNavRules(navigationRules) {
267
+ var keyLabel = (code) => {
268
+ if (!code)
269
+ return "";
270
+ return KeyLabels[code] || code.replace(/^Key/, "").replace(/^Digit/, "");
271
+ };
272
+ var humanizeRule = (navId) => {
273
+ const text = navId.replace(/[-_]+/g, " ").trim();
274
+ return text.charAt(0).toUpperCase() + text.slice(1);
275
+ };
276
+ function getGenericCommandsFromNavRules(navigationRules, descriptions) {
247
277
  if (!navigationRules) {
248
278
  return [];
249
279
  }
250
- return Object.keys(navigationRules).map((navId) => GenericNavigationRuleCommands[navId]).filter(Boolean);
280
+ return Object.keys(navigationRules).map((navId) => {
281
+ const rule = navigationRules[navId];
282
+ const generic = GenericNavigationRuleCommands[navId];
283
+ return {
284
+ label: (rule == null ? void 0 : rule.key) ? keyLabel(rule.key) : (generic == null ? void 0 : generic.label) || "",
285
+ description: (descriptions == null ? void 0 : descriptions[navId]) || (generic == null ? void 0 : generic.description) || humanizeRule(navId),
286
+ command: navId
287
+ };
288
+ });
251
289
  }
252
290
 
291
+ // src/edge-utils.ts
292
+ var makeEdgeCreator = (nodes, edges, useDirectedEdges) => {
293
+ const addEdgeToNode = (nodeId, edgeId) => {
294
+ const node = nodes[nodeId];
295
+ if (!node) {
296
+ console.error(`Building edges. Node ${nodeId} does not exist, so edge ${edgeId} was not added to it.`);
297
+ return;
298
+ }
299
+ if (!node.edges) {
300
+ node.edges = [];
301
+ }
302
+ if (node.edges.indexOf(edgeId) === -1) {
303
+ node.edges.push(edgeId);
304
+ }
305
+ };
306
+ return (source, target, rules, addTo) => {
307
+ if (!source || !target || source === target) {
308
+ return;
309
+ }
310
+ const id = `${source}-${target}`;
311
+ const targetId = !useDirectedEdges ? id : `${target}-${id}`;
312
+ const addToSource = !addTo || addTo === "source";
313
+ const addToTarget = !addTo || addTo === "target";
314
+ const checkEdgeRules = (eId) => {
315
+ if (edges[eId]) {
316
+ (rules || []).forEach((r) => {
317
+ if (edges[eId].navigationRules.indexOf(r) === -1) {
318
+ edges[eId].navigationRules.push(r);
319
+ }
320
+ });
321
+ } else {
322
+ edges[eId] = {
323
+ source,
324
+ target,
325
+ navigationRules: rules ? [...rules] : []
326
+ };
327
+ }
328
+ };
329
+ checkEdgeRules(id);
330
+ if (useDirectedEdges && addToTarget) {
331
+ checkEdgeRules(targetId);
332
+ }
333
+ if (addToSource) {
334
+ addEdgeToNode(source, id);
335
+ }
336
+ if (addToTarget) {
337
+ addEdgeToNode(target, targetId);
338
+ }
339
+ };
340
+ };
341
+ var chain = (createEdge, ids, rules, extents = "terminal") => {
342
+ for (let i = 0; i < ids.length - 1; i++) {
343
+ createEdge(ids[i], ids[i + 1], rules);
344
+ }
345
+ if (extents === "circular" && ids.length > 1) {
346
+ createEdge(ids[ids.length - 1], ids[0], rules);
347
+ }
348
+ };
349
+
350
+ // src/frame.ts
351
+ var prepareFrameOptions = (options) => {
352
+ var _a, _b, _c;
353
+ const f = options.frame;
354
+ const dimCount = ((_b = (_a = options.dimensions) == null ? void 0 : _a.values) == null ? void 0 : _b.length) || 0;
355
+ if (!f || dimCount < 2 || ((_c = options.dimensions.parentOptions) == null ? void 0 : _c.addLevel0)) {
356
+ return options;
357
+ }
358
+ const data = f.data || { id: "data", edges: [], semantics: { label: "Data" } };
359
+ return __spreadProps(__spreadValues({}, options), {
360
+ dimensions: __spreadProps(__spreadValues({}, options.dimensions), {
361
+ parentOptions: __spreadProps(__spreadValues({}, options.dimensions.parentOptions || {}), {
362
+ addLevel0: __spreadProps(__spreadValues({}, data), { edges: data.edges || [] })
363
+ })
364
+ })
365
+ });
366
+ };
367
+ var buildFrame = (options, nodes, edges, topId) => {
368
+ var _a, _b, _c;
369
+ const f = options.frame;
370
+ if (!f)
371
+ return;
372
+ if (!topId || !nodes[topId]) {
373
+ console.error("Building frame. No top data node was found to place under the frame.");
374
+ return;
375
+ }
376
+ const createEdge = makeEdgeCreator(nodes, edges, options.useDirectedEdges);
377
+ const siblingRules = ((_a = f.navigationRules) == null ? void 0 : _a.sibling_sibling) || ["left", "right"];
378
+ const parentRules = ((_b = f.navigationRules) == null ? void 0 : _b.parent_child) || ["drill-out", "drill-in"];
379
+ const extents = ((_c = f.behavior) == null ? void 0 : _c.extents) || "circular";
380
+ const root = f.root;
381
+ nodes[root.id] = __spreadProps(__spreadValues({}, root), { edges: [...root.edges || []], depth: 0, frameRole: "root" });
382
+ const elementIds = (f.elements || []).map((e) => {
383
+ nodes[e.id] = __spreadProps(__spreadValues({}, e), {
384
+ edges: [...e.edges || []],
385
+ depth: 1,
386
+ parentId: root.id,
387
+ frameRole: "element"
388
+ });
389
+ return e.id;
390
+ });
391
+ let dataId = topId;
392
+ if (f.data && f.data.id !== topId) {
393
+ nodes[f.data.id] = __spreadProps(__spreadValues({}, f.data), { edges: [...f.data.edges || []] });
394
+ createEdge(f.data.id, topId, parentRules, "source");
395
+ createEdge(f.data.id, topId, parentRules, "target");
396
+ nodes[topId].parentId = f.data.id;
397
+ dataId = f.data.id;
398
+ }
399
+ const dataNode = nodes[dataId];
400
+ dataNode.frameRole = "data";
401
+ dataNode.depth = 1;
402
+ dataNode.parentId = root.id;
403
+ const children = [...elementIds, dataId];
404
+ createEdge(root.id, children[0], parentRules, "source");
405
+ children.forEach((c) => createEdge(root.id, c, parentRules, "target"));
406
+ chain(createEdge, children, siblingRules, extents);
407
+ return { rootId: root.id, elementIds, dataId, parentRules };
408
+ };
409
+
410
+ // src/spatial-grid.ts
411
+ var buildSpatialGrid = (options, nodes, edges) => {
412
+ var _a, _b, _c;
413
+ const g = options.spatialGrid;
414
+ if (!g)
415
+ return;
416
+ const createEdge = makeEdgeCreator(nodes, edges, options.useDirectedEdges);
417
+ const xRules = ((_a = g.navigationRules) == null ? void 0 : _a.x) || ["left", "right"];
418
+ const yRules = ((_b = g.navigationRules) == null ? void 0 : _b.y) || ["up", "down"];
419
+ const parentRules = ((_c = g.navigationRules) == null ? void 0 : _c.parent_child) || ["drill-out", "drill-in"];
420
+ const extents = g.extents || "terminal";
421
+ const across = g.levelNavigation !== "within";
422
+ const skipEmpty = g.skipEmpty !== false;
423
+ const leafMode = g.leaves || "points";
424
+ const idOf = (d) => d[typeof options.idKey === "function" ? options.idKey(d) : options.idKey];
425
+ const rows = options.data.filter((d) => typeof d[g.xKey] === "number" && typeof d[g.yKey] === "number");
426
+ const ext = (key, given) => {
427
+ if (given)
428
+ return given;
429
+ let min = Infinity;
430
+ let max = -Infinity;
431
+ rows.forEach((d) => {
432
+ min = Math.min(min, d[key]);
433
+ max = Math.max(max, d[key]);
434
+ });
435
+ return [min, max];
436
+ };
437
+ const xExtent = ext(g.xKey, g.xExtent);
438
+ const yExtent = ext(g.yKey, g.yExtent);
439
+ const indexOf = (v, [lo, hi], n) => {
440
+ if (hi === lo)
441
+ return 0;
442
+ return Math.max(0, Math.min(n - 1, Math.floor((v - lo) / (hi - lo) * n)));
443
+ };
444
+ const rootDefaults = { id: "grid", edges: [], semantics: { label: "Grid" } };
445
+ const root = __spreadValues(__spreadValues({}, rootDefaults), g.root || {});
446
+ root.edges = root.edges || [];
447
+ root.depth = 0;
448
+ root.data = __spreadProps(__spreadValues({}, root.data || {}), {
449
+ xKey: g.xKey,
450
+ yKey: g.yKey,
451
+ xExtent,
452
+ yExtent,
453
+ levels: g.levels,
454
+ count: rows.length
455
+ });
456
+ nodes[root.id] = root;
457
+ const cellId = (level, col, row) => g.cellIds ? g.cellIds(level, col, row) : createValidId(`${root.id}_L${level}_${col}_${row}`);
458
+ const cellsByLevel = [];
459
+ g.levels.forEach((n, level) => {
460
+ const cells = {};
461
+ const add = (col, row) => {
462
+ const key = `${col}_${row}`;
463
+ if (cells[key])
464
+ return cells[key];
465
+ const id = cellId(level, col, row);
466
+ const xStep = (xExtent[1] - xExtent[0]) / n;
467
+ const yStep = (yExtent[1] - yExtent[0]) / n;
468
+ let parent = root.id;
469
+ if (level > 0) {
470
+ const pn = g.levels[level - 1];
471
+ const parentCell = cellsByLevel[level - 1][`${Math.floor(col * pn / n)}_${Math.floor(row * pn / n)}`];
472
+ parent = parentCell == null ? void 0 : parentCell.id;
473
+ parentCell == null ? void 0 : parentCell.children.push(id);
474
+ }
475
+ cells[key] = { id, col, row, parent, children: [] };
476
+ nodes[id] = {
477
+ id,
478
+ renderId: id,
479
+ edges: [],
480
+ depth: level + 1,
481
+ parentId: parent,
482
+ data: {
483
+ level,
484
+ col,
485
+ row,
486
+ cellsPerAxis: n,
487
+ xExtent: [xExtent[0] + col * xStep, xExtent[0] + (col + 1) * xStep],
488
+ yExtent: [yExtent[0] + row * yStep, yExtent[0] + (row + 1) * yStep],
489
+ count: 0
490
+ }
491
+ };
492
+ return cells[key];
493
+ };
494
+ if (!skipEmpty) {
495
+ for (let c = 0; c < n; c++)
496
+ for (let r = 0; r < n; r++)
497
+ add(c, r);
498
+ }
499
+ rows.forEach((d) => add(indexOf(d[g.xKey], xExtent, n), indexOf(d[g.yKey], yExtent, n)));
500
+ cellsByLevel.push(cells);
501
+ });
502
+ const finest = cellsByLevel[cellsByLevel.length - 1];
503
+ const fn = g.levels[g.levels.length - 1];
504
+ const leafIds = [];
505
+ const leafParent = {};
506
+ rows.forEach((d) => {
507
+ const id = idOf(d);
508
+ if (!nodes[id])
509
+ return;
510
+ g.levels.forEach((n, level) => {
511
+ const c = cellsByLevel[level][`${indexOf(d[g.xKey], xExtent, n)}_${indexOf(d[g.yKey], yExtent, n)}`];
512
+ nodes[c.id].data.count++;
513
+ });
514
+ const cell = finest[`${indexOf(d[g.xKey], xExtent, fn)}_${indexOf(d[g.yKey], yExtent, fn)}`];
515
+ cell.children.push(id);
516
+ leafParent[id] = cell.id;
517
+ leafIds.push(id);
518
+ nodes[id].parentId = cell.id;
519
+ nodes[id].depth = g.levels.length + 1;
520
+ });
521
+ const topLeftFirst = (a, b) => b.row - a.row || a.col - b.col;
522
+ const rootChildren = Object.values(cellsByLevel[0]).sort(topLeftFirst);
523
+ if (rootChildren.length)
524
+ createEdge(root.id, rootChildren[0].id, parentRules, "source");
525
+ rootChildren.forEach((c) => createEdge(root.id, c.id, parentRules, "target"));
526
+ const pos = (id) => nodes[id].data;
527
+ cellsByLevel.forEach((cells, level) => {
528
+ Object.values(cells).forEach((c) => {
529
+ if (!c.children.length)
530
+ return;
531
+ let first;
532
+ if (level === cellsByLevel.length - 1) {
533
+ first = [...c.children].sort((a, b) => leafOrderX(a, b))[0];
534
+ } else {
535
+ first = [...c.children].sort((a, b) => topLeftFirst(pos(a), pos(b)))[0];
536
+ }
537
+ createEdge(c.id, first, parentRules, "source");
538
+ c.children.forEach((k) => createEdge(c.id, k, parentRules, "target"));
539
+ });
540
+ });
541
+ const linkCells = (ids) => {
542
+ const byRow = {};
543
+ const byCol = {};
544
+ ids.forEach((id) => {
545
+ const p = pos(id);
546
+ (byRow[p.row] = byRow[p.row] || []).push(id);
547
+ (byCol[p.col] = byCol[p.col] || []).push(id);
548
+ });
549
+ Object.values(byRow).forEach(
550
+ (r) => chain(
551
+ createEdge,
552
+ r.sort((a, b) => pos(a).col - pos(b).col),
553
+ xRules,
554
+ extents
555
+ )
556
+ );
557
+ Object.values(byCol).forEach(
558
+ (c) => chain(
559
+ createEdge,
560
+ c.sort((a, b) => pos(b).row - pos(a).row),
561
+ yRules,
562
+ extents
563
+ )
564
+ );
565
+ };
566
+ cellsByLevel.forEach((cells, level) => {
567
+ const list = Object.values(cells);
568
+ if (across || level === 0) {
569
+ linkCells(list.map((c) => c.id));
570
+ } else {
571
+ const groups = {};
572
+ list.forEach((c) => (groups[c.parent] = groups[c.parent] || []).push(c.id));
573
+ Object.values(groups).forEach(linkCells);
574
+ }
575
+ });
576
+ function leafOrderX(a, b) {
577
+ const da = nodes[a].data;
578
+ const db = nodes[b].data;
579
+ return da[g.xKey] - db[g.xKey] || db[g.yKey] - da[g.yKey];
580
+ }
581
+ const leafOrderY = (a, b) => {
582
+ const da = nodes[a].data;
583
+ const db = nodes[b].data;
584
+ return db[g.yKey] - da[g.yKey] || da[g.xKey] - db[g.xKey];
585
+ };
586
+ const linkLeaves = (ids) => {
587
+ if (leafMode === "cells") {
588
+ const byY = {};
589
+ const byX = {};
590
+ ids.forEach((id) => {
591
+ const d = nodes[id].data;
592
+ (byY[d[g.yKey]] = byY[d[g.yKey]] || []).push(id);
593
+ (byX[d[g.xKey]] = byX[d[g.xKey]] || []).push(id);
594
+ });
595
+ Object.values(byY).forEach((r) => chain(createEdge, r.sort(leafOrderX), xRules, extents));
596
+ Object.values(byX).forEach((c) => chain(createEdge, c.sort(leafOrderY), yRules, extents));
597
+ } else {
598
+ chain(createEdge, [...ids].sort(leafOrderX), xRules, extents);
599
+ chain(createEdge, [...ids].sort(leafOrderY), yRules, extents);
600
+ }
601
+ };
602
+ if (across) {
603
+ linkLeaves(leafIds);
604
+ } else {
605
+ Object.values(finest).forEach((c) => linkLeaves(c.children));
606
+ }
607
+ return {
608
+ rootId: root.id,
609
+ levels: g.levels,
610
+ cellsByLevel: cellsByLevel.map((cells) => Object.values(cells).map((c) => c.id)),
611
+ leafIds,
612
+ parentRules
613
+ };
614
+ };
615
+
616
+ // src/hierarchy.ts
617
+ var buildHierarchy = (options, nodes, edges) => {
618
+ var _a, _b;
619
+ const h = options.hierarchy;
620
+ if (!h)
621
+ return;
622
+ const createEdge = makeEdgeCreator(nodes, edges, options.useDirectedEdges);
623
+ const siblingRules = ((_a = h.navigationRules) == null ? void 0 : _a.sibling_sibling) || ["left", "right"];
624
+ const parentRules = ((_b = h.navigationRules) == null ? void 0 : _b.parent_child) || ["drill-out", "drill-in"];
625
+ const extents = h.extents || "circular";
626
+ const idOf = (d) => d[typeof options.idKey === "function" ? options.idKey(d) : options.idKey];
627
+ const children = {};
628
+ let rootId;
629
+ options.data.forEach((d) => {
630
+ const id = idOf(d);
631
+ const parent = d[h.parentKey];
632
+ if (parent === void 0 || parent === null || parent === "") {
633
+ if (rootId) {
634
+ console.error(
635
+ `Building hierarchy. More than one root was found: ${rootId} and ${id}. Using ${rootId}.`
636
+ );
637
+ return;
638
+ }
639
+ rootId = id;
640
+ } else {
641
+ if (!children[parent])
642
+ children[parent] = [];
643
+ children[parent].push(d);
644
+ }
645
+ });
646
+ if (!rootId) {
647
+ console.error("Building hierarchy. No root row was found. One row must have an empty parent.");
648
+ return;
649
+ }
650
+ const byDepth = [];
651
+ const visit = (id, parentId, depth) => {
652
+ const node = nodes[id];
653
+ if (!node) {
654
+ console.error(`Building hierarchy. Row ${id} has no node. Check idKey.`);
655
+ return;
656
+ }
657
+ node.depth = depth;
658
+ if (parentId)
659
+ node.parentId = parentId;
660
+ if (!byDepth[depth])
661
+ byDepth[depth] = [];
662
+ byDepth[depth].push(id);
663
+ let kids = children[id] || [];
664
+ if (h.sortFunction)
665
+ kids = [...kids].sort((a, b) => h.sortFunction(a, b));
666
+ const kidIds = kids.map(idOf);
667
+ node.childCount = kidIds.length;
668
+ if (kidIds.length) {
669
+ createEdge(id, kidIds[0], parentRules, "source");
670
+ kidIds.forEach((k) => createEdge(id, k, parentRules, "target"));
671
+ if (h.levelNavigation !== "across") {
672
+ chain(createEdge, kidIds, siblingRules, extents);
673
+ }
674
+ }
675
+ kidIds.forEach((k) => visit(k, id, depth + 1));
676
+ };
677
+ visit(rootId, void 0, 0);
678
+ if (h.levelNavigation === "across") {
679
+ byDepth.forEach((ids) => chain(createEdge, ids, siblingRules, extents));
680
+ }
681
+ return { rootId, depthCount: byDepth.length, parentRules };
682
+ };
683
+
253
684
  // src/structure.ts
254
685
  var structure_default = (options) => {
255
686
  if (options.dataType === "vega-lite" || options.dataType === "vl" || options.dataType === "Vega-Lite") {
@@ -726,9 +1157,9 @@ var scaffoldDimensions = (options, nodes) => {
726
1157
  }
727
1158
  return dimensions;
728
1159
  };
729
- var buildEdges = (options, nodes, dimensions) => {
1160
+ var buildEdges = (options, nodes, dimensions, existingEdges) => {
730
1161
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
731
- let edges = {};
1162
+ let edges = existingEdges || {};
732
1163
  const addEdgeToNode = (nodeId, edgeId) => {
733
1164
  if (nodes[nodeId].edges.indexOf(edgeId) === -1) {
734
1165
  nodes[nodeId].edges.push(edgeId);
@@ -802,7 +1233,7 @@ var buildEdges = (options, nodes, dimensions) => {
802
1233
  createEdge(level1Node.id, nextLevel1Node.id, siblingRules);
803
1234
  }
804
1235
  if (!l && extents === "bridgedCustom") {
805
- createEdge(po.level1Options.behavior.customBridgePost, level1Node.id, siblingRules);
1236
+ createEdge(po.level1Options.behavior.customBridgePrevious, level1Node.id, siblingRules);
806
1237
  }
807
1238
  l++;
808
1239
  });
@@ -989,7 +1420,7 @@ var buildEdges = (options, nodes, dimensions) => {
989
1420
  return edges;
990
1421
  };
991
1422
  var buildRules = (options, edges, dimensions) => {
992
- var _a, _b, _c, _d;
1423
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
993
1424
  let rules = options.navigationRules;
994
1425
  if (!rules) {
995
1426
  let dimKeys = Object.keys(dimensions || {});
@@ -1093,6 +1524,20 @@ var buildRules = (options, edges, dimensions) => {
1093
1524
  checkKeys(ss[0], ss[1]);
1094
1525
  });
1095
1526
  }
1527
+ const extraPairs = [
1528
+ (_f = (_e = options.frame) == null ? void 0 : _e.navigationRules) == null ? void 0 : _f.parent_child,
1529
+ (_h = (_g = options.frame) == null ? void 0 : _g.navigationRules) == null ? void 0 : _h.sibling_sibling,
1530
+ (_j = (_i = options.spatialGrid) == null ? void 0 : _i.navigationRules) == null ? void 0 : _j.x,
1531
+ (_l = (_k = options.spatialGrid) == null ? void 0 : _k.navigationRules) == null ? void 0 : _l.y,
1532
+ (_n = (_m = options.spatialGrid) == null ? void 0 : _m.navigationRules) == null ? void 0 : _n.parent_child,
1533
+ (_p = (_o = options.hierarchy) == null ? void 0 : _o.navigationRules) == null ? void 0 : _p.parent_child,
1534
+ (_r = (_q = options.hierarchy) == null ? void 0 : _q.navigationRules) == null ? void 0 : _r.sibling_sibling
1535
+ ];
1536
+ extraPairs.forEach((pair) => {
1537
+ if (pair && !used[pair[0]] && !used[pair[1]]) {
1538
+ checkKeys(pair[0], pair[1]);
1539
+ }
1540
+ });
1096
1541
  Object.keys(edges).forEach((e) => {
1097
1542
  edges[e].navigationRules.forEach((rule) => {
1098
1543
  if (!used[rule]) {
@@ -1127,20 +1572,38 @@ var buildRules = (options, edges, dimensions) => {
1127
1572
  }
1128
1573
  return rules;
1129
1574
  };
1130
- var buildStructure = (options) => {
1131
- if (options.addIds) {
1132
- addSimpleDataIDs(options);
1575
+ var buildStructure = (inputOptions) => {
1576
+ var _a, _b, _c;
1577
+ if (inputOptions.addIds) {
1578
+ addSimpleDataIDs(inputOptions);
1133
1579
  }
1580
+ const options = prepareFrameOptions(inputOptions);
1134
1581
  let nodes = buildNodes(options);
1135
1582
  let dimensions = scaffoldDimensions(options, nodes);
1136
- let edges = buildEdges(options, nodes, dimensions);
1583
+ let edges = {};
1584
+ const spatialGrid = buildSpatialGrid(options, nodes, edges);
1585
+ const hierarchy = buildHierarchy(options, nodes, edges);
1586
+ let frame;
1587
+ if (options.frame) {
1588
+ const dimKeys = Object.keys(dimensions || {});
1589
+ const topId = (spatialGrid == null ? void 0 : spatialGrid.rootId) || (hierarchy == null ? void 0 : hierarchy.rootId) || ((_c = (_b = (_a = options.dimensions) == null ? void 0 : _a.parentOptions) == null ? void 0 : _b.addLevel0) == null ? void 0 : _c.id) || (dimKeys.length === 1 ? dimensions[dimKeys[0]].nodeId : void 0);
1590
+ frame = buildFrame(options, nodes, edges, topId);
1591
+ }
1592
+ edges = buildEdges(options, nodes, dimensions, edges);
1137
1593
  let navigationRules = buildRules(options, edges, dimensions);
1138
- return {
1594
+ const structure = {
1139
1595
  nodes,
1140
1596
  edges,
1141
1597
  dimensions,
1142
1598
  navigationRules
1143
1599
  };
1600
+ if (frame)
1601
+ structure.frame = frame;
1602
+ if (spatialGrid)
1603
+ structure.spatialGrid = spatialGrid;
1604
+ if (hierarchy)
1605
+ structure.hierarchy = hierarchy;
1606
+ return structure;
1144
1607
  };
1145
1608
 
1146
1609
  // src/input.ts
@@ -1506,15 +1969,15 @@ var rendering_default = (options) => {
1506
1969
  const attributes = resolveProp("semantics", "attributes");
1507
1970
  if (typeof attributes === "object") {
1508
1971
  Object.keys(attributes).forEach((attribute) => {
1509
- node.setAttribute(attribute, attributes[attribute]);
1972
+ nodeText.setAttribute(attribute, attributes[attribute]);
1510
1973
  });
1511
1974
  }
1512
1975
  nodeText.setAttribute("role", resolveProp("semantics", "role"));
1513
1976
  nodeText.classList.add("dn-node-text");
1977
+ const label = resolveProp("semantics", "label");
1514
1978
  if (d.showText) {
1515
- nodeText.innerText = d.semantics.label;
1979
+ nodeText.innerText = label;
1516
1980
  }
1517
- const label = resolveProp("semantics", "label");
1518
1981
  if (!label) {
1519
1982
  console.error(
1520
1983
  "Accessibility error: a label must be supplied to every rendered element using semantics.label."
@@ -1569,7 +2032,10 @@ var rendering_default = (options) => {
1569
2032
  return;
1570
2033
  }
1571
2034
  const optionsCommands = commandOptions.commands;
1572
- const genericCommandsFromRules = getGenericCommandsFromNavRules(commandOptions.navigationRules);
2035
+ const genericCommandsFromRules = getGenericCommandsFromNavRules(
2036
+ commandOptions.navigationRules,
2037
+ commandOptions.descriptions
2038
+ );
1573
2039
  const commands = optionsCommands ? typeof optionsCommands === "function" ? optionsCommands(genericCommandsFromRules) : optionsCommands : genericCommandsFromRules;
1574
2040
  if (!customElements.get("dn-commands-table")) {
1575
2041
  customElements.define("dn-commands-table", CommandsTable);
@@ -1761,7 +2227,7 @@ var searchNodes = (query, structure, describeFn, limit = 10) => {
1761
2227
  return results;
1762
2228
  };
1763
2229
  var text_chat_default = (options) => {
1764
- var _a;
2230
+ var _a, _b, _c, _d;
1765
2231
  const {
1766
2232
  structure,
1767
2233
  container,
@@ -1779,7 +2245,9 @@ var text_chat_default = (options) => {
1779
2245
  if (!rootEl) {
1780
2246
  throw new Error(`textChat: container "${container}" not found`);
1781
2247
  }
1782
- const resolvedEntryPoint = entryPoint || (structure.dimensions ? (_a = structure.dimensions[Object.keys(structure.dimensions)[0]]) == null ? void 0 : _a.nodeId : Object.keys(structure.nodes)[0]);
2248
+ const level0Id = Object.keys(structure.nodes).find((id) => structure.nodes[id].dimensionLevel === 0);
2249
+ const firstDimensionId = structure.dimensions ? (_a = structure.dimensions[Object.keys(structure.dimensions)[0]]) == null ? void 0 : _a.nodeId : void 0;
2250
+ const resolvedEntryPoint = entryPoint || ((_b = structure.frame) == null ? void 0 : _b.rootId) || level0Id || ((_c = structure.spatialGrid) == null ? void 0 : _c.rootId) || ((_d = structure.hierarchy) == null ? void 0 : _d.rootId) || firstDimensionId || Object.keys(structure.nodes)[0];
1783
2251
  const inputHandler = input_default({
1784
2252
  structure,
1785
2253
  navigationRules: structure.navigationRules || {},
@@ -2337,7 +2805,9 @@ export {
2337
2805
  src_default as default,
2338
2806
  describeNode,
2339
2807
  expandHull,
2808
+ getGenericCommandsFromNavRules,
2340
2809
  grahamScan,
2810
+ keyLabel,
2341
2811
  offsetLinePath,
2342
2812
  unionOfRectPaths
2343
2813
  };
package/dist/input.cjs CHANGED
@@ -1 +1 @@
1
- var p=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var b=Object.prototype.hasOwnProperty;var v=(r,t)=>{for(var o in t)p(r,o,{get:t[o],enumerable:!0})},x=(r,t,o,l)=>{if(t&&typeof t=="object"||typeof t=="function")for(let e of m(t))!b.call(r,e)&&e!==o&&p(r,e,{get:()=>t[e],enumerable:!(l=k(t,e))||l.enumerable});return r};var h=r=>x(p({},"__esModule",{value:!0}),r);var R={};v(R,{default:()=>N});module.exports=h(R);var g={ArrowLeft:"left",ArrowRight:"right",ArrowUp:"up",ArrowDown:"down",Period:"forward",Comma:"backward",Escape:"drill-out",Enter:"drill-in"};var f={left:{key:"ArrowLeft",direction:"source"},right:{key:"ArrowRight",direction:"target"},up:{key:"ArrowUp",direction:"source"},down:{key:"ArrowDown",direction:"target"},"drill-in":{key:"Enter",direction:"target"},"drill-out":{key:"Backspace",direction:"source"},backward:{key:"Comma",direction:"source"},forward:{key:"Period",direction:"target"},previous:{key:"Semicolon",direction:"source"},next:{key:"Quote",direction:"target"},exit:{key:"Escape",direction:"target"},help:{key:"KeyY",direction:"target"},undo:{key:"KeyZ",direction:"target"}};var N=r=>{let t={},o=g,l=f;return t.moveTo=e=>{let i=r.structure.nodes[e];if(i)return i},t.move=(e,i)=>{if(e){let a=r.structure.nodes[e];if(a.edges){let d=null,s=0,u=l[i];if(!u)return;let w=(c,n)=>{if(c!==i)return null;let y={target:typeof n.target=="string"?n.target:n.target(a,e),source:typeof n.source=="string"?n.source:n.source(a,e)};return y[u.direction]!==e?y[u.direction]:null};for(s=0;s<a.edges.length;s++){let c=r.structure.edges[a.edges[s]];if(c.navigationRules.forEach(n=>{d||(d=w(n,c))}),d)break}return d?t.moveTo(d):void 0}}},t.enter=()=>{if(r.entryPoint)return t.moveTo(r.entryPoint);console.error("No entry point was specified in InputOptions, returning undefined")},t.exit=()=>{if(r.exitPoint)return r.exitPoint;console.error("No exit point was specified in InputOptions, returning undefined")},t.keydownValidator=e=>{let i=o[e.code];if(i)return i},t.focus=e=>{let i=document.getElementById(e);i&&i.focus()},t.setNavigationKeyBindings=e=>{e?(o={},l=e,Object.keys(e).forEach(i=>{let a=e[i];o[a.key]=i})):(o=g,l=f)},t.setNavigationKeyBindings(r.navigationRules),t};
1
+ var p=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var b=Object.prototype.hasOwnProperty;var v=(r,t)=>{for(var o in t)p(r,o,{get:t[o],enumerable:!0})},x=(r,t,o,l)=>{if(t&&typeof t=="object"||typeof t=="function")for(let e of m(t))!b.call(r,e)&&e!==o&&p(r,e,{get:()=>t[e],enumerable:!(l=k(t,e))||l.enumerable});return r};var h=r=>x(p({},"__esModule",{value:!0}),r);var E={};v(E,{default:()=>R});module.exports=h(E);var g={ArrowLeft:"left",ArrowRight:"right",ArrowUp:"up",ArrowDown:"down",Period:"forward",Comma:"backward",Escape:"drill-out",Enter:"drill-in"};var f={left:{key:"ArrowLeft",direction:"source"},right:{key:"ArrowRight",direction:"target"},up:{key:"ArrowUp",direction:"source"},down:{key:"ArrowDown",direction:"target"},"drill-in":{key:"Enter",direction:"target"},"drill-out":{key:"Backspace",direction:"source"},backward:{key:"Comma",direction:"source"},forward:{key:"Period",direction:"target"},previous:{key:"Semicolon",direction:"source"},next:{key:"Quote",direction:"target"},exit:{key:"Escape",direction:"target"},help:{key:"KeyY",direction:"target"},undo:{key:"KeyZ",direction:"target"}};var R=r=>{let t={},o=g,l=f;return t.moveTo=e=>{let i=r.structure.nodes[e];if(i)return i},t.move=(e,i)=>{if(e){let a=r.structure.nodes[e];if(a.edges){let d=null,s=0,u=l[i];if(!u)return;let w=(c,n)=>{if(c!==i)return null;let y={target:typeof n.target=="string"?n.target:n.target(a,e),source:typeof n.source=="string"?n.source:n.source(a,e)};return y[u.direction]!==e?y[u.direction]:null};for(s=0;s<a.edges.length;s++){let c=r.structure.edges[a.edges[s]];if(c.navigationRules.forEach(n=>{d||(d=w(n,c))}),d)break}return d?t.moveTo(d):void 0}}},t.enter=()=>{if(r.entryPoint)return t.moveTo(r.entryPoint);console.error("No entry point was specified in InputOptions, returning undefined")},t.exit=()=>{if(r.exitPoint)return r.exitPoint;console.error("No exit point was specified in InputOptions, returning undefined")},t.keydownValidator=e=>{let i=o[e.code];if(i)return i},t.focus=e=>{let i=document.getElementById(e);i&&i.focus()},t.setNavigationKeyBindings=e=>{e?(o={},l=e,Object.keys(e).forEach(i=>{let a=e[i];o[a.key]=i})):(o=g,l=f)},t.setNavigationKeyBindings(r.navigationRules),t};
package/dist/input.js CHANGED
@@ -1 +1 @@
1
- import{a}from"./chunk-UNB4R2QN.js";import"./chunk-7YO7HC2V.js";export{a as default};
1
+ import{a}from"./chunk-QT52GVQM.js";import"./chunk-B5HGEXMZ.js";export{a as default};