@almadar/ui 5.121.3 → 5.121.4

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.
@@ -1088,9 +1088,9 @@ function getGlobalEventBus() {
1088
1088
  function useEventBus() {
1089
1089
  const context = React73.useContext(providers.EventBusContext);
1090
1090
  const baseBus = context ?? getGlobalEventBus() ?? fallbackEventBus;
1091
- const scope = providers.useTraitScope();
1091
+ const chain = providers.useTraitScopeChain();
1092
1092
  return React73.useMemo(() => {
1093
- if (!scope) {
1093
+ if (chain.length === 0) {
1094
1094
  return {
1095
1095
  ...baseBus,
1096
1096
  emit: (type, payload, source) => {
@@ -1106,22 +1106,31 @@ function useEventBus() {
1106
1106
  emit: (type, payload, source) => {
1107
1107
  if (typeof type === "string" && type.startsWith("UI:")) {
1108
1108
  const tail = type.slice(3);
1109
- const qualified = tail.includes(".") ? type : `UI:${scope.orbital}.${scope.trait}.${tail}`;
1110
- if (qualified !== type) {
1111
- scopeLog.info("emit:qualified", {
1109
+ const isQualified = tail.includes(".");
1110
+ const event = isQualified ? tail.split(".").slice(2).join(".") : tail;
1111
+ if (!event) {
1112
+ baseBus.emit(type, payload, source);
1113
+ return;
1114
+ }
1115
+ const keys = /* @__PURE__ */ new Set();
1116
+ if (isQualified) keys.add(type);
1117
+ for (const sc of chain) {
1118
+ keys.add(`UI:${sc.orbital}.${sc.trait}.${event}`);
1119
+ }
1120
+ if (keys.size > 1) {
1121
+ scopeLog.info("emit:fan-out", {
1112
1122
  from: type,
1113
- to: qualified,
1114
- scopeOrbital: scope.orbital,
1115
- scopeTrait: scope.trait
1123
+ keys: Array.from(keys),
1124
+ chainDepth: chain.length
1116
1125
  });
1117
1126
  }
1118
- baseBus.emit(qualified, payload, source);
1127
+ for (const key of keys) baseBus.emit(key, payload, source);
1119
1128
  return;
1120
1129
  }
1121
1130
  baseBus.emit(type, payload, source);
1122
1131
  }
1123
1132
  };
1124
- }, [baseBus, scope]);
1133
+ }, [baseBus, chain]);
1125
1134
  }
1126
1135
  function useEventListener(event, handler) {
1127
1136
  const eventBus = useEventBus();
@@ -1398,13 +1407,13 @@ var init_Icon = __esm({
1398
1407
  style
1399
1408
  }) => {
1400
1409
  const directIcon = typeof icon === "string" ? void 0 : icon;
1401
- const effectiveName = typeof icon === "string" ? icon : name;
1410
+ const effectiveName = typeof icon === "string" && icon !== "" ? icon : name;
1411
+ const effectiveStrokeWidth = strokeWidth != null && strokeWidth > 0 ? strokeWidth : void 0;
1402
1412
  const family = useIconFamily();
1403
1413
  const RenderedComponent = React73__namespace.default.useMemo(() => {
1404
1414
  if (directIcon) return null;
1405
1415
  return effectiveName ? resolveIconForFamily(effectiveName) : null;
1406
1416
  }, [directIcon, effectiveName, family]);
1407
- const effectiveStrokeWidth = strokeWidth ?? void 0;
1408
1417
  const inlineStyle = {
1409
1418
  ...effectiveStrokeWidth === void 0 ? { strokeWidth: "var(--icon-stroke-width, 2)" } : {},
1410
1419
  ...style
@@ -1881,7 +1890,7 @@ var init_Input = __esm({
1881
1890
  eventBus.emit(`UI:${action}`, { value: e.currentTarget.value });
1882
1891
  }
1883
1892
  };
1884
- const wrapField = (field) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full", children: [
1893
+ const wrapField = (field, fullWidth = true) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: fullWidth ? "w-full" : "w-fit", children: [
1885
1894
  label && /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium text-foreground mb-1", children: label }),
1886
1895
  field,
1887
1896
  (helperText || error) && /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("mt-1 text-xs", error ? "text-error" : "text-muted-foreground"), children: error ?? helperText })
@@ -1941,7 +1950,8 @@ var init_Input = __esm({
1941
1950
  ),
1942
1951
  ...props
1943
1952
  }
1944
- )
1953
+ ),
1954
+ false
1945
1955
  );
1946
1956
  }
1947
1957
  return wrapField(
@@ -4110,6 +4120,7 @@ var init_Overlay = __esm({
4110
4120
  className: cn(
4111
4121
  "fixed inset-0 z-40",
4112
4122
  blur && "backdrop-blur-sm",
4123
+ "animate-overlay-in",
4113
4124
  className
4114
4125
  ),
4115
4126
  style: { backgroundColor: "rgba(0, 0, 0, 0.6)" },
@@ -4801,6 +4812,18 @@ var init_RangeSlider = __esm({
4801
4812
  function easeOut(t) {
4802
4813
  return t * (2 - t);
4803
4814
  }
4815
+ function formatDisplay(value, format, decimals) {
4816
+ switch (format) {
4817
+ case "currency":
4818
+ return `$${value.toFixed(2)}`;
4819
+ case "percent":
4820
+ return `${Math.round(value)}%`;
4821
+ case "number":
4822
+ return value.toLocaleString();
4823
+ default:
4824
+ return value.toFixed(decimals);
4825
+ }
4826
+ }
4804
4827
  exports.AnimatedCounter = void 0;
4805
4828
  var init_AnimatedCounter = __esm({
4806
4829
  "components/marketing/atoms/AnimatedCounter.tsx"() {
@@ -4812,6 +4835,7 @@ var init_AnimatedCounter = __esm({
4812
4835
  duration = 600,
4813
4836
  prefix,
4814
4837
  suffix,
4838
+ format,
4815
4839
  className
4816
4840
  }) => {
4817
4841
  const numericRaw = typeof rawValue === "number" ? rawValue : Number.parseFloat(String(rawValue ?? ""));
@@ -4827,6 +4851,10 @@ var init_AnimatedCounter = __esm({
4827
4851
  setDisplayValue(to);
4828
4852
  return;
4829
4853
  }
4854
+ if (window.matchMedia?.("(prefers-reduced-motion: reduce)").matches) {
4855
+ setDisplayValue(to);
4856
+ return;
4857
+ }
4830
4858
  const startTime = performance.now();
4831
4859
  const diff = to - from;
4832
4860
  function animate(currentTime) {
@@ -4848,7 +4876,7 @@ var init_AnimatedCounter = __esm({
4848
4876
  };
4849
4877
  }, [value, duration]);
4850
4878
  const decimalPlaces = Number.isInteger(value) ? 0 : String(value).split(".")[1]?.length ?? 0;
4851
- const formattedValue = displayValue.toFixed(decimalPlaces);
4879
+ const formattedValue = formatDisplay(displayValue, format, decimalPlaces);
4852
4880
  return /* @__PURE__ */ jsxRuntime.jsxs(exports.Typography, { variant: "h3", className: cn("tabular-nums", className), children: [
4853
4881
  prefix,
4854
4882
  formattedValue,
@@ -6061,6 +6089,15 @@ var init_Modal = __esm({
6061
6089
  const [dragY, setDragY] = React73.useState(0);
6062
6090
  const dragStartY = React73.useRef(0);
6063
6091
  const isDragging = React73.useRef(false);
6092
+ const [closing, setClosing] = React73.useState(false);
6093
+ const wasOpenRef = React73.useRef(isOpen);
6094
+ React73.useEffect(() => {
6095
+ if (wasOpenRef.current && !isOpen) setClosing(true);
6096
+ wasOpenRef.current = isOpen;
6097
+ }, [isOpen]);
6098
+ const handleAnimEnd = (e) => {
6099
+ if (closing && e.target === e.currentTarget) setClosing(false);
6100
+ };
6064
6101
  React73.useEffect(() => {
6065
6102
  if (isOpen) {
6066
6103
  previousActiveElement.current = document.activeElement;
@@ -6094,7 +6131,11 @@ var init_Modal = __esm({
6094
6131
  document.body.style.overflow = "";
6095
6132
  };
6096
6133
  }, [isOpen]);
6097
- if (!isOpen || typeof document === "undefined") return null;
6134
+ if (typeof document === "undefined") return null;
6135
+ const renderOpen = isOpen || closing;
6136
+ if (!renderOpen) return null;
6137
+ const dialogAnim = closing ? "animate-modal-out" : "animate-modal-in";
6138
+ const overlayAnim = closing ? "animate-overlay-out" : "animate-overlay-in";
6098
6139
  const handleClose = () => {
6099
6140
  if (closeEvent) eventBus.emit(`UI:${closeEvent}`, {});
6100
6141
  onClose();
@@ -6111,7 +6152,8 @@ var init_Modal = __esm({
6111
6152
  className: cn(
6112
6153
  "fixed inset-0 z-[1000]",
6113
6154
  "flex items-start justify-center px-4 pb-4 pt-[10vh]",
6114
- "max-sm:items-stretch max-sm:p-0 max-sm:pt-0"
6155
+ "max-sm:items-stretch max-sm:p-0 max-sm:pt-0",
6156
+ overlayAnim
6115
6157
  ),
6116
6158
  style: { backgroundColor: "rgba(0, 0, 0, 0.6)" },
6117
6159
  onClick: handleOverlayClick,
@@ -6139,8 +6181,10 @@ var init_Modal = __esm({
6139
6181
  // full height, no rounded corners, no min-width.
6140
6182
  "max-sm:max-w-none max-sm:max-h-none max-sm:w-full max-sm:h-full max-sm:rounded-none",
6141
6183
  lookStyles2[look],
6142
- className
6184
+ className,
6185
+ dialogAnim
6143
6186
  ),
6187
+ onAnimationEnd: handleAnimEnd,
6144
6188
  style: dragY > 0 ? {
6145
6189
  transform: `translateY(${dragY}px)`,
6146
6190
  transition: isDragging.current ? "none" : "transform 200ms ease-out"
@@ -9777,7 +9821,8 @@ var init_LoadingState = __esm({
9777
9821
  exports.LoadingState = ({
9778
9822
  title,
9779
9823
  message,
9780
- className
9824
+ className,
9825
+ fullPage = false
9781
9826
  }) => {
9782
9827
  const { t } = hooks.useTranslate();
9783
9828
  const displayMessage = message ?? t("common.loading");
@@ -9786,7 +9831,8 @@ var init_LoadingState = __esm({
9786
9831
  {
9787
9832
  align: "center",
9788
9833
  className: cn(
9789
- "justify-center py-12",
9834
+ "justify-center",
9835
+ fullPage ? "fixed inset-0 z-[1000] py-12 bg-background/80 backdrop-blur-sm animate-overlay-in" : "py-12",
9790
9836
  className
9791
9837
  ),
9792
9838
  children: [
@@ -12988,7 +13034,7 @@ var init_BookCoverPage = __esm({
12988
13034
  size: "lg",
12989
13035
  action: "BOOK_START",
12990
13036
  className: "mt-8",
12991
- children: /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "body", children: t("book.startReading") })
13037
+ children: /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "body", color: "inherit", children: t("book.startReading") })
12992
13038
  }
12993
13039
  )
12994
13040
  ]
@@ -15771,6 +15817,10 @@ function Canvas2D({
15771
15817
  window.removeEventListener("keyup", onUp);
15772
15818
  };
15773
15819
  }, [keyMap, keyUpMap, eventBus]);
15820
+ React73.useEffect(() => {
15821
+ if (!keyMap && !keyUpMap) return;
15822
+ canvasRef.current?.focus();
15823
+ }, [keyMap, keyUpMap]);
15774
15824
  if (error) {
15775
15825
  return /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: cn("flex items-center justify-center w-full h-full bg-[var(--color-card)] rounded-container", className), children: /* @__PURE__ */ jsxRuntime.jsxs(exports.Stack, { direction: "vertical", gap: "md", align: "center", children: [
15776
15826
  /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "alert-circle", size: "xl" }),
@@ -15819,7 +15869,7 @@ function Canvas2D({
15819
15869
  onWheel: gestureHandlers.onWheel,
15820
15870
  onContextMenu: (e) => e.preventDefault(),
15821
15871
  className: "cursor-pointer touch-none",
15822
- tabIndex: isFree ? 0 : void 0,
15872
+ tabIndex: isFree || keyMap || keyUpMap ? 0 : void 0,
15823
15873
  style: {
15824
15874
  width: viewportSize.width,
15825
15875
  height: viewportSize.height
@@ -16885,8 +16935,9 @@ var init_Chart = __esm({
16885
16935
  align: "center",
16886
16936
  flex: true,
16887
16937
  className: "min-w-0",
16938
+ style: { height: "100%" },
16888
16939
  children: [
16889
- /* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { gap: histogram ? "none" : "xs", align: "end", className: "w-full", style: { height: "100%" }, children: series.map((s, sIdx) => {
16940
+ /* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { gap: histogram ? "none" : "xs", align: "end", justify: histogram ? void 0 : "center", className: "w-full flex-1 min-h-0", children: series.map((s, sIdx) => {
16890
16941
  const value = valueAt(s, label);
16891
16942
  const barHeight = value / maxValue * 100;
16892
16943
  const color = seriesColor(s, sIdx);
@@ -16899,6 +16950,8 @@ var init_Chart = __esm({
16899
16950
  ),
16900
16951
  style: {
16901
16952
  height: `${barHeight}%`,
16953
+ // Cap width so a lone category doesn't paint the whole plot as one solid block; narrow columns are unaffected (flex-1 binds first).
16954
+ ...!histogram && { maxWidth: 72 },
16902
16955
  backgroundColor: color
16903
16956
  },
16904
16957
  onClick: () => onPointClick?.(
@@ -16933,8 +16986,9 @@ var init_Chart = __esm({
16933
16986
  align: "center",
16934
16987
  flex: true,
16935
16988
  className: "min-w-0",
16989
+ style: { height: "100%" },
16936
16990
  children: [
16937
- /* @__PURE__ */ jsxRuntime.jsx(exports.VStack, { gap: "none", className: "w-full", style: { height: "100%" }, justify: "end", children: series.map((s, sIdx) => {
16991
+ /* @__PURE__ */ jsxRuntime.jsx(exports.VStack, { gap: "none", className: "w-full flex-1 min-h-0", justify: "end", children: series.map((s, sIdx) => {
16938
16992
  const value = valueAt(s, label);
16939
16993
  const ratio = stack === "normalize" ? total === 0 ? 0 : value / total * 100 : value / maxValue * 100;
16940
16994
  const color = seriesColor(s, sIdx);
@@ -16979,6 +17033,7 @@ var init_Chart = __esm({
16979
17033
  const innerRadius = donut ? radius * 0.6 : 0;
16980
17034
  const center = size / 2;
16981
17035
  const segments = React73.useMemo(() => {
17036
+ if (!Number.isFinite(total) || total <= 0) return [];
16982
17037
  let currentAngle = -Math.PI / 2;
16983
17038
  return data.map((point, idx) => {
16984
17039
  const angle = point.value / total * 2 * Math.PI;
@@ -16990,13 +17045,25 @@ var init_Chart = __esm({
16990
17045
  const y1 = center + radius * Math.sin(startAngle);
16991
17046
  const x2 = center + radius * Math.cos(endAngle);
16992
17047
  const y2 = center + radius * Math.sin(endAngle);
17048
+ const fullCircle = angle >= 2 * Math.PI - 1e-9;
17049
+ const midAngle = startAngle + angle / 2;
17050
+ const xm = center + radius * Math.cos(midAngle);
17051
+ const ym = center + radius * Math.sin(midAngle);
16993
17052
  let d;
16994
17053
  if (innerRadius > 0) {
16995
17054
  const ix1 = center + innerRadius * Math.cos(startAngle);
16996
17055
  const iy1 = center + innerRadius * Math.sin(startAngle);
16997
17056
  const ix2 = center + innerRadius * Math.cos(endAngle);
16998
17057
  const iy2 = center + innerRadius * Math.sin(endAngle);
16999
- d = `M ${ix1} ${iy1} L ${x1} ${y1} A ${radius} ${radius} 0 ${largeArc} 1 ${x2} ${y2} L ${ix2} ${iy2} A ${innerRadius} ${innerRadius} 0 ${largeArc} 0 ${ix1} ${iy1} Z`;
17058
+ if (fullCircle) {
17059
+ const ixm = center + innerRadius * Math.cos(midAngle);
17060
+ const iym = center + innerRadius * Math.sin(midAngle);
17061
+ d = `M ${ix1} ${iy1} L ${x1} ${y1} A ${radius} ${radius} 0 1 1 ${xm} ${ym} A ${radius} ${radius} 0 1 1 ${x2} ${y2} L ${ix2} ${iy2} A ${innerRadius} ${innerRadius} 0 1 0 ${ixm} ${iym} A ${innerRadius} ${innerRadius} 0 1 0 ${ix1} ${iy1} Z`;
17062
+ } else {
17063
+ d = `M ${ix1} ${iy1} L ${x1} ${y1} A ${radius} ${radius} 0 ${largeArc} 1 ${x2} ${y2} L ${ix2} ${iy2} A ${innerRadius} ${innerRadius} 0 ${largeArc} 0 ${ix1} ${iy1} Z`;
17064
+ }
17065
+ } else if (fullCircle) {
17066
+ d = `M ${center} ${center} L ${x1} ${y1} A ${radius} ${radius} 0 1 1 ${xm} ${ym} A ${radius} ${radius} 0 1 1 ${x2} ${y2} Z`;
17000
17067
  } else {
17001
17068
  d = `M ${center} ${center} L ${x1} ${y1} A ${radius} ${radius} 0 ${largeArc} 1 ${x2} ${y2} Z`;
17002
17069
  }
@@ -20396,10 +20463,10 @@ function DataGrid({
20396
20463
  ] }),
20397
20464
  badgeFields.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { gap: "xs", className: "flex-wrap", children: badgeFields.map((field) => {
20398
20465
  const val = getNestedValue(itemData, field.name);
20399
- if (val === void 0 || val === null) return null;
20466
+ if (val === void 0 || val === null || val === "") return null;
20400
20467
  return /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "xs", className: "items-center", children: [
20401
20468
  field.icon && renderIconInput(field.icon, { size: "xs" }),
20402
- /* @__PURE__ */ jsxRuntime.jsx(exports.Badge, { variant: resolveBadgeVariant(field, String(val)), children: String(val) })
20469
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Badge, { variant: resolveBadgeVariant(field, String(val)), children: formatValue(val, field.format) })
20403
20470
  ] }, field.name);
20404
20471
  }) })
20405
20472
  ] }),
@@ -25790,7 +25857,7 @@ function GameMenu({
25790
25857
  logo,
25791
25858
  className
25792
25859
  }) {
25793
- const resolvedOptions = options ?? menuItems ?? DEFAULT_MENU_OPTIONS;
25860
+ const resolvedOptions = (options?.length ? options : void 0) ?? (menuItems?.length ? menuItems : void 0) ?? DEFAULT_MENU_OPTIONS;
25794
25861
  const eventBus = useEventBus();
25795
25862
  const handleOptionClick = React73__namespace.useCallback(
25796
25863
  (option) => {
@@ -31534,6 +31601,11 @@ var init_VoteStack = __esm({
31534
31601
  {
31535
31602
  className: cn(
31536
31603
  "inline-flex items-center justify-center",
31604
+ // Shrink-wrap in stretch contexts (slot/sidecar wrappers are
31605
+ // flex-column with stretch alignment): without this the root spans
31606
+ // the full wrapper width and the count row's `w-full` turns the
31607
+ // compact pill into a page-wide band.
31608
+ "w-fit",
31537
31609
  variant === "vertical" ? "flex-col" : "flex-row",
31538
31610
  "rounded-sm",
31539
31611
  "border-[length:var(--border-width)] border-border",
@@ -35439,7 +35511,7 @@ var init_Sidebar = __esm({
35439
35511
  isActive ? [
35440
35512
  "bg-primary text-primary-foreground",
35441
35513
  "font-medium shadow-sm",
35442
- "border-primary translate-x-1 -translate-y-0.5"
35514
+ "border-primary translate-x-1 rtl:-translate-x-1 -translate-y-0.5"
35443
35515
  ].join(" ") : [
35444
35516
  "text-foreground",
35445
35517
  "hover:bg-muted hover:border-border",
@@ -35449,10 +35521,10 @@ var init_Sidebar = __esm({
35449
35521
  title: collapsed ? item.label : void 0,
35450
35522
  children: [
35451
35523
  item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: item.icon, size: "sm", className: cn("min-w-[20px] flex-shrink-0", isActive && "text-primary-foreground") }) : /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { icon: item.icon, size: "sm", className: cn("min-w-[20px] flex-shrink-0", isActive && "text-primary-foreground") })),
35452
- !collapsed && /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "body", color: isActive ? "inherit" : "primary", className: "font-medium truncate flex-1 text-left", children: item.label }),
35524
+ !collapsed && /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "body", color: isActive ? "inherit" : "primary", className: "font-medium truncate flex-1 text-start", children: item.label }),
35453
35525
  !collapsed && item.badge !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.Badge, { variant: "danger", size: "sm", children: item.badge }),
35454
35526
  collapsed && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: cn(
35455
- "absolute left-full ml-2 px-2 py-1 text-xs opacity-0 group-hover:opacity-100",
35527
+ "absolute start-full ms-2 px-2 py-1 text-xs opacity-0 group-hover:opacity-100",
35456
35528
  "pointer-events-none whitespace-nowrap z-50 transition-opacity",
35457
35529
  "bg-primary text-primary-foreground",
35458
35530
  "border-[length:var(--border-width-thin)] border-border",
@@ -35507,7 +35579,7 @@ var init_Sidebar = __esm({
35507
35579
  as: "aside",
35508
35580
  className: cn(
35509
35581
  "flex flex-col h-full",
35510
- "bg-card border-r border-border",
35582
+ "bg-card border-e border-border",
35511
35583
  "transition-all duration-300 ease-in-out",
35512
35584
  collapsed ? "w-20" : "w-64",
35513
35585
  className
@@ -36668,7 +36740,7 @@ function resolveColor3(color, el) {
36668
36740
  function truncateLabel(label) {
36669
36741
  return label.length > MAX_LABEL_CHARS ? label.slice(0, MAX_LABEL_CHARS - 1) + "\u2026" : label;
36670
36742
  }
36671
- var GROUP_COLORS2, GROUP_GRAVITY, UNGROUPED_GRAVITY, labelMeasureCtx, MAX_LABEL_CHARS; exports.GraphCanvas = void 0;
36743
+ var GROUP_COLORS2, GROUP_GRAVITY, UNGROUPED_GRAVITY, labelMeasureCtx, MAX_LABEL_CHARS, NO_NODES, NO_EDGES, NO_SIM; exports.GraphCanvas = void 0;
36672
36744
  var init_GraphCanvas = __esm({
36673
36745
  "components/core/molecules/GraphCanvas.tsx"() {
36674
36746
  "use client";
@@ -36692,11 +36764,14 @@ var init_GraphCanvas = __esm({
36692
36764
  UNGROUPED_GRAVITY = 0.02;
36693
36765
  labelMeasureCtx = null;
36694
36766
  MAX_LABEL_CHARS = 22;
36767
+ NO_NODES = [];
36768
+ NO_EDGES = [];
36769
+ NO_SIM = [];
36695
36770
  exports.GraphCanvas = ({
36696
36771
  title,
36697
- nodes: propNodes = [],
36698
- edges: propEdges = [],
36699
- similarity: propSimilarity = [],
36772
+ nodes: propNodes = NO_NODES,
36773
+ edges: propEdges = NO_EDGES,
36774
+ similarity: propSimilarity = NO_SIM,
36700
36775
  height = 400,
36701
36776
  showLabels = true,
36702
36777
  interactive = true,
@@ -36746,6 +36821,7 @@ var init_GraphCanvas = __esm({
36746
36821
  const interactionRef = React73.useRef({
36747
36822
  mode: "none",
36748
36823
  dragNodeId: null,
36824
+ pressedNodeId: null,
36749
36825
  startMouse: { x: 0, y: 0 },
36750
36826
  startOffset: { x: 0, y: 0 },
36751
36827
  downPos: { x: 0, y: 0 }
@@ -36793,6 +36869,11 @@ var init_GraphCanvas = __esm({
36793
36869
  () => [...new Set(propNodes.map((n) => n.group).filter(Boolean))],
36794
36870
  [propNodes]
36795
36871
  );
36872
+ const nodesKey = React73.useMemo(() => propNodes.map((n) => n.id).join(""), [propNodes]);
36873
+ const edgesKey = React73.useMemo(
36874
+ () => propEdges.map((e) => `${e.source}${e.target}`).join(""),
36875
+ [propEdges]
36876
+ );
36796
36877
  React73.useEffect(() => {
36797
36878
  const canvas = canvasRef.current;
36798
36879
  if (!canvas || propNodes.length === 0) return;
@@ -36973,7 +37054,7 @@ var init_GraphCanvas = __esm({
36973
37054
  return () => {
36974
37055
  cancelAnimationFrame(animRef.current);
36975
37056
  };
36976
- }, [propNodes, propEdges, propSimilarity, layout, repulsion, linkDistance, nodeSpacing, showLabels]);
37057
+ }, [nodesKey, edgesKey, propSimilarity, layout, repulsion, linkDistance, nodeSpacing, showLabels]);
36977
37058
  React73.useEffect(() => {
36978
37059
  const canvas = canvasRef.current;
36979
37060
  if (!canvas) return;
@@ -37103,6 +37184,7 @@ var init_GraphCanvas = __esm({
37103
37184
  const cancelSinglePointer = React73.useCallback(() => {
37104
37185
  interactionRef.current.mode = "none";
37105
37186
  interactionRef.current.dragNodeId = null;
37187
+ interactionRef.current.pressedNodeId = null;
37106
37188
  }, []);
37107
37189
  const handlePointerDown = React73.useCallback(
37108
37190
  (e) => {
@@ -37113,6 +37195,7 @@ var init_GraphCanvas = __esm({
37113
37195
  state.downPos = { x: e.clientX, y: e.clientY };
37114
37196
  state.startMouse = { x: e.clientX, y: e.clientY };
37115
37197
  state.startOffset = { ...offset };
37198
+ state.pressedNodeId = node?.id ?? null;
37116
37199
  if (draggable && node) {
37117
37200
  state.mode = "dragging";
37118
37201
  state.dragNodeId = node.id;
@@ -37164,7 +37247,8 @@ var init_GraphCanvas = __esm({
37164
37247
  if (moved < 4) {
37165
37248
  const coords = toCoords(e);
37166
37249
  if (!coords) return;
37167
- const node = nodeAt(coords.graphX, coords.graphY);
37250
+ const node = (state.pressedNodeId ? nodesRef.current.find((n) => n.id === state.pressedNodeId) : void 0) ?? nodeAt(coords.graphX, coords.graphY);
37251
+ state.pressedNodeId = null;
37168
37252
  if (node) {
37169
37253
  if (node.badge && node.badge > 1 && onBadgeClick) {
37170
37254
  const r = (node.size || 8) + (selectedNodeId === node.id ? 4 : 0);
@@ -37184,6 +37268,7 @@ var init_GraphCanvas = __esm({
37184
37268
  );
37185
37269
  const handlePointerLeave = React73.useCallback(() => {
37186
37270
  setHoveredNode(null);
37271
+ interactionRef.current.pressedNodeId = null;
37187
37272
  }, []);
37188
37273
  const gestureHandlers = useCanvasGestures({
37189
37274
  canvasRef,
@@ -40352,8 +40437,17 @@ var init_MediaGallery = __esm({
40352
40437
  const eventBus = useEventBus();
40353
40438
  const { t } = hooks.useTranslate();
40354
40439
  const [lightboxItem, setLightboxItem] = React73.useState(null);
40440
+ const [failedIds, setFailedIds] = React73.useState(/* @__PURE__ */ new Set());
40355
40441
  const closeLightbox = React73.useCallback(() => setLightboxItem(null), []);
40356
40442
  useEventListener("UI:LIGHTBOX_CLOSE", closeLightbox);
40443
+ const handleImageError = React73.useCallback((id) => {
40444
+ setFailedIds((prev) => {
40445
+ if (prev.has(id)) return prev;
40446
+ const next = new Set(prev);
40447
+ next.add(id);
40448
+ return next;
40449
+ });
40450
+ }, []);
40357
40451
  const handleItemClick = React73.useCallback(
40358
40452
  (item) => {
40359
40453
  if (selectable) {
@@ -40369,7 +40463,7 @@ var init_MediaGallery = __esm({
40369
40463
  );
40370
40464
  const entityData = Array.isArray(entity) ? entity : [];
40371
40465
  const items = React73__namespace.default.useMemo(() => {
40372
- if (propItems) return propItems;
40466
+ if (propItems && propItems.length > 0) return propItems;
40373
40467
  if (entityData.length === 0) return [];
40374
40468
  return entityData.map((record, idx) => {
40375
40469
  return {
@@ -40452,13 +40546,14 @@ var init_MediaGallery = __esm({
40452
40546
  ),
40453
40547
  onClick: () => handleItemClick(item),
40454
40548
  children: [
40455
- /* @__PURE__ */ jsxRuntime.jsx(
40549
+ failedIds.has(item.id) ? /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "w-full h-full flex items-center justify-center bg-muted text-muted-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { icon: LucideIcons2.Image, size: "lg" }) }) : /* @__PURE__ */ jsxRuntime.jsx(
40456
40550
  "img",
40457
40551
  {
40458
40552
  src: item.thumbnail || item.src,
40459
40553
  alt: item.alt || item.caption || "",
40460
40554
  className: "w-full h-full object-cover",
40461
- loading: "lazy"
40555
+ loading: "lazy",
40556
+ onError: () => handleImageError(item.id)
40462
40557
  }
40463
40558
  ),
40464
40559
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -43946,6 +44041,11 @@ var init_TeamOrganism = __esm({
43946
44041
  exports.TeamOrganism.displayName = "TeamOrganism";
43947
44042
  }
43948
44043
  });
44044
+ function formatDate4(value) {
44045
+ const d = new Date(value);
44046
+ if (isNaN(d.getTime())) return value;
44047
+ return d.toLocaleDateString(void 0, { year: "numeric", month: "short", day: "numeric" });
44048
+ }
43949
44049
  var lookStyles10, STATUS_STYLES2; exports.Timeline = void 0;
43950
44050
  var init_Timeline = __esm({
43951
44051
  "components/core/organisms/Timeline.tsx"() {
@@ -44073,7 +44173,7 @@ var init_Timeline = __esm({
44073
44173
  /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "xs", className: cn("flex-1 min-w-0", !isLast && "pb-6"), children: [
44074
44174
  /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { justify: "between", align: "start", wrap: true, children: [
44075
44175
  /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "body", weight: "semibold", children: item.title }),
44076
- item.date && /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "secondary", className: "flex-shrink-0", children: item.date })
44176
+ item.date && /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "secondary", className: "flex-shrink-0", children: formatDate4(item.date) })
44077
44177
  ] }),
44078
44178
  item.description && /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", color: "secondary", children: item.description }),
44079
44179
  item.tags && item.tags.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { gap: "xs", wrap: true, children: item.tags.map((tag, tagIdx) => /* @__PURE__ */ jsxRuntime.jsx(exports.Badge, { variant: "default", children: tag }, tagIdx)) }),
@@ -45285,7 +45385,7 @@ function substituteTraitRefsDeep(value, pathKey) {
45285
45385
  }
45286
45386
  return value;
45287
45387
  }
45288
- function renderPatternProps(props, onDismiss) {
45388
+ function renderPatternProps(props, onDismiss, propsSchema) {
45289
45389
  const rendered = {};
45290
45390
  for (const [key, value] of Object.entries(props)) {
45291
45391
  if (key === "children") {
@@ -45303,9 +45403,10 @@ function renderPatternProps(props, onDismiss) {
45303
45403
  };
45304
45404
  rendered[key] = /* @__PURE__ */ jsxRuntime.jsx(SlotContentRenderer, { content: childContent, onDismiss });
45305
45405
  } else if (Array.isArray(value)) {
45406
+ const isDataArray = propsSchema?.[key]?.items?.types?.includes("object") ?? false;
45306
45407
  rendered[key] = value.map((item, i) => {
45307
45408
  const el = item;
45308
- if (isPatternConfig(el)) {
45409
+ if (!isDataArray && isPatternConfig(el)) {
45309
45410
  const nestedProps = {};
45310
45411
  for (const [k, v] of Object.entries(el)) {
45311
45412
  if (k !== "type") nestedProps[k] = v;
@@ -45393,14 +45494,15 @@ function SlotContentRenderer({
45393
45494
  );
45394
45495
  }
45395
45496
  }
45396
- const renderedProps = renderPatternProps(restProps, onDismiss);
45397
45497
  const patternDef = patterns.getPatternDefinition(content.pattern);
45398
45498
  const propsSchema = patternDef?.propsSchema;
45499
+ const renderedProps = renderPatternProps(restProps, onDismiss, propsSchema);
45399
45500
  if (propsSchema) {
45400
45501
  for (const [propKey, propValue] of Object.entries(renderedProps)) {
45401
45502
  if (typeof propValue !== "string") continue;
45402
45503
  const propDef = propsSchema[propKey];
45403
45504
  if (!propDef || propDef.kind !== "callback") continue;
45505
+ if (propValue === "") continue;
45404
45506
  renderedProps[propKey] = ui.wrapCallbackForEvent(
45405
45507
  `UI:${propValue}`,
45406
45508
  propDef.callbackArgs,
@@ -47189,6 +47291,16 @@ function useSharedEntityStore() {
47189
47291
  }
47190
47292
  return storeRef.current;
47191
47293
  }
47294
+ var SharedEntityStoreContext = React73.createContext(null);
47295
+ function useSharedEntityStoreContext() {
47296
+ const store = React73.useContext(SharedEntityStoreContext);
47297
+ if (!store) {
47298
+ throw new Error(
47299
+ "useSharedEntityStoreContext: no SharedEntityStoreContext.Provider found in the component tree"
47300
+ );
47301
+ }
47302
+ return store;
47303
+ }
47192
47304
  function useSharedEntitySnapshot(store, entityId) {
47193
47305
  return React73.useSyncExternalStore(
47194
47306
  (onStoreChange) => store.subscribe(entityId, onStoreChange),
@@ -48121,6 +48233,7 @@ exports.OrbitalStateMachineView = exports.StateMachineView;
48121
48233
  exports.RuntimeDebugger = RuntimeDebugger;
48122
48234
  exports.ScoreDisplay = ScoreDisplay;
48123
48235
  exports.SequenceBar = SequenceBar;
48236
+ exports.SharedEntityStoreContext = SharedEntityStoreContext;
48124
48237
  exports.Skeleton = Skeleton;
48125
48238
  exports.SlotContentRenderer = SlotContentRenderer;
48126
48239
  exports.StatBadge = StatBadge;
@@ -48215,6 +48328,7 @@ exports.useQuerySingleton = useQuerySingleton;
48215
48328
  exports.useRenderInterpolation = useRenderInterpolation;
48216
48329
  exports.useSharedEntitySnapshot = useSharedEntitySnapshot;
48217
48330
  exports.useSharedEntityStore = useSharedEntityStore;
48331
+ exports.useSharedEntityStoreContext = useSharedEntityStoreContext;
48218
48332
  exports.useSwipeGesture = useSwipeGesture;
48219
48333
  exports.useTapReveal = useTapReveal;
48220
48334
  exports.useTraitListens = useTraitListens;