@geomak/ui 2.0.0 → 3.0.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.cjs +199 -61
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +69 -16
- package/dist/index.d.ts +69 -16
- package/dist/index.js +200 -62
- package/dist/index.js.map +1 -1
- package/dist/styles.css +50 -26
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1465,70 +1465,208 @@ function ContextMenuLabel({ icon, value }) {
|
|
|
1465
1465
|
function ChevronRight2() {
|
|
1466
1466
|
return /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4 flex-shrink-0", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) });
|
|
1467
1467
|
}
|
|
1468
|
-
function
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1468
|
+
function readDismissed(key) {
|
|
1469
|
+
if (key === null) return false;
|
|
1470
|
+
if (typeof window === "undefined") return false;
|
|
1471
|
+
try {
|
|
1472
|
+
return window.localStorage.getItem(key) === "true";
|
|
1473
|
+
} catch {
|
|
1474
|
+
return false;
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
function writeDismissed(key) {
|
|
1478
|
+
if (key === null) return;
|
|
1479
|
+
if (typeof window === "undefined") return;
|
|
1480
|
+
try {
|
|
1481
|
+
window.localStorage.setItem(key, "true");
|
|
1482
|
+
} catch {
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
function useTargetBbox(ref) {
|
|
1486
|
+
const [bbox, setBbox] = React8.useState(null);
|
|
1487
|
+
React8.useLayoutEffect(() => {
|
|
1488
|
+
const el = ref?.current;
|
|
1489
|
+
if (!el) {
|
|
1490
|
+
setBbox(null);
|
|
1484
1491
|
return;
|
|
1485
1492
|
}
|
|
1486
|
-
const
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
const
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1493
|
+
const update = () => setBbox(el.getBoundingClientRect());
|
|
1494
|
+
update();
|
|
1495
|
+
window.addEventListener("scroll", update, true);
|
|
1496
|
+
window.addEventListener("resize", update);
|
|
1497
|
+
const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(update) : null;
|
|
1498
|
+
ro?.observe(el);
|
|
1499
|
+
return () => {
|
|
1500
|
+
window.removeEventListener("scroll", update, true);
|
|
1501
|
+
window.removeEventListener("resize", update);
|
|
1502
|
+
ro?.disconnect();
|
|
1503
|
+
};
|
|
1504
|
+
}, [ref]);
|
|
1505
|
+
return bbox;
|
|
1506
|
+
}
|
|
1507
|
+
var TOOLTIP_WIDTH = 280;
|
|
1508
|
+
var TOOLTIP_GAP = 12;
|
|
1509
|
+
function tooltipStyleFor(bbox, placement) {
|
|
1510
|
+
const pl = placement ?? "right";
|
|
1511
|
+
if (pl === "right") return { left: bbox.right + TOOLTIP_GAP, top: bbox.top + bbox.height / 2, transform: "translateY(-50%)", width: TOOLTIP_WIDTH };
|
|
1512
|
+
if (pl === "left") return { left: bbox.left - TOOLTIP_WIDTH - TOOLTIP_GAP, top: bbox.top + bbox.height / 2, transform: "translateY(-50%)", width: TOOLTIP_WIDTH };
|
|
1513
|
+
if (pl === "bottom") return { left: bbox.left + bbox.width / 2, top: bbox.bottom + TOOLTIP_GAP, transform: "translateX(-50%)", width: TOOLTIP_WIDTH };
|
|
1514
|
+
return { left: bbox.left + bbox.width / 2, top: bbox.top - TOOLTIP_GAP, transform: "translate(-50%, -100%)", width: TOOLTIP_WIDTH };
|
|
1515
|
+
}
|
|
1516
|
+
function useFocusTrap(containerRef, active) {
|
|
1517
|
+
React8.useEffect(() => {
|
|
1518
|
+
if (!active) return;
|
|
1519
|
+
const el = containerRef.current;
|
|
1520
|
+
if (!el) return;
|
|
1521
|
+
const t = setTimeout(() => {
|
|
1522
|
+
const first = el.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
|
|
1523
|
+
first?.focus();
|
|
1524
|
+
}, 0);
|
|
1525
|
+
const onKey = (e) => {
|
|
1526
|
+
if (e.key !== "Tab") return;
|
|
1527
|
+
const focusables = el.querySelectorAll(
|
|
1528
|
+
'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
|
|
1529
|
+
);
|
|
1530
|
+
if (focusables.length === 0) return;
|
|
1531
|
+
const first = focusables[0];
|
|
1532
|
+
const last = focusables[focusables.length - 1];
|
|
1533
|
+
if (e.shiftKey && document.activeElement === first) {
|
|
1534
|
+
e.preventDefault();
|
|
1535
|
+
last.focus();
|
|
1536
|
+
} else if (!e.shiftKey && document.activeElement === last) {
|
|
1537
|
+
e.preventDefault();
|
|
1538
|
+
first.focus();
|
|
1539
|
+
}
|
|
1540
|
+
};
|
|
1541
|
+
document.addEventListener("keydown", onKey);
|
|
1542
|
+
return () => {
|
|
1543
|
+
clearTimeout(t);
|
|
1544
|
+
document.removeEventListener("keydown", onKey);
|
|
1545
|
+
};
|
|
1546
|
+
}, [containerRef, active]);
|
|
1547
|
+
}
|
|
1548
|
+
function Wizard({
|
|
1549
|
+
children,
|
|
1550
|
+
steps,
|
|
1551
|
+
storageKey = "oxygen.wizard.completed",
|
|
1552
|
+
dismissible = true,
|
|
1553
|
+
onComplete,
|
|
1554
|
+
onSkip
|
|
1555
|
+
}) {
|
|
1556
|
+
const tooltipRef = React8.useRef(null);
|
|
1557
|
+
const tooltipTitleId = React8.useId();
|
|
1558
|
+
const tooltipBodyId = React8.useId();
|
|
1559
|
+
const [open, setOpen] = React8.useState(() => steps.length > 0 && !readDismissed(storageKey));
|
|
1560
|
+
const [activeIndex, setActiveIndex] = React8.useState(0);
|
|
1561
|
+
const step = steps[activeIndex];
|
|
1562
|
+
const bbox = useTargetBbox(step?.stepRef);
|
|
1563
|
+
useFocusTrap(tooltipRef, open);
|
|
1564
|
+
React8.useEffect(() => {
|
|
1565
|
+
if (!open || !dismissible) return;
|
|
1566
|
+
const onKey = (e) => {
|
|
1567
|
+
if (e.key === "Escape") {
|
|
1568
|
+
e.preventDefault();
|
|
1569
|
+
handleSkip();
|
|
1529
1570
|
}
|
|
1530
|
-
|
|
1531
|
-
|
|
1571
|
+
};
|
|
1572
|
+
document.addEventListener("keydown", onKey);
|
|
1573
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
1574
|
+
}, [open, dismissible]);
|
|
1575
|
+
const handleSkip = React8.useCallback(() => {
|
|
1576
|
+
writeDismissed(storageKey);
|
|
1577
|
+
setOpen(false);
|
|
1578
|
+
onSkip?.();
|
|
1579
|
+
}, [storageKey, onSkip]);
|
|
1580
|
+
const handleComplete = React8.useCallback(() => {
|
|
1581
|
+
writeDismissed(storageKey);
|
|
1582
|
+
setOpen(false);
|
|
1583
|
+
onComplete?.();
|
|
1584
|
+
}, [storageKey, onComplete]);
|
|
1585
|
+
const handleNext = () => {
|
|
1586
|
+
if (activeIndex < steps.length - 1) setActiveIndex((i) => i + 1);
|
|
1587
|
+
else handleComplete();
|
|
1588
|
+
};
|
|
1589
|
+
const handlePrev = () => {
|
|
1590
|
+
if (activeIndex > 0) setActiveIndex((i) => i - 1);
|
|
1591
|
+
};
|
|
1592
|
+
const highlightStyle = bbox ? {
|
|
1593
|
+
left: bbox.left - 4,
|
|
1594
|
+
top: bbox.top - 4,
|
|
1595
|
+
width: bbox.width + 8,
|
|
1596
|
+
height: bbox.height + 8
|
|
1597
|
+
} : { display: "none" };
|
|
1598
|
+
const tooltipStyle = bbox ? tooltipStyleFor(bbox, step?.placement) : { display: "none" };
|
|
1599
|
+
const isLast = activeIndex === steps.length - 1;
|
|
1600
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1601
|
+
children,
|
|
1602
|
+
open && step && /* @__PURE__ */ jsxRuntime.jsxs(Portal, { children: [
|
|
1603
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1604
|
+
"div",
|
|
1605
|
+
{
|
|
1606
|
+
className: "fixed inset-0 z-[7000000] bg-foreground/40 backdrop-blur-[1px] pointer-events-auto",
|
|
1607
|
+
"aria-hidden": "true"
|
|
1608
|
+
}
|
|
1609
|
+
),
|
|
1610
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1611
|
+
"div",
|
|
1612
|
+
{
|
|
1613
|
+
className: "fixed z-[7000001] pointer-events-none rounded-md ring-2 ring-accent ring-offset-2 ring-offset-background transition-all duration-200",
|
|
1614
|
+
style: highlightStyle,
|
|
1615
|
+
"aria-hidden": "true"
|
|
1616
|
+
}
|
|
1617
|
+
),
|
|
1618
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1619
|
+
"div",
|
|
1620
|
+
{
|
|
1621
|
+
ref: tooltipRef,
|
|
1622
|
+
role: "dialog",
|
|
1623
|
+
"aria-modal": "true",
|
|
1624
|
+
"aria-labelledby": step.title ? tooltipTitleId : void 0,
|
|
1625
|
+
"aria-describedby": tooltipBodyId,
|
|
1626
|
+
className: "fixed z-[7000002] rounded-lg bg-surface text-foreground border border-border shadow-xl p-4 pointer-events-auto",
|
|
1627
|
+
style: tooltipStyle,
|
|
1628
|
+
children: [
|
|
1629
|
+
step.title && /* @__PURE__ */ jsxRuntime.jsx("h3", { id: tooltipTitleId, className: "text-sm font-semibold text-foreground mb-1", children: step.title }),
|
|
1630
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { id: tooltipBodyId, className: "text-sm text-foreground-secondary leading-relaxed", children: step.description }),
|
|
1631
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex items-center justify-between", children: [
|
|
1632
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-foreground-muted tabular-nums", children: [
|
|
1633
|
+
activeIndex + 1,
|
|
1634
|
+
" / ",
|
|
1635
|
+
steps.length
|
|
1636
|
+
] }),
|
|
1637
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1638
|
+
dismissible && !isLast && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1639
|
+
Button,
|
|
1640
|
+
{
|
|
1641
|
+
variant: "ghost",
|
|
1642
|
+
size: "sm",
|
|
1643
|
+
content: "Skip",
|
|
1644
|
+
onClick: handleSkip
|
|
1645
|
+
}
|
|
1646
|
+
),
|
|
1647
|
+
activeIndex > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1648
|
+
Button,
|
|
1649
|
+
{
|
|
1650
|
+
variant: "secondary",
|
|
1651
|
+
size: "sm",
|
|
1652
|
+
content: "Back",
|
|
1653
|
+
onClick: handlePrev
|
|
1654
|
+
}
|
|
1655
|
+
),
|
|
1656
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1657
|
+
Button,
|
|
1658
|
+
{
|
|
1659
|
+
size: "sm",
|
|
1660
|
+
content: isLast ? "Done" : "Next",
|
|
1661
|
+
onClick: handleNext
|
|
1662
|
+
}
|
|
1663
|
+
)
|
|
1664
|
+
] })
|
|
1665
|
+
] })
|
|
1666
|
+
]
|
|
1667
|
+
}
|
|
1668
|
+
)
|
|
1669
|
+
] })
|
|
1532
1670
|
] });
|
|
1533
1671
|
}
|
|
1534
1672
|
var SearchInput = React8__default.default.forwardRef(function SearchInput2({
|