@dxos/react-ui-canvas 0.8.4-main.03d5cd7b56 → 0.8.4-main.05e74ebcff
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 +102 -5
- package/dist/lib/browser/index.mjs +777 -18
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +777 -18
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/CellGrid/CellGrid.d.ts +21 -0
- package/dist/types/src/components/CellGrid/CellGrid.d.ts.map +1 -0
- package/dist/types/src/components/CellGrid/CellGrid.stories.d.ts +21 -0
- package/dist/types/src/components/CellGrid/CellGrid.stories.d.ts.map +1 -0
- package/dist/types/src/components/CellGrid/headers/Ruler.d.ts +15 -0
- package/dist/types/src/components/CellGrid/headers/Ruler.d.ts.map +1 -0
- package/dist/types/src/components/CellGrid/headers/TrackHeader.d.ts +19 -0
- package/dist/types/src/components/CellGrid/headers/TrackHeader.d.ts.map +1 -0
- package/dist/types/src/components/CellGrid/headers/index.d.ts +3 -0
- package/dist/types/src/components/CellGrid/headers/index.d.ts.map +1 -0
- package/dist/types/src/components/CellGrid/index.d.ts +6 -0
- package/dist/types/src/components/CellGrid/index.d.ts.map +1 -0
- package/dist/types/src/components/CellGrid/input/index.d.ts +3 -0
- package/dist/types/src/components/CellGrid/input/index.d.ts.map +1 -0
- package/dist/types/src/components/CellGrid/input/pointer.d.ts +29 -0
- package/dist/types/src/components/CellGrid/input/pointer.d.ts.map +1 -0
- package/dist/types/src/components/CellGrid/input/wheel.d.ts +14 -0
- package/dist/types/src/components/CellGrid/input/wheel.d.ts.map +1 -0
- package/dist/types/src/components/CellGrid/render/index.d.ts +3 -0
- package/dist/types/src/components/CellGrid/render/index.d.ts.map +1 -0
- package/dist/types/src/components/CellGrid/render/overlay-layer.d.ts +21 -0
- package/dist/types/src/components/CellGrid/render/overlay-layer.d.ts.map +1 -0
- package/dist/types/src/components/CellGrid/render/static-layer.d.ts +36 -0
- package/dist/types/src/components/CellGrid/render/static-layer.d.ts.map +1 -0
- package/dist/types/src/components/CellGrid/state/atoms.d.ts +23 -0
- package/dist/types/src/components/CellGrid/state/atoms.d.ts.map +1 -0
- package/dist/types/src/components/CellGrid/state/index.d.ts +4 -0
- package/dist/types/src/components/CellGrid/state/index.d.ts.map +1 -0
- package/dist/types/src/components/CellGrid/state/types.d.ts +39 -0
- package/dist/types/src/components/CellGrid/state/types.d.ts.map +1 -0
- package/dist/types/src/components/CellGrid/state/viewport.d.ts +52 -0
- package/dist/types/src/components/CellGrid/state/viewport.d.ts.map +1 -0
- package/dist/types/src/components/CellGrid/state/viewport.test.d.ts +2 -0
- package/dist/types/src/components/CellGrid/state/viewport.test.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +14 -13
- package/src/components/CellGrid/CellGrid.stories.tsx +238 -0
- package/src/components/CellGrid/CellGrid.tsx +266 -0
- package/src/components/CellGrid/headers/Ruler.tsx +71 -0
- package/src/components/CellGrid/headers/TrackHeader.tsx +58 -0
- package/src/components/CellGrid/headers/index.ts +6 -0
- package/src/components/CellGrid/index.ts +9 -0
- package/src/components/CellGrid/input/index.ts +6 -0
- package/src/components/CellGrid/input/pointer.ts +208 -0
- package/src/components/CellGrid/input/wheel.ts +68 -0
- package/src/components/CellGrid/render/index.ts +6 -0
- package/src/components/CellGrid/render/overlay-layer.ts +66 -0
- package/src/components/CellGrid/render/static-layer.ts +112 -0
- package/src/components/CellGrid/state/atoms.ts +43 -0
- package/src/components/CellGrid/state/index.ts +7 -0
- package/src/components/CellGrid/state/types.ts +40 -0
- package/src/components/CellGrid/state/viewport.test.ts +50 -0
- package/src/components/CellGrid/state/viewport.ts +94 -0
- package/src/components/index.ts +1 -0
|
@@ -475,9 +475,751 @@ var Canvas = /* @__PURE__ */ forwardRef(({ children, classNames, scale: scalePro
|
|
|
475
475
|
}, ready ? children : null));
|
|
476
476
|
});
|
|
477
477
|
|
|
478
|
-
// src/components/
|
|
479
|
-
import
|
|
478
|
+
// src/components/CellGrid/CellGrid.tsx
|
|
479
|
+
import { RegistryContext } from "@effect-atom/atom-react";
|
|
480
|
+
import React5, { useContext as useContext2, useEffect as useEffect4, useMemo as useMemo3, useRef as useRef2, useState as useState2 } from "react";
|
|
481
|
+
import { useResizeDetector as useResizeDetector2 } from "react-resize-detector";
|
|
482
|
+
import { mx as mx5 } from "@dxos/ui-theme";
|
|
483
|
+
|
|
484
|
+
// src/components/CellGrid/headers/Ruler.tsx
|
|
485
|
+
import React3, { useMemo as useMemo2 } from "react";
|
|
480
486
|
import { mx as mx3 } from "@dxos/ui-theme";
|
|
487
|
+
|
|
488
|
+
// src/components/CellGrid/state/viewport.ts
|
|
489
|
+
var cellKey = (col, row) => `${col},${row}`;
|
|
490
|
+
var cellWidth = (viewport) => viewport.baseCellWidth * viewport.zoomX;
|
|
491
|
+
var worldToScreen = (viewport, headers, coord) => {
|
|
492
|
+
const w = cellWidth(viewport);
|
|
493
|
+
return {
|
|
494
|
+
x: headers.left + coord.col * w - viewport.scrollX,
|
|
495
|
+
y: headers.top + coord.row * viewport.cellHeight - viewport.scrollY,
|
|
496
|
+
w: (coord.length ?? 1) * w,
|
|
497
|
+
h: viewport.cellHeight
|
|
498
|
+
};
|
|
499
|
+
};
|
|
500
|
+
var screenToWorld = (viewport, headers, point) => {
|
|
501
|
+
const w = cellWidth(viewport);
|
|
502
|
+
return {
|
|
503
|
+
col: (point.x - headers.left + viewport.scrollX) / w,
|
|
504
|
+
row: (point.y - headers.top + viewport.scrollY) / viewport.cellHeight
|
|
505
|
+
};
|
|
506
|
+
};
|
|
507
|
+
var hitTestCell = (viewport, headers, point) => {
|
|
508
|
+
if (point.x < headers.left || point.y < headers.top) {
|
|
509
|
+
return null;
|
|
510
|
+
}
|
|
511
|
+
const { col, row } = screenToWorld(viewport, headers, point);
|
|
512
|
+
if (col < 0 || row < 0) {
|
|
513
|
+
return null;
|
|
514
|
+
}
|
|
515
|
+
return {
|
|
516
|
+
col: Math.floor(col),
|
|
517
|
+
row: Math.floor(row)
|
|
518
|
+
};
|
|
519
|
+
};
|
|
520
|
+
var visibleCellRange = (viewport, headers, size) => {
|
|
521
|
+
const w = cellWidth(viewport);
|
|
522
|
+
const innerW = Math.max(0, size.width - headers.left);
|
|
523
|
+
const innerH = Math.max(0, size.height - headers.top);
|
|
524
|
+
const minCol = Math.max(0, Math.floor(viewport.scrollX / w));
|
|
525
|
+
const maxCol = Math.floor((viewport.scrollX + innerW) / w);
|
|
526
|
+
const minRow = Math.max(0, Math.floor(viewport.scrollY / viewport.cellHeight));
|
|
527
|
+
const maxRow = Math.floor((viewport.scrollY + innerH) / viewport.cellHeight);
|
|
528
|
+
return {
|
|
529
|
+
minCol,
|
|
530
|
+
maxCol,
|
|
531
|
+
minRow,
|
|
532
|
+
maxRow
|
|
533
|
+
};
|
|
534
|
+
};
|
|
535
|
+
var visibleCells = function* (cells, range) {
|
|
536
|
+
for (const cell of cells.values()) {
|
|
537
|
+
if (cell.row < range.minRow || cell.row > range.maxRow) {
|
|
538
|
+
continue;
|
|
539
|
+
}
|
|
540
|
+
const start = cell.col;
|
|
541
|
+
const end = cell.col + cell.length - 1;
|
|
542
|
+
if (end < range.minCol || start > range.maxCol) {
|
|
543
|
+
continue;
|
|
544
|
+
}
|
|
545
|
+
yield cell;
|
|
546
|
+
}
|
|
547
|
+
};
|
|
548
|
+
|
|
549
|
+
// src/components/CellGrid/headers/Ruler.tsx
|
|
550
|
+
var Ruler = ({ viewport, headers, width, majorEvery = 4, classNames }) => {
|
|
551
|
+
const safeMajorEvery = Math.max(1, Math.floor(majorEvery));
|
|
552
|
+
const ticks = useMemo2(() => {
|
|
553
|
+
const w = cellWidth(viewport);
|
|
554
|
+
if (w < 1 || width <= headers.left) {
|
|
555
|
+
return [];
|
|
556
|
+
}
|
|
557
|
+
const innerWidth = width - headers.left;
|
|
558
|
+
const startCol = Math.floor(viewport.scrollX / w);
|
|
559
|
+
const endCol = Math.ceil((viewport.scrollX + innerWidth) / w);
|
|
560
|
+
const result = [];
|
|
561
|
+
for (let col = startCol; col <= endCol; col++) {
|
|
562
|
+
result.push({
|
|
563
|
+
col,
|
|
564
|
+
x: headers.left + col * w - viewport.scrollX,
|
|
565
|
+
major: col % safeMajorEvery === 0
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
return result;
|
|
569
|
+
}, [
|
|
570
|
+
viewport,
|
|
571
|
+
headers.left,
|
|
572
|
+
width,
|
|
573
|
+
safeMajorEvery
|
|
574
|
+
]);
|
|
575
|
+
return /* @__PURE__ */ React3.createElement("div", {
|
|
576
|
+
className: mx3("absolute top-0 left-0 right-0 border-b border-neutral-200 dark:border-neutral-700 bg-baseSurface select-none overflow-hidden", classNames),
|
|
577
|
+
style: {
|
|
578
|
+
height: headers.top
|
|
579
|
+
}
|
|
580
|
+
}, ticks.map(({ col, x, major }) => /* @__PURE__ */ React3.createElement("div", {
|
|
581
|
+
key: col,
|
|
582
|
+
className: mx3("absolute top-0 bottom-0 text-[10px] text-neutral-500 dark:text-neutral-400", major ? "border-l border-neutral-400 dark:border-neutral-500" : "border-l border-neutral-200 dark:border-neutral-700"),
|
|
583
|
+
style: {
|
|
584
|
+
transform: `translateX(${x}px)`
|
|
585
|
+
}
|
|
586
|
+
}, major ? /* @__PURE__ */ React3.createElement("span", {
|
|
587
|
+
className: "absolute left-1 top-0"
|
|
588
|
+
}, col) : null)));
|
|
589
|
+
};
|
|
590
|
+
|
|
591
|
+
// src/components/CellGrid/headers/TrackHeader.tsx
|
|
592
|
+
import React4 from "react";
|
|
593
|
+
import { mx as mx4 } from "@dxos/ui-theme";
|
|
594
|
+
var TrackHeader = ({ viewport, headers, rows, height, classNames }) => {
|
|
595
|
+
return /* @__PURE__ */ React4.createElement("div", {
|
|
596
|
+
className: mx4("absolute left-0 border-r border-neutral-200 dark:border-neutral-700 select-none overflow-hidden", classNames),
|
|
597
|
+
style: {
|
|
598
|
+
top: headers.top,
|
|
599
|
+
width: headers.left,
|
|
600
|
+
height: Math.max(0, height - headers.top)
|
|
601
|
+
}
|
|
602
|
+
}, /* @__PURE__ */ React4.createElement("div", {
|
|
603
|
+
style: {
|
|
604
|
+
transform: `translateY(${-viewport.scrollY}px)`
|
|
605
|
+
}
|
|
606
|
+
}, rows.map((row, index) => /* @__PURE__ */ React4.createElement("div", {
|
|
607
|
+
key: row.id,
|
|
608
|
+
className: "flex items-center px-2 text-xs text-neutral-700 dark:text-neutral-300",
|
|
609
|
+
style: {
|
|
610
|
+
height: viewport.cellHeight,
|
|
611
|
+
// Match the canvas's row-band: a translucent gray overlay on odd rows,
|
|
612
|
+
// transparent on even rows. The container's overall background bleeds
|
|
613
|
+
// through, so the labels stay legible in both themes.
|
|
614
|
+
backgroundColor: index % 2 === 0 ? "transparent" : "rgba(128, 128, 128, 0.08)",
|
|
615
|
+
// Match the canvas gridline color (rgba(128, 128, 128, 0.25)). Use a
|
|
616
|
+
// half-pixel inset to keep crisp single-pixel rendering on retina.
|
|
617
|
+
boxShadow: "inset 0 -1px 0 rgba(128, 128, 128, 0.25)"
|
|
618
|
+
}
|
|
619
|
+
}, row.label ?? row.id))));
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
// src/components/CellGrid/input/pointer.ts
|
|
623
|
+
var attachPointerHandlers = (element, { registry, atoms, headers, handlers }) => {
|
|
624
|
+
let drag = null;
|
|
625
|
+
const local = (event) => {
|
|
626
|
+
const rect = element.getBoundingClientRect();
|
|
627
|
+
return {
|
|
628
|
+
x: event.clientX - rect.left,
|
|
629
|
+
y: event.clientY - rect.top
|
|
630
|
+
};
|
|
631
|
+
};
|
|
632
|
+
const tryCapture = (pointerId) => {
|
|
633
|
+
try {
|
|
634
|
+
element.setPointerCapture(pointerId);
|
|
635
|
+
} catch {
|
|
636
|
+
}
|
|
637
|
+
};
|
|
638
|
+
const onPointerDown = (event) => {
|
|
639
|
+
if (event.button === 1 || event.button === 0 && event.altKey) {
|
|
640
|
+
drag = {
|
|
641
|
+
kind: "pan",
|
|
642
|
+
lastX: event.clientX,
|
|
643
|
+
lastY: event.clientY
|
|
644
|
+
};
|
|
645
|
+
tryCapture(event.pointerId);
|
|
646
|
+
event.preventDefault();
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
if (event.button !== 0) {
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
const viewport = registry.get(atoms.viewport);
|
|
653
|
+
const point = local(event);
|
|
654
|
+
const coord = hitTestCell(viewport, headers, point);
|
|
655
|
+
if (!coord) {
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
const tool = registry.get(atoms.tool);
|
|
659
|
+
tryCapture(event.pointerId);
|
|
660
|
+
switch (tool) {
|
|
661
|
+
case "toggle":
|
|
662
|
+
case "resize": {
|
|
663
|
+
const cells = registry.get(atoms.cells);
|
|
664
|
+
const key = cellKey(coord.col, coord.row);
|
|
665
|
+
const mode = cells.has(key) ? "unset" : "set";
|
|
666
|
+
handlers.onCellToggle?.(coord, mode);
|
|
667
|
+
drag = {
|
|
668
|
+
kind: "toggle",
|
|
669
|
+
mode,
|
|
670
|
+
touched: /* @__PURE__ */ new Set([
|
|
671
|
+
key
|
|
672
|
+
])
|
|
673
|
+
};
|
|
674
|
+
break;
|
|
675
|
+
}
|
|
676
|
+
case "select": {
|
|
677
|
+
drag = {
|
|
678
|
+
kind: "select",
|
|
679
|
+
origin: coord
|
|
680
|
+
};
|
|
681
|
+
registry.set(atoms.selection, {
|
|
682
|
+
range: {
|
|
683
|
+
col0: coord.col,
|
|
684
|
+
row0: coord.row,
|
|
685
|
+
col1: coord.col,
|
|
686
|
+
row1: coord.row
|
|
687
|
+
}
|
|
688
|
+
});
|
|
689
|
+
break;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
};
|
|
693
|
+
const onPointerMove = (event) => {
|
|
694
|
+
if (!drag) {
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
if (drag.kind === "pan") {
|
|
698
|
+
const dx = event.clientX - drag.lastX;
|
|
699
|
+
const dy = event.clientY - drag.lastY;
|
|
700
|
+
drag.lastX = event.clientX;
|
|
701
|
+
drag.lastY = event.clientY;
|
|
702
|
+
registry.update(atoms.viewport, (current) => ({
|
|
703
|
+
...current,
|
|
704
|
+
scrollX: Math.max(0, current.scrollX - dx),
|
|
705
|
+
scrollY: Math.max(0, current.scrollY - dy)
|
|
706
|
+
}));
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
const viewport = registry.get(atoms.viewport);
|
|
710
|
+
const coord = hitTestCell(viewport, headers, local(event));
|
|
711
|
+
if (!coord) {
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
714
|
+
if (drag.kind === "toggle") {
|
|
715
|
+
const key = cellKey(coord.col, coord.row);
|
|
716
|
+
if (!drag.touched.has(key)) {
|
|
717
|
+
drag.touched.add(key);
|
|
718
|
+
handlers.onCellToggle?.(coord, drag.mode);
|
|
719
|
+
}
|
|
720
|
+
} else if (drag.kind === "select") {
|
|
721
|
+
registry.set(atoms.selection, {
|
|
722
|
+
range: {
|
|
723
|
+
col0: drag.origin.col,
|
|
724
|
+
row0: drag.origin.row,
|
|
725
|
+
col1: coord.col,
|
|
726
|
+
row1: coord.row
|
|
727
|
+
}
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
};
|
|
731
|
+
const releaseCapture = (event) => {
|
|
732
|
+
if (element.hasPointerCapture(event.pointerId)) {
|
|
733
|
+
element.releasePointerCapture(event.pointerId);
|
|
734
|
+
}
|
|
735
|
+
};
|
|
736
|
+
const onPointerUp = (event) => {
|
|
737
|
+
if (!drag) {
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
if (drag.kind === "select") {
|
|
741
|
+
const range = registry.get(atoms.selection).range;
|
|
742
|
+
if (range) {
|
|
743
|
+
handlers.onSelectionCommit?.(range);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
drag = null;
|
|
747
|
+
releaseCapture(event);
|
|
748
|
+
};
|
|
749
|
+
const onPointerCancel = (event) => {
|
|
750
|
+
drag = null;
|
|
751
|
+
releaseCapture(event);
|
|
752
|
+
};
|
|
753
|
+
element.addEventListener("pointerdown", onPointerDown);
|
|
754
|
+
element.addEventListener("pointermove", onPointerMove);
|
|
755
|
+
element.addEventListener("pointerup", onPointerUp);
|
|
756
|
+
element.addEventListener("pointercancel", onPointerCancel);
|
|
757
|
+
return () => {
|
|
758
|
+
element.removeEventListener("pointerdown", onPointerDown);
|
|
759
|
+
element.removeEventListener("pointermove", onPointerMove);
|
|
760
|
+
element.removeEventListener("pointerup", onPointerUp);
|
|
761
|
+
element.removeEventListener("pointercancel", onPointerCancel);
|
|
762
|
+
};
|
|
763
|
+
};
|
|
764
|
+
var toggleCell = (registry, atoms, coord, factory, mode = "toggle") => {
|
|
765
|
+
registry.update(atoms.cells, (current) => {
|
|
766
|
+
const next = new Map(current);
|
|
767
|
+
const key = cellKey(coord.col, coord.row);
|
|
768
|
+
const exists = next.has(key);
|
|
769
|
+
if (mode === "set" || mode === "toggle" && !exists) {
|
|
770
|
+
next.set(key, factory(coord));
|
|
771
|
+
} else if (mode === "unset" || mode === "toggle" && exists) {
|
|
772
|
+
next.delete(key);
|
|
773
|
+
}
|
|
774
|
+
return next;
|
|
775
|
+
});
|
|
776
|
+
};
|
|
777
|
+
|
|
778
|
+
// src/components/CellGrid/input/wheel.ts
|
|
779
|
+
var MIN_ZOOM = 0.25;
|
|
780
|
+
var MAX_ZOOM = 8;
|
|
781
|
+
var attachWheelHandlers = (element, { registry, atoms, headers }) => {
|
|
782
|
+
const onWheel = (event) => {
|
|
783
|
+
if (event.ctrlKey || event.metaKey) {
|
|
784
|
+
event.preventDefault();
|
|
785
|
+
const rect = element.getBoundingClientRect();
|
|
786
|
+
const x = event.clientX - rect.left;
|
|
787
|
+
const factor = Math.exp(-event.deltaY / 200);
|
|
788
|
+
registry.update(atoms.viewport, (current2) => {
|
|
789
|
+
const nextZoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, current2.zoomX * factor));
|
|
790
|
+
if (nextZoom === current2.zoomX) {
|
|
791
|
+
return current2;
|
|
792
|
+
}
|
|
793
|
+
const w = cellWidth(current2);
|
|
794
|
+
const worldX = (x - headers.left + current2.scrollX) / w;
|
|
795
|
+
const nextW = current2.baseCellWidth * nextZoom;
|
|
796
|
+
const nextScrollX2 = Math.max(0, worldX * nextW - (x - headers.left));
|
|
797
|
+
return {
|
|
798
|
+
...current2,
|
|
799
|
+
zoomX: nextZoom,
|
|
800
|
+
scrollX: nextScrollX2
|
|
801
|
+
};
|
|
802
|
+
});
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
const dx = event.shiftKey ? event.deltaY : event.deltaX;
|
|
806
|
+
const dy = event.shiftKey ? 0 : event.deltaY;
|
|
807
|
+
const current = registry.get(atoms.viewport);
|
|
808
|
+
const nextScrollX = Math.max(0, current.scrollX + dx);
|
|
809
|
+
const nextScrollY = Math.max(0, current.scrollY + dy);
|
|
810
|
+
if (nextScrollX === current.scrollX && nextScrollY === current.scrollY) {
|
|
811
|
+
return;
|
|
812
|
+
}
|
|
813
|
+
event.preventDefault();
|
|
814
|
+
registry.set(atoms.viewport, {
|
|
815
|
+
...current,
|
|
816
|
+
scrollX: nextScrollX,
|
|
817
|
+
scrollY: nextScrollY
|
|
818
|
+
});
|
|
819
|
+
};
|
|
820
|
+
element.addEventListener("wheel", onWheel, {
|
|
821
|
+
passive: false
|
|
822
|
+
});
|
|
823
|
+
return () => element.removeEventListener("wheel", onWheel);
|
|
824
|
+
};
|
|
825
|
+
|
|
826
|
+
// src/components/CellGrid/render/overlay-layer.ts
|
|
827
|
+
var drawOverlay = ({ ctx, size, viewport, headers, selection, playhead, style }) => {
|
|
828
|
+
ctx.clearRect(0, 0, size.width, size.height);
|
|
829
|
+
ctx.save();
|
|
830
|
+
ctx.beginPath();
|
|
831
|
+
ctx.rect(headers.left, headers.top, size.width - headers.left, size.height - headers.top);
|
|
832
|
+
ctx.clip();
|
|
833
|
+
if (selection.range) {
|
|
834
|
+
const { col0, row0, col1, row1 } = selection.range;
|
|
835
|
+
const minCol = Math.min(col0, col1);
|
|
836
|
+
const maxCol = Math.max(col0, col1);
|
|
837
|
+
const minRow = Math.min(row0, row1);
|
|
838
|
+
const maxRow = Math.max(row0, row1);
|
|
839
|
+
const tl = worldToScreen(viewport, headers, {
|
|
840
|
+
col: minCol,
|
|
841
|
+
row: minRow
|
|
842
|
+
});
|
|
843
|
+
const br = worldToScreen(viewport, headers, {
|
|
844
|
+
col: maxCol + 1,
|
|
845
|
+
row: maxRow + 1
|
|
846
|
+
});
|
|
847
|
+
ctx.fillStyle = style.selectionFill;
|
|
848
|
+
ctx.fillRect(tl.x, tl.y, br.x - tl.x, br.y - tl.y);
|
|
849
|
+
ctx.strokeStyle = style.selectionStroke;
|
|
850
|
+
ctx.setLineDash([
|
|
851
|
+
4,
|
|
852
|
+
3
|
|
853
|
+
]);
|
|
854
|
+
ctx.lineWidth = 1;
|
|
855
|
+
ctx.strokeRect(tl.x + 0.5, tl.y + 0.5, br.x - tl.x - 1, br.y - tl.y - 1);
|
|
856
|
+
ctx.setLineDash([]);
|
|
857
|
+
}
|
|
858
|
+
if (playhead !== null) {
|
|
859
|
+
const w = cellWidth(viewport);
|
|
860
|
+
const x = headers.left + playhead * w - viewport.scrollX;
|
|
861
|
+
if (x >= headers.left && x <= size.width) {
|
|
862
|
+
ctx.strokeStyle = style.playhead;
|
|
863
|
+
ctx.lineWidth = 2;
|
|
864
|
+
ctx.beginPath();
|
|
865
|
+
ctx.moveTo(x, headers.top);
|
|
866
|
+
ctx.lineTo(x, size.height);
|
|
867
|
+
ctx.stroke();
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
ctx.restore();
|
|
871
|
+
};
|
|
872
|
+
|
|
873
|
+
// src/components/CellGrid/render/static-layer.ts
|
|
874
|
+
var drawCells = ({ ctx, size, viewport, headers, rows, cells, renderCell, style }) => {
|
|
875
|
+
ctx.clearRect(0, 0, size.width, size.height);
|
|
876
|
+
if (style.background) {
|
|
877
|
+
ctx.fillStyle = style.background;
|
|
878
|
+
ctx.fillRect(0, 0, size.width, size.height);
|
|
879
|
+
}
|
|
880
|
+
const range = visibleCellRange(viewport, headers, size);
|
|
881
|
+
const w = cellWidth(viewport);
|
|
882
|
+
const h = viewport.cellHeight;
|
|
883
|
+
if (style.rowBand) {
|
|
884
|
+
ctx.fillStyle = style.rowBand;
|
|
885
|
+
for (let row = range.minRow; row <= Math.min(range.maxRow, rows.length - 1); row++) {
|
|
886
|
+
if (row % 2 === 0) {
|
|
887
|
+
continue;
|
|
888
|
+
}
|
|
889
|
+
const y = headers.top + row * h - viewport.scrollY;
|
|
890
|
+
ctx.fillRect(headers.left, y, size.width - headers.left, h);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
ctx.strokeStyle = style.gridLine;
|
|
894
|
+
ctx.lineWidth = 1;
|
|
895
|
+
ctx.beginPath();
|
|
896
|
+
for (let col = range.minCol; col <= range.maxCol + 1; col++) {
|
|
897
|
+
const x = Math.floor(headers.left + col * w - viewport.scrollX) + 0.5;
|
|
898
|
+
if (x < headers.left) {
|
|
899
|
+
continue;
|
|
900
|
+
}
|
|
901
|
+
ctx.moveTo(x, headers.top);
|
|
902
|
+
ctx.lineTo(x, size.height);
|
|
903
|
+
}
|
|
904
|
+
for (let row = range.minRow; row <= Math.min(range.maxRow + 1, rows.length); row++) {
|
|
905
|
+
const y = Math.floor(headers.top + row * h - viewport.scrollY) + 0.5;
|
|
906
|
+
if (y < headers.top) {
|
|
907
|
+
continue;
|
|
908
|
+
}
|
|
909
|
+
ctx.moveTo(headers.left, y);
|
|
910
|
+
ctx.lineTo(size.width, y);
|
|
911
|
+
}
|
|
912
|
+
ctx.stroke();
|
|
913
|
+
ctx.save();
|
|
914
|
+
ctx.beginPath();
|
|
915
|
+
ctx.rect(headers.left, headers.top, size.width - headers.left, size.height - headers.top);
|
|
916
|
+
ctx.clip();
|
|
917
|
+
for (const cell of visibleCells(cells, range)) {
|
|
918
|
+
if (cell.row >= rows.length) {
|
|
919
|
+
continue;
|
|
920
|
+
}
|
|
921
|
+
const rect = worldToScreen(viewport, headers, cell);
|
|
922
|
+
renderCell({
|
|
923
|
+
ctx,
|
|
924
|
+
...rect,
|
|
925
|
+
cell
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
ctx.restore();
|
|
929
|
+
};
|
|
930
|
+
|
|
931
|
+
// src/components/CellGrid/CellGrid.tsx
|
|
932
|
+
var defaultHeaders = {
|
|
933
|
+
left: 80,
|
|
934
|
+
top: 24
|
|
935
|
+
};
|
|
936
|
+
var defaultStaticStyle = {
|
|
937
|
+
gridLine: "rgba(128,128,128,0.25)",
|
|
938
|
+
rowBand: "rgba(128,128,128,0.06)"
|
|
939
|
+
};
|
|
940
|
+
var defaultOverlayStyle = {
|
|
941
|
+
playhead: "rgb(220, 38, 38)",
|
|
942
|
+
selectionFill: "rgba(59, 130, 246, 0.15)",
|
|
943
|
+
selectionStroke: "rgb(59, 130, 246)"
|
|
944
|
+
};
|
|
945
|
+
var setupCanvas = (canvas, width, height) => {
|
|
946
|
+
const dpr = window.devicePixelRatio || 1;
|
|
947
|
+
canvas.width = Math.max(1, Math.floor(width * dpr));
|
|
948
|
+
canvas.height = Math.max(1, Math.floor(height * dpr));
|
|
949
|
+
canvas.style.width = `${width}px`;
|
|
950
|
+
canvas.style.height = `${height}px`;
|
|
951
|
+
const ctx = canvas.getContext("2d");
|
|
952
|
+
if (!ctx) {
|
|
953
|
+
return null;
|
|
954
|
+
}
|
|
955
|
+
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
956
|
+
return ctx;
|
|
957
|
+
};
|
|
958
|
+
var CellGrid = ({ atoms, rows, renderCell, headers: headersProp, staticStyle: staticStyleProp, overlayStyle: overlayStyleProp, classNames, onCellToggle, onSelectionCommit }) => {
|
|
959
|
+
const registry = useContext2(RegistryContext);
|
|
960
|
+
const headers = useMemo3(() => {
|
|
961
|
+
if (headersProp === false) {
|
|
962
|
+
return {
|
|
963
|
+
left: 0,
|
|
964
|
+
top: 0
|
|
965
|
+
};
|
|
966
|
+
}
|
|
967
|
+
return {
|
|
968
|
+
...defaultHeaders,
|
|
969
|
+
...headersProp ?? {}
|
|
970
|
+
};
|
|
971
|
+
}, [
|
|
972
|
+
headersProp
|
|
973
|
+
]);
|
|
974
|
+
const staticStyle = useMemo3(() => ({
|
|
975
|
+
...defaultStaticStyle,
|
|
976
|
+
...staticStyleProp ?? {}
|
|
977
|
+
}), [
|
|
978
|
+
staticStyleProp
|
|
979
|
+
]);
|
|
980
|
+
const overlayStyle = useMemo3(() => ({
|
|
981
|
+
...defaultOverlayStyle,
|
|
982
|
+
...overlayStyleProp ?? {}
|
|
983
|
+
}), [
|
|
984
|
+
overlayStyleProp
|
|
985
|
+
]);
|
|
986
|
+
const { ref: containerRef, width = 0, height = 0 } = useResizeDetector2();
|
|
987
|
+
const staticCanvasRef = useRef2(null);
|
|
988
|
+
const overlayCanvasRef = useRef2(null);
|
|
989
|
+
const overlayInputRef = useRef2(null);
|
|
990
|
+
const [staticCtx, setStaticCtx] = useState2(null);
|
|
991
|
+
const [overlayCtx, setOverlayCtx] = useState2(null);
|
|
992
|
+
const [viewportState, setViewportState] = useState2(() => registry.get(atoms.viewport));
|
|
993
|
+
useEffect4(() => {
|
|
994
|
+
if (!width || !height) {
|
|
995
|
+
return;
|
|
996
|
+
}
|
|
997
|
+
if (staticCanvasRef.current) {
|
|
998
|
+
const ctx = setupCanvas(staticCanvasRef.current, width, height);
|
|
999
|
+
setStaticCtx(ctx);
|
|
1000
|
+
}
|
|
1001
|
+
if (overlayCanvasRef.current) {
|
|
1002
|
+
const ctx = setupCanvas(overlayCanvasRef.current, width, height);
|
|
1003
|
+
setOverlayCtx(ctx);
|
|
1004
|
+
}
|
|
1005
|
+
}, [
|
|
1006
|
+
width,
|
|
1007
|
+
height
|
|
1008
|
+
]);
|
|
1009
|
+
useEffect4(() => registry.subscribe(atoms.viewport, (next) => setViewportState(next)), [
|
|
1010
|
+
registry,
|
|
1011
|
+
atoms.viewport
|
|
1012
|
+
]);
|
|
1013
|
+
useEffect4(() => {
|
|
1014
|
+
if (!staticCtx || !width || !height) {
|
|
1015
|
+
return;
|
|
1016
|
+
}
|
|
1017
|
+
let raf = null;
|
|
1018
|
+
const schedule = () => {
|
|
1019
|
+
if (raf !== null) {
|
|
1020
|
+
return;
|
|
1021
|
+
}
|
|
1022
|
+
raf = requestAnimationFrame(() => {
|
|
1023
|
+
raf = null;
|
|
1024
|
+
drawCells({
|
|
1025
|
+
ctx: staticCtx,
|
|
1026
|
+
size: {
|
|
1027
|
+
width,
|
|
1028
|
+
height
|
|
1029
|
+
},
|
|
1030
|
+
viewport: registry.get(atoms.viewport),
|
|
1031
|
+
headers,
|
|
1032
|
+
rows,
|
|
1033
|
+
cells: registry.get(atoms.cells),
|
|
1034
|
+
renderCell,
|
|
1035
|
+
style: staticStyle
|
|
1036
|
+
});
|
|
1037
|
+
});
|
|
1038
|
+
};
|
|
1039
|
+
schedule();
|
|
1040
|
+
const unsubCells = registry.subscribe(atoms.cells, schedule);
|
|
1041
|
+
const unsubViewport = registry.subscribe(atoms.viewport, schedule);
|
|
1042
|
+
return () => {
|
|
1043
|
+
if (raf !== null) {
|
|
1044
|
+
cancelAnimationFrame(raf);
|
|
1045
|
+
}
|
|
1046
|
+
unsubCells();
|
|
1047
|
+
unsubViewport();
|
|
1048
|
+
};
|
|
1049
|
+
}, [
|
|
1050
|
+
staticCtx,
|
|
1051
|
+
width,
|
|
1052
|
+
height,
|
|
1053
|
+
registry,
|
|
1054
|
+
atoms.cells,
|
|
1055
|
+
atoms.viewport,
|
|
1056
|
+
headers,
|
|
1057
|
+
rows,
|
|
1058
|
+
renderCell,
|
|
1059
|
+
staticStyle
|
|
1060
|
+
]);
|
|
1061
|
+
useEffect4(() => {
|
|
1062
|
+
if (!overlayCtx || !width || !height) {
|
|
1063
|
+
return;
|
|
1064
|
+
}
|
|
1065
|
+
let raf = null;
|
|
1066
|
+
let stopped = false;
|
|
1067
|
+
const paint = () => {
|
|
1068
|
+
drawOverlay({
|
|
1069
|
+
ctx: overlayCtx,
|
|
1070
|
+
size: {
|
|
1071
|
+
width,
|
|
1072
|
+
height
|
|
1073
|
+
},
|
|
1074
|
+
viewport: registry.get(atoms.viewport),
|
|
1075
|
+
headers,
|
|
1076
|
+
selection: registry.get(atoms.selection),
|
|
1077
|
+
playhead: registry.get(atoms.playhead),
|
|
1078
|
+
style: overlayStyle
|
|
1079
|
+
});
|
|
1080
|
+
};
|
|
1081
|
+
const isAnimating = () => registry.get(atoms.playhead) !== null;
|
|
1082
|
+
const loop = () => {
|
|
1083
|
+
if (stopped) {
|
|
1084
|
+
return;
|
|
1085
|
+
}
|
|
1086
|
+
paint();
|
|
1087
|
+
if (isAnimating()) {
|
|
1088
|
+
raf = requestAnimationFrame(loop);
|
|
1089
|
+
} else {
|
|
1090
|
+
raf = null;
|
|
1091
|
+
}
|
|
1092
|
+
};
|
|
1093
|
+
const kick = () => {
|
|
1094
|
+
paint();
|
|
1095
|
+
if (raf === null && isAnimating()) {
|
|
1096
|
+
raf = requestAnimationFrame(loop);
|
|
1097
|
+
}
|
|
1098
|
+
};
|
|
1099
|
+
kick();
|
|
1100
|
+
const unsubSelection = registry.subscribe(atoms.selection, () => paint());
|
|
1101
|
+
const unsubPlayhead = registry.subscribe(atoms.playhead, kick);
|
|
1102
|
+
const unsubViewport = registry.subscribe(atoms.viewport, () => paint());
|
|
1103
|
+
return () => {
|
|
1104
|
+
stopped = true;
|
|
1105
|
+
if (raf !== null) {
|
|
1106
|
+
cancelAnimationFrame(raf);
|
|
1107
|
+
}
|
|
1108
|
+
unsubSelection();
|
|
1109
|
+
unsubPlayhead();
|
|
1110
|
+
unsubViewport();
|
|
1111
|
+
};
|
|
1112
|
+
}, [
|
|
1113
|
+
overlayCtx,
|
|
1114
|
+
width,
|
|
1115
|
+
height,
|
|
1116
|
+
registry,
|
|
1117
|
+
atoms.selection,
|
|
1118
|
+
atoms.playhead,
|
|
1119
|
+
atoms.viewport,
|
|
1120
|
+
headers,
|
|
1121
|
+
overlayStyle
|
|
1122
|
+
]);
|
|
1123
|
+
const callbacksRef = useRef2({
|
|
1124
|
+
onCellToggle,
|
|
1125
|
+
onSelectionCommit
|
|
1126
|
+
});
|
|
1127
|
+
callbacksRef.current = {
|
|
1128
|
+
onCellToggle,
|
|
1129
|
+
onSelectionCommit
|
|
1130
|
+
};
|
|
1131
|
+
useEffect4(() => {
|
|
1132
|
+
const element = overlayInputRef.current;
|
|
1133
|
+
if (!element) {
|
|
1134
|
+
return;
|
|
1135
|
+
}
|
|
1136
|
+
const detachPointer = attachPointerHandlers(element, {
|
|
1137
|
+
registry,
|
|
1138
|
+
atoms,
|
|
1139
|
+
headers,
|
|
1140
|
+
handlers: {
|
|
1141
|
+
onCellToggle: (coord, mode) => callbacksRef.current.onCellToggle?.(coord, mode),
|
|
1142
|
+
onSelectionCommit: (range) => callbacksRef.current.onSelectionCommit?.(range)
|
|
1143
|
+
}
|
|
1144
|
+
});
|
|
1145
|
+
const detachWheel = attachWheelHandlers(element, {
|
|
1146
|
+
registry,
|
|
1147
|
+
atoms,
|
|
1148
|
+
headers
|
|
1149
|
+
});
|
|
1150
|
+
return () => {
|
|
1151
|
+
detachPointer();
|
|
1152
|
+
detachWheel();
|
|
1153
|
+
};
|
|
1154
|
+
}, [
|
|
1155
|
+
registry,
|
|
1156
|
+
atoms,
|
|
1157
|
+
headers
|
|
1158
|
+
]);
|
|
1159
|
+
return /* @__PURE__ */ React5.createElement("div", {
|
|
1160
|
+
ref: containerRef,
|
|
1161
|
+
className: mx5("relative w-full h-full overflow-hidden bg-baseSurface", classNames)
|
|
1162
|
+
}, /* @__PURE__ */ React5.createElement("canvas", {
|
|
1163
|
+
ref: staticCanvasRef,
|
|
1164
|
+
className: "absolute inset-0 pointer-events-none",
|
|
1165
|
+
style: {
|
|
1166
|
+
top: -1,
|
|
1167
|
+
left: -1
|
|
1168
|
+
}
|
|
1169
|
+
}), /* @__PURE__ */ React5.createElement("canvas", {
|
|
1170
|
+
ref: overlayCanvasRef,
|
|
1171
|
+
className: "absolute inset-0 pointer-events-none",
|
|
1172
|
+
style: {
|
|
1173
|
+
top: -1,
|
|
1174
|
+
left: -1
|
|
1175
|
+
}
|
|
1176
|
+
}), /* @__PURE__ */ React5.createElement("div", {
|
|
1177
|
+
ref: overlayInputRef,
|
|
1178
|
+
className: "absolute inset-0 touch-none",
|
|
1179
|
+
style: {
|
|
1180
|
+
paddingLeft: headers.left,
|
|
1181
|
+
paddingTop: headers.top
|
|
1182
|
+
}
|
|
1183
|
+
}), headers.top > 0 && /* @__PURE__ */ React5.createElement(Ruler, {
|
|
1184
|
+
viewport: viewportState,
|
|
1185
|
+
headers,
|
|
1186
|
+
width
|
|
1187
|
+
}), headers.left > 0 && /* @__PURE__ */ React5.createElement(TrackHeader, {
|
|
1188
|
+
viewport: viewportState,
|
|
1189
|
+
headers,
|
|
1190
|
+
rows,
|
|
1191
|
+
height
|
|
1192
|
+
}), headers.top > 0 && headers.left > 0 && /* @__PURE__ */ React5.createElement("div", {
|
|
1193
|
+
className: "absolute top-0 left-0 border-b border-r border-neutral-200 dark:border-neutral-700 bg-baseSurface",
|
|
1194
|
+
style: {
|
|
1195
|
+
width: headers.left,
|
|
1196
|
+
height: headers.top
|
|
1197
|
+
}
|
|
1198
|
+
}));
|
|
1199
|
+
};
|
|
1200
|
+
|
|
1201
|
+
// src/components/CellGrid/state/atoms.ts
|
|
1202
|
+
import { Atom } from "@effect-atom/atom-react";
|
|
1203
|
+
var defaultViewport = (options = {}) => ({
|
|
1204
|
+
scrollX: 0,
|
|
1205
|
+
scrollY: 0,
|
|
1206
|
+
baseCellWidth: options.cellWidth ?? 24,
|
|
1207
|
+
cellHeight: options.cellHeight ?? 24,
|
|
1208
|
+
zoomX: 1
|
|
1209
|
+
});
|
|
1210
|
+
var createCellGridAtoms = (options = {}) => ({
|
|
1211
|
+
cells: Atom.keepAlive(Atom.make(/* @__PURE__ */ new Map())),
|
|
1212
|
+
viewport: Atom.keepAlive(Atom.make(defaultViewport(options))),
|
|
1213
|
+
selection: Atom.keepAlive(Atom.make({
|
|
1214
|
+
range: null
|
|
1215
|
+
})),
|
|
1216
|
+
playhead: Atom.keepAlive(Atom.make(null)),
|
|
1217
|
+
tool: Atom.keepAlive(Atom.make("toggle"))
|
|
1218
|
+
});
|
|
1219
|
+
|
|
1220
|
+
// src/components/FPS.tsx
|
|
1221
|
+
import React6, { useEffect as useEffect5, useReducer, useRef as useRef3 } from "react";
|
|
1222
|
+
import { mx as mx6 } from "@dxos/ui-theme";
|
|
481
1223
|
var SEC = 1e3;
|
|
482
1224
|
var FPS = ({ classNames, width = 60, height = 30, bar = "bg-cyan-500" }) => {
|
|
483
1225
|
const [{ fps, max, len }, dispatch] = useReducer((state) => {
|
|
@@ -510,12 +1252,12 @@ var FPS = ({ classNames, width = 60, height = 30, bar = "bg-cyan-500" }) => {
|
|
|
510
1252
|
frames: 0,
|
|
511
1253
|
prevTime: Date.now()
|
|
512
1254
|
});
|
|
513
|
-
const requestRef =
|
|
1255
|
+
const requestRef = useRef3(null);
|
|
514
1256
|
const tick = () => {
|
|
515
1257
|
dispatch();
|
|
516
1258
|
requestRef.current = requestAnimationFrame(tick);
|
|
517
1259
|
};
|
|
518
|
-
|
|
1260
|
+
useEffect5(() => {
|
|
519
1261
|
requestRef.current = requestAnimationFrame(tick);
|
|
520
1262
|
return () => {
|
|
521
1263
|
if (requestRef.current) {
|
|
@@ -523,17 +1265,17 @@ var FPS = ({ classNames, width = 60, height = 30, bar = "bg-cyan-500" }) => {
|
|
|
523
1265
|
}
|
|
524
1266
|
};
|
|
525
1267
|
}, []);
|
|
526
|
-
return /* @__PURE__ */
|
|
1268
|
+
return /* @__PURE__ */ React6.createElement("div", {
|
|
527
1269
|
style: {
|
|
528
1270
|
width: width + 6
|
|
529
1271
|
},
|
|
530
|
-
className:
|
|
531
|
-
}, /* @__PURE__ */
|
|
1272
|
+
className: mx6("relative flex flex-col p-0.5", "bg-base-surface text-xs text-subdued font-thin pointer-events-none border border-separator", classNames)
|
|
1273
|
+
}, /* @__PURE__ */ React6.createElement("div", null, fps[len - 1], " FPS"), /* @__PURE__ */ React6.createElement("div", {
|
|
532
1274
|
className: "w-full relative",
|
|
533
1275
|
style: {
|
|
534
1276
|
height
|
|
535
1277
|
}
|
|
536
|
-
}, fps.map((frame, i) => /* @__PURE__ */
|
|
1278
|
+
}, fps.map((frame, i) => /* @__PURE__ */ React6.createElement("div", {
|
|
537
1279
|
key: `fps-${i}`,
|
|
538
1280
|
className: bar,
|
|
539
1281
|
style: {
|
|
@@ -547,9 +1289,9 @@ var FPS = ({ classNames, width = 60, height = 30, bar = "bg-cyan-500" }) => {
|
|
|
547
1289
|
};
|
|
548
1290
|
|
|
549
1291
|
// src/components/Grid/Grid.tsx
|
|
550
|
-
import
|
|
1292
|
+
import React7, { forwardRef as forwardRef2, useId, useMemo as useMemo4 } from "react";
|
|
551
1293
|
import { useForwardedRef } from "@dxos/react-ui";
|
|
552
|
-
import { mx as
|
|
1294
|
+
import { mx as mx7 } from "@dxos/ui-theme";
|
|
553
1295
|
var gridRatios = [
|
|
554
1296
|
1 / 4,
|
|
555
1297
|
1,
|
|
@@ -564,7 +1306,7 @@ var defaultOffset = {
|
|
|
564
1306
|
var createId = (parent, grid) => `dx-canvas-grid-${parent}-${grid}`;
|
|
565
1307
|
var Grid = (props) => {
|
|
566
1308
|
const { scale, offset } = useCanvasContext();
|
|
567
|
-
return /* @__PURE__ */
|
|
1309
|
+
return /* @__PURE__ */ React7.createElement(GridComponent, {
|
|
568
1310
|
...props,
|
|
569
1311
|
scale,
|
|
570
1312
|
offset
|
|
@@ -574,35 +1316,35 @@ var GridComponent = /* @__PURE__ */ forwardRef2(({ size: gridSize = defaultGridS
|
|
|
574
1316
|
const svgRef = useForwardedRef(forwardedRef);
|
|
575
1317
|
const { width = 0, height = 0 } = svgRef.current?.getBoundingClientRect() ?? {};
|
|
576
1318
|
const instanceId = useId();
|
|
577
|
-
const grids =
|
|
1319
|
+
const grids = useMemo4(() => gridRatios.map((ratio) => ({
|
|
578
1320
|
id: ratio,
|
|
579
1321
|
size: ratio * gridSize * scale
|
|
580
1322
|
})).filter(({ size }) => size >= gridSize && size <= 128), [
|
|
581
1323
|
gridSize,
|
|
582
1324
|
scale
|
|
583
1325
|
]);
|
|
584
|
-
return /* @__PURE__ */
|
|
1326
|
+
return /* @__PURE__ */ React7.createElement("svg", {
|
|
585
1327
|
...testId("dx-canvas-grid"),
|
|
586
1328
|
ref: svgRef,
|
|
587
|
-
className:
|
|
588
|
-
}, /* @__PURE__ */
|
|
1329
|
+
className: mx7("dx-fullscreen pointer-events-none touch-none select-none", "stroke-neutral-500", classNames)
|
|
1330
|
+
}, /* @__PURE__ */ React7.createElement("defs", null, grids.map(({ id, size }) => /* @__PURE__ */ React7.createElement(GridPattern, {
|
|
589
1331
|
key: id,
|
|
590
1332
|
id: createId(instanceId, id),
|
|
591
1333
|
offset,
|
|
592
1334
|
size
|
|
593
|
-
}))), showAxes && /* @__PURE__ */
|
|
1335
|
+
}))), showAxes && /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement("line", {
|
|
594
1336
|
x1: 0,
|
|
595
1337
|
y1: offset.y,
|
|
596
1338
|
x2: width,
|
|
597
1339
|
y2: offset.y,
|
|
598
1340
|
className: "stroke-neutral-500 opacity-40"
|
|
599
|
-
}), /* @__PURE__ */
|
|
1341
|
+
}), /* @__PURE__ */ React7.createElement("line", {
|
|
600
1342
|
x1: offset.x,
|
|
601
1343
|
y1: 0,
|
|
602
1344
|
x2: offset.x,
|
|
603
1345
|
y2: height,
|
|
604
1346
|
className: "stroke-neutral-500 opacity-40"
|
|
605
|
-
})), /* @__PURE__ */
|
|
1347
|
+
})), /* @__PURE__ */ React7.createElement("g", null, grids.map(({ id }, i) => /* @__PURE__ */ React7.createElement("rect", {
|
|
606
1348
|
key: id,
|
|
607
1349
|
opacity: 0.1 + i * 0.05,
|
|
608
1350
|
fill: `url(#${createId(instanceId, id)})`,
|
|
@@ -626,6 +1368,7 @@ export {
|
|
|
626
1368
|
Arrow,
|
|
627
1369
|
Canvas,
|
|
628
1370
|
CanvasContext,
|
|
1371
|
+
CellGrid,
|
|
629
1372
|
DATA_TEST_ID,
|
|
630
1373
|
Dimension,
|
|
631
1374
|
FPS,
|
|
@@ -637,15 +1380,31 @@ export {
|
|
|
637
1380
|
Point,
|
|
638
1381
|
ProjectionMapper,
|
|
639
1382
|
Rect,
|
|
1383
|
+
Ruler,
|
|
1384
|
+
TrackHeader,
|
|
1385
|
+
attachPointerHandlers,
|
|
1386
|
+
attachWheelHandlers,
|
|
1387
|
+
cellKey,
|
|
1388
|
+
cellWidth,
|
|
1389
|
+
createCellGridAtoms,
|
|
640
1390
|
createPath,
|
|
641
1391
|
defaultOrigin,
|
|
1392
|
+
defaultViewport,
|
|
1393
|
+
drawCells,
|
|
1394
|
+
drawOverlay,
|
|
642
1395
|
getRelativePoint,
|
|
643
1396
|
getZoomTransform,
|
|
1397
|
+
hitTestCell,
|
|
644
1398
|
inspectElement,
|
|
1399
|
+
screenToWorld,
|
|
645
1400
|
testId,
|
|
1401
|
+
toggleCell,
|
|
646
1402
|
useCanvasContext,
|
|
647
1403
|
useDrag,
|
|
648
1404
|
useWheel,
|
|
1405
|
+
visibleCellRange,
|
|
1406
|
+
visibleCells,
|
|
1407
|
+
worldToScreen,
|
|
649
1408
|
zoomInPlace,
|
|
650
1409
|
zoomTo
|
|
651
1410
|
};
|