@geomak/ui 7.7.0 → 7.7.1

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 CHANGED
@@ -1213,7 +1213,7 @@ function TabsTrigger({ value, icon, badge, closeable, onClose, disabled, classNa
1213
1213
  {
1214
1214
  value,
1215
1215
  disabled,
1216
- className: cx(base, sz.trigger, layoutCls, closeable ? "pr-8" : "", variantCls, className),
1216
+ className: cx(base, sz.trigger, layoutCls, closeable ? "!pr-8" : "", variantCls, className),
1217
1217
  children: [
1218
1218
  variant === "segmented" && isActive && /* @__PURE__ */ jsxRuntime.jsx(
1219
1219
  framerMotion.motion.span,
@@ -1298,9 +1298,11 @@ function TreeNodeItem({
1298
1298
  item,
1299
1299
  onNodeClick,
1300
1300
  defaultExpandAll,
1301
- defaultExpandedKeys
1301
+ defaultExpandedKeys,
1302
+ leafIcon
1302
1303
  }) {
1303
1304
  if (!isParent(item)) {
1305
+ const glyph = item.icon ?? leafIcon;
1304
1306
  return /* @__PURE__ */ jsxRuntime.jsxs(
1305
1307
  "button",
1306
1308
  {
@@ -1314,7 +1316,10 @@ function TreeNodeItem({
1314
1316
  parentLabel: item.parentLabel
1315
1317
  }),
1316
1318
  children: [
1317
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-1.5 h-1.5 rounded-full flex-shrink-0 bg-foreground-muted group-hover:bg-accent transition-colors duration-150" }),
1319
+ glyph != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-4 w-4 flex-shrink-0 items-center justify-center text-foreground-muted group-hover:text-accent transition-colors duration-150", children: glyph }) : (
1320
+ /* Default leaf bullet */
1321
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-1.5 h-1.5 rounded-full flex-shrink-0 bg-foreground-muted group-hover:bg-accent transition-colors duration-150" })
1322
+ ),
1318
1323
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-foreground-secondary group-hover:text-foreground transition-colors duration-150", children: item.label })
1319
1324
  ]
1320
1325
  }
@@ -1322,48 +1327,53 @@ function TreeNodeItem({
1322
1327
  }
1323
1328
  const initialOpen = defaultExpandAll || defaultExpandedKeys.includes(item.key) ? [item.key] : [];
1324
1329
  return /* @__PURE__ */ jsxRuntime.jsx(AccordionPrimitive__namespace.Root, { type: "multiple", defaultValue: initialOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(AccordionPrimitive__namespace.Item, { value: item.key, className: "border-none", children: [
1325
- /* @__PURE__ */ jsxRuntime.jsxs(
1326
- AccordionPrimitive__namespace.Trigger,
1327
- {
1328
- onClick: () => onNodeClick({
1329
- isParent: true,
1330
- key: item.key,
1331
- label: item.label,
1332
- data: item.nodeData,
1333
- parentLabel: item.parentLabel
1334
- }),
1335
- className: "flex items-center gap-2 cursor-pointer py-1.5 px-2 group focus:outline-none focus-visible:ring-2 focus-visible:ring-accent w-full text-left rounded-md hover:bg-surface-raised transition-colors duration-150",
1336
- children: [
1337
- /* @__PURE__ */ jsxRuntime.jsx(
1330
+ /* @__PURE__ */ jsxRuntime.jsx(AccordionPrimitive__namespace.Header, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center rounded-md hover:bg-surface-raised transition-colors duration-150", children: [
1331
+ /* @__PURE__ */ jsxRuntime.jsx(
1332
+ AccordionPrimitive__namespace.Trigger,
1333
+ {
1334
+ "aria-label": `Toggle ${item.label}`,
1335
+ className: "group flex flex-shrink-0 items-center justify-center rounded-md p-1.5 cursor-pointer text-foreground-muted hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-inset transition-colors duration-150",
1336
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1338
1337
  "svg",
1339
1338
  {
1340
1339
  viewBox: "0 0 24 24",
1341
1340
  fill: "none",
1342
1341
  stroke: "currentColor",
1343
1342
  strokeWidth: 2.5,
1344
- className: "h-3.5 w-3.5 flex-shrink-0 text-foreground-muted transition-transform duration-200 group-data-[state=open]:rotate-0 group-data-[state=closed]:-rotate-90",
1343
+ className: "h-3.5 w-3.5 transition-transform duration-200 group-data-[state=open]:rotate-0 group-data-[state=closed]:-rotate-90",
1345
1344
  "aria-hidden": "true",
1346
- children: /* @__PURE__ */ jsxRuntime.jsx(
1347
- "path",
1348
- {
1349
- strokeLinecap: "round",
1350
- strokeLinejoin: "round",
1351
- d: "M19 9l-7 7-7-7"
1352
- }
1353
- )
1345
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
1354
1346
  }
1355
- ),
1356
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-foreground select-none", children: item.label })
1357
- ]
1358
- }
1359
- ),
1347
+ )
1348
+ }
1349
+ ),
1350
+ /* @__PURE__ */ jsxRuntime.jsxs(
1351
+ "button",
1352
+ {
1353
+ type: "button",
1354
+ onClick: () => onNodeClick({
1355
+ isParent: true,
1356
+ key: item.key,
1357
+ label: item.label,
1358
+ data: item.nodeData,
1359
+ parentLabel: item.parentLabel
1360
+ }),
1361
+ className: "flex flex-1 min-w-0 items-center gap-2 py-1.5 pr-2 text-left cursor-pointer rounded-md focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-inset",
1362
+ children: [
1363
+ item.icon != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-4 w-4 flex-shrink-0 items-center justify-center text-foreground-muted", children: item.icon }),
1364
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm font-semibold text-foreground select-none", children: item.label })
1365
+ ]
1366
+ }
1367
+ )
1368
+ ] }) }),
1360
1369
  /* @__PURE__ */ jsxRuntime.jsx(AccordionPrimitive__namespace.Content, { className: "overflow-hidden data-[state=open]:animate-accordion-down data-[state=closed]:animate-accordion-up", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-3.5 border-l border-border py-0.5", children: item.children.map((child) => /* @__PURE__ */ jsxRuntime.jsx(
1361
1370
  TreeNodeItem,
1362
1371
  {
1363
1372
  item: child,
1364
1373
  onNodeClick,
1365
1374
  defaultExpandAll,
1366
- defaultExpandedKeys
1375
+ defaultExpandedKeys,
1376
+ leafIcon
1367
1377
  },
1368
1378
  child.key
1369
1379
  )) }) })
@@ -1374,6 +1384,7 @@ function Tree({
1374
1384
  onNodeClick,
1375
1385
  defaultExpandAll = false,
1376
1386
  defaultExpandedKeys = [],
1387
+ leafIcon,
1377
1388
  className = "",
1378
1389
  style
1379
1390
  }) {
@@ -1383,7 +1394,8 @@ function Tree({
1383
1394
  item,
1384
1395
  onNodeClick,
1385
1396
  defaultExpandAll,
1386
- defaultExpandedKeys
1397
+ defaultExpandedKeys,
1398
+ leafIcon
1387
1399
  },
1388
1400
  item.key
1389
1401
  )) });
@@ -4681,6 +4693,8 @@ var TOGGLE_POSITION_CLASS = {
4681
4693
  function ScalableContainer({
4682
4694
  width = "100%",
4683
4695
  height = "auto",
4696
+ targetWidth,
4697
+ targetHeight,
4684
4698
  expandedWidth = "100%",
4685
4699
  expandedHeight = "100%",
4686
4700
  expanded,
@@ -4690,100 +4704,40 @@ function ScalableContainer({
4690
4704
  expandIcon,
4691
4705
  collapseIcon,
4692
4706
  togglePosition = "top-right",
4693
- expandContainerRef,
4694
- expandRatio = 3,
4695
4707
  className = ""
4696
4708
  }) {
4697
4709
  const containerRef = React31.useRef(null);
4698
4710
  const [internalScaled, setInternalScaled] = React31.useState(false);
4699
4711
  const isScaled = expanded ?? internalScaled;
4700
4712
  const reduced = framerMotion.useReducedMotion();
4701
- const usePush = expandContainerRef != null;
4702
- const grownRef = React31.useRef([]);
4703
4713
  const prevScaled = React31.useRef(isScaled);
4704
- const kickResizeDuringTransition = () => {
4714
+ const expandW = targetWidth ?? expandedWidth;
4715
+ const expandH = targetHeight ?? expandedHeight;
4716
+ React31.useEffect(() => {
4717
+ if (isScaled === prevScaled.current) return;
4718
+ prevScaled.current = isScaled;
4705
4719
  if (typeof window === "undefined") return;
4706
4720
  const kick = () => window.dispatchEvent(new Event("resize"));
4707
4721
  const interval = window.setInterval(kick, 80);
4708
- window.setTimeout(() => {
4722
+ const stop = window.setTimeout(() => {
4709
4723
  window.clearInterval(interval);
4710
4724
  kick();
4711
- }, reduced ? 0 : 400);
4712
- };
4713
- const growAncestors = () => {
4714
- const bound = expandContainerRef?.current;
4715
- if (!bound || !containerRef.current) return;
4716
- const grown = [];
4717
- let el = containerRef.current.parentElement;
4718
- while (el && el !== bound && bound.contains(el)) {
4719
- const parent = el.parentElement;
4720
- const parentStyle = parent ? getComputedStyle(parent) : null;
4721
- if (parent && parentStyle && parentStyle.display.includes("flex")) {
4722
- grown.push({
4723
- el,
4724
- parent,
4725
- prev: {
4726
- flexGrow: el.style.flexGrow,
4727
- flexBasis: el.style.flexBasis,
4728
- height: el.style.height,
4729
- transition: el.style.transition,
4730
- parentFlexWrap: parent.style.flexWrap
4731
- }
4732
- });
4733
- const t = (prop) => `${prop} ${reduced ? 0 : 0.32}s cubic-bezier(0.16, 1, 0.3, 1)`;
4734
- const ours = `${t("flex-grow")}, ${t("flex-basis")}, ${t("height")}`;
4735
- el.style.transition = el.style.transition ? `${el.style.transition}, ${ours}` : ours;
4736
- if (parentStyle.flexDirection.startsWith("row")) {
4737
- parent.style.flexWrap = "wrap";
4738
- el.style.flexBasis = "100%";
4739
- el.style.height = `${expandRatio / (expandRatio + 1) * 100}%`;
4740
- } else {
4741
- el.style.flexBasis = "0%";
4742
- el.style.flexGrow = String(expandRatio);
4743
- }
4744
- }
4745
- el = parent;
4746
- }
4747
- grownRef.current = grown;
4748
- };
4749
- const restoreAncestors = () => {
4750
- for (const { el, parent, prev } of grownRef.current) {
4751
- el.style.flexGrow = prev.flexGrow;
4752
- el.style.flexBasis = prev.flexBasis;
4753
- el.style.height = prev.height;
4754
- window.setTimeout(() => {
4755
- el.style.transition = prev.transition;
4756
- parent.style.flexWrap = prev.parentFlexWrap;
4757
- }, reduced ? 0 : 360);
4758
- }
4759
- grownRef.current = [];
4760
- };
4761
- React31.useEffect(() => {
4762
- if (!usePush || isScaled === prevScaled.current) return;
4763
- prevScaled.current = isScaled;
4764
- if (isScaled) growAncestors();
4765
- else restoreAncestors();
4766
- kickResizeDuringTransition();
4767
- }, [isScaled, usePush]);
4768
- React31.useEffect(() => () => {
4769
- for (const { el, parent, prev } of grownRef.current) {
4770
- el.style.flexGrow = prev.flexGrow;
4771
- el.style.flexBasis = prev.flexBasis;
4772
- el.style.height = prev.height;
4773
- el.style.transition = prev.transition;
4774
- parent.style.flexWrap = prev.parentFlexWrap;
4725
+ }, reduced ? 0 : 420);
4726
+ if (isScaled) {
4727
+ window.setTimeout(
4728
+ () => containerRef.current?.scrollIntoView({ behavior: "smooth", block: "nearest" }),
4729
+ reduced ? 0 : 360
4730
+ );
4775
4731
  }
4776
- }, []);
4732
+ return () => {
4733
+ window.clearInterval(interval);
4734
+ window.clearTimeout(stop);
4735
+ };
4736
+ }, [isScaled, reduced]);
4777
4737
  const onToggle = () => {
4778
4738
  const next = !isScaled;
4779
4739
  if (expanded === void 0) setInternalScaled(next);
4780
4740
  onExpandedChange?.(next);
4781
- if (next && !usePush) {
4782
- window.setTimeout(
4783
- () => containerRef.current?.scrollIntoView({ behavior: "smooth", block: "nearest" }),
4784
- reduced ? 0 : 340
4785
- );
4786
- }
4787
4741
  };
4788
4742
  const wrapperClass = isScaled ? assignClassOnClick : void 0;
4789
4743
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -4791,24 +4745,20 @@ function ScalableContainer({
4791
4745
  {
4792
4746
  ref: containerRef,
4793
4747
  style: {
4794
- width: isScaled && !usePush ? expandedWidth : width,
4795
- height: isScaled && !usePush ? expandedHeight : height
4796
- },
4797
- animate: {
4798
- // Push mode keeps the container filling its (now growing)
4799
- // wrapper — the wrapper's flex-grow does the work.
4800
- width: isScaled && !usePush ? expandedWidth : width,
4801
- height: isScaled && !usePush ? expandedHeight : height
4748
+ width: isScaled ? expandW : width,
4749
+ height: isScaled ? expandH : height,
4750
+ flex: isScaled ? "none" : void 0
4802
4751
  },
4752
+ animate: { width: isScaled ? expandW : width, height: isScaled ? expandH : height },
4803
4753
  transition: reduced ? { duration: 0 } : {
4804
4754
  width: { type: "tween", duration: 0.32, ease: [0.16, 1, 0.3, 1] },
4805
4755
  height: { type: "tween", duration: 0.32, ease: [0.16, 1, 0.3, 1] }
4806
4756
  },
4807
4757
  className: cx(
4808
4758
  "relative rounded-lg overflow-hidden",
4809
- // OS-window aesthetic: subtle elevation at rest, lifted shadow
4810
- // when expanded. No background colour change.
4811
- isScaled ? "shadow-2xl" : "shadow-md",
4759
+ // OS-window aesthetic: subtle elevation at rest, lifted shadow +
4760
+ // raised stacking when expanded so it sits above neighbours.
4761
+ isScaled ? "z-raised shadow-2xl" : "shadow-md",
4812
4762
  "transition-shadow duration-300",
4813
4763
  className
4814
4764
  ),