@almadar/ui 5.155.0 → 5.157.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.
@@ -1,6 +1,6 @@
1
1
  import * as React87 from 'react';
2
2
  import React87__default, { createContext, useContext, useMemo, useRef, useEffect, useCallback, Suspense, useState, useSyncExternalStore, useLayoutEffect, lazy, useId } from 'react';
3
- import { EventBusContext, useTraitScopeChain, useEntitySchemaOptional, useEntityBindingSnapshot, useTraitScope, TraitScopeProvider, useNavStack, useCurrentPagePath, useGameAudioContextOptional, matchPathAmong } from '@almadar/ui/providers';
3
+ import { EventBusContext, useTraitScopeChain, RenderSlotProvider, useEntitySchemaOptional, useEntityBindingSnapshot, useTraitScope, TraitScopeProvider, useNavStack, useCurrentPagePath, useRenderSlot, useGameAudioContextOptional, matchPathAmong } from '@almadar/ui/providers';
4
4
  import { createLogger, isLogLevelEnabled } from '@almadar/logger';
5
5
  import { createContextFromBindings, interpolateValue } from '@almadar/runtime';
6
6
  import { ANONYMOUS_USER, isRenderBindingMarker, isFileValue, isInlineTrait, ANIMATION_NAMES } from '@almadar/core';
@@ -8,7 +8,7 @@ export { ANONYMOUS_USER } from '@almadar/core';
8
8
  import { clsx } from 'clsx';
9
9
  import { twMerge } from 'tailwind-merge';
10
10
  import * as LucideIcons2 from 'lucide-react';
11
- import { Loader2, X, Lightbulb, CheckCircle, List, Printer, ChevronRight, ChevronLeft, GitBranch, Pencil, Eye, Plus, ArrowRight, Trash, Code, FileText, WrapText, Check, Copy, RotateCcw, Play, Terminal, XCircle, AlertTriangle, Trash2, Link2, ArrowLeft, ZoomOut, ZoomIn, Download, DollarSign, ChevronDown, Menu as Menu$1, Package, Calendar, MoreHorizontal, Image as Image$1, Upload, HelpCircle, PauseCircle, Search, Type, Heading1, Heading2, Heading3, ListOrdered, Quote, Minus, Eraser, TrendingUp, TrendingDown, AlertCircle, Circle, Clock, CheckCircle2, ChevronUp, Tag, User } from 'lucide-react';
11
+ import { Loader2, X, Lightbulb, CheckCircle, List, Printer, ChevronRight, ChevronLeft, GitBranch, Pencil, Eye, Plus, ArrowRight, Trash, Code, FileText, WrapText, Check, Copy, RotateCcw, Play, Terminal, XCircle, AlertTriangle, Trash2, Link2, ArrowLeft, ZoomOut, ZoomIn, Download, DollarSign, ChevronDown, Menu as Menu$1, Package, Calendar, MoreHorizontal, Image as Image$1, Upload, HelpCircle, PauseCircle, Search, Type, Heading1, Heading2, Heading3, ListOrdered, Quote, Minus, Eraser, TrendingUp, TrendingDown, AlertCircle, Circle, Clock, CheckCircle2, ChevronUp } from 'lucide-react';
12
12
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
13
13
  import { createPortal } from 'react-dom';
14
14
  import { useTranslate } from '@almadar/ui/hooks';
@@ -7793,10 +7793,21 @@ function ControlGrid({
7793
7793
  directionAssets,
7794
7794
  size = "md",
7795
7795
  disabled,
7796
+ visibility = "auto",
7796
7797
  className
7797
7798
  }) {
7798
7799
  const eventBus = useEventBus();
7799
7800
  const [active, setActive] = React87.useState(/* @__PURE__ */ new Set());
7801
+ const [coarse, setCoarse] = React87.useState(
7802
+ () => typeof window !== "undefined" && window.matchMedia("(pointer: coarse)").matches
7803
+ );
7804
+ React87.useEffect(() => {
7805
+ if (visibility !== "auto" || typeof window === "undefined") return;
7806
+ const mq = window.matchMedia("(pointer: coarse)");
7807
+ const onChange = (e) => setCoarse(e.matches);
7808
+ mq.addEventListener("change", onChange);
7809
+ return () => mq.removeEventListener("change", onChange);
7810
+ }, [visibility]);
7800
7811
  const handlePress = React87.useCallback(
7801
7812
  (id) => {
7802
7813
  setActive((prev) => new Set(prev).add(id));
@@ -7829,6 +7840,7 @@ function ControlGrid({
7829
7840
  },
7830
7841
  [kind, actionEvent, directionEvent, directionReleaseEvents, eventBus, onAction, onDirection]
7831
7842
  );
7843
+ if (visibility === "auto" && !coarse) return null;
7832
7844
  if (kind === "dpad") {
7833
7845
  const ds = dpadSizeMap[size];
7834
7846
  const dir = (d) => /* @__PURE__ */ jsx(
@@ -7978,7 +7990,7 @@ function StatBadge({
7978
7990
  assetUrl,
7979
7991
  iconUrl,
7980
7992
  label,
7981
- value = 0,
7993
+ value,
7982
7994
  max,
7983
7995
  format = "number",
7984
7996
  icon,
@@ -7989,6 +8001,7 @@ function StatBadge({
7989
8001
  source: _source,
7990
8002
  field: _field
7991
8003
  }) {
8004
+ const hasValue = value !== void 0 && value !== null;
7992
8005
  const numValue = typeof value === "number" ? value : parseInt(String(value), 10) || 0;
7993
8006
  const resolvedAsset = iconUrl ?? assetUrl;
7994
8007
  return /* @__PURE__ */ jsxs(
@@ -8002,8 +8015,8 @@ function StatBadge({
8002
8015
  ),
8003
8016
  children: [
8004
8017
  resolvedAsset ? /* @__PURE__ */ jsx(GameIcon, { assetUrl: resolvedAsset, icon: "image", size: 16, className: "flex-shrink-0" }) : icon ? /* @__PURE__ */ jsx(Box, { as: "span", className: "flex-shrink-0 text-lg", children: typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, className: "w-4 h-4" }) : /* @__PURE__ */ jsx(Icon, { icon, className: "w-4 h-4" }) }) : null,
8005
- /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-muted-foreground font-medium", children: label }),
8006
- format === "hearts" && max && /* @__PURE__ */ jsx(
8018
+ /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-muted-foreground font-medium text-xs", children: label }),
8019
+ hasValue && format === "hearts" && max && /* @__PURE__ */ jsx(
8007
8020
  HealthBar,
8008
8021
  {
8009
8022
  current: numValue,
@@ -8012,7 +8025,7 @@ function StatBadge({
8012
8025
  size: size === "lg" ? "md" : "sm"
8013
8026
  }
8014
8027
  ),
8015
- format === "bar" && max && /* @__PURE__ */ jsx(
8028
+ hasValue && format === "bar" && max && /* @__PURE__ */ jsx(
8016
8029
  HealthBar,
8017
8030
  {
8018
8031
  current: numValue,
@@ -8021,14 +8034,15 @@ function StatBadge({
8021
8034
  size: size === "lg" ? "md" : "sm"
8022
8035
  }
8023
8036
  ),
8024
- format === "number" && /* @__PURE__ */ jsx(
8037
+ hasValue && format === "number" && /* @__PURE__ */ jsx(
8025
8038
  ScoreDisplay,
8026
8039
  {
8027
8040
  value: numValue,
8028
- size: size === "lg" ? "md" : "sm"
8041
+ size: size === "lg" ? "md" : "sm",
8042
+ className: "font-display"
8029
8043
  }
8030
8044
  ),
8031
- format === "text" && /* @__PURE__ */ jsx(Typography, { as: "span", className: "font-bold text-foreground", children: value })
8045
+ hasValue && format === "text" && /* @__PURE__ */ jsx(Typography, { as: "span", className: "font-bold text-foreground", children: value })
8032
8046
  ]
8033
8047
  }
8034
8048
  );
@@ -8044,6 +8058,7 @@ var init_StatBadge = __esm({
8044
8058
  init_HealthBar();
8045
8059
  init_ScoreDisplay();
8046
8060
  sizeMap6 = {
8061
+ xs: "text-xs px-1.5 py-0.5",
8047
8062
  sm: "text-xs px-2 py-1",
8048
8063
  md: "text-sm px-3 py-1.5",
8049
8064
  lg: "text-base px-4 py-2"
@@ -8086,6 +8101,7 @@ function GameHud({
8086
8101
  items,
8087
8102
  elements,
8088
8103
  size = "md",
8104
+ variant = "floating",
8089
8105
  className,
8090
8106
  transparent = true
8091
8107
  }) {
@@ -8100,7 +8116,7 @@ function GameHud({
8100
8116
  /* @__PURE__ */ jsx(Box, { position: "absolute", className: "top-4 right-4 flex flex-col gap-2 items-end pointer-events-auto", children: rightStats.map((stat, i) => /* @__PURE__ */ jsx(StatBadge, { ...stat, size }, i)) })
8101
8117
  ] });
8102
8118
  }
8103
- if (position === "top" || position === "bottom") {
8119
+ if ((position === "top" || position === "bottom") && variant === "bar") {
8104
8120
  const mid = Math.ceil(stats.length / 2);
8105
8121
  const leftStats = stats.slice(0, mid);
8106
8122
  const rightStats = stats.slice(mid);
@@ -11588,7 +11604,7 @@ var init_StateJsonView = __esm({
11588
11604
  StateJsonView.displayName = "StateJsonView";
11589
11605
  }
11590
11606
  });
11591
- var FONT_BASE, GAME_FONTS, FONT_FACES, GameShell;
11607
+ var GAME_FONTS, GameShell;
11592
11608
  var init_GameShell = __esm({
11593
11609
  "components/game/templates/GameShell.tsx"() {
11594
11610
  init_cn();
@@ -11596,7 +11612,6 @@ var init_GameShell = __esm({
11596
11612
  init_Card();
11597
11613
  init_Typography();
11598
11614
  init_AtlasImage();
11599
- FONT_BASE = "https://almadar-kflow-assets.web.app/shared/_shared/kenney-fonts/fonts";
11600
11615
  GAME_FONTS = {
11601
11616
  future: "Kenney Future",
11602
11617
  "future-narrow": "Kenney Future Narrow",
@@ -11604,14 +11619,6 @@ var init_GameShell = __esm({
11604
11619
  blocks: "Kenney Blocks",
11605
11620
  mini: "Kenney Mini"
11606
11621
  };
11607
- FONT_FACES = `
11608
- @font-face { font-family: 'Kenney Future'; src: url('${FONT_BASE}/Kenney%20Future.ttf') format('truetype'); font-display: swap; }
11609
- @font-face { font-family: 'Kenney Future Narrow'; src: url('${FONT_BASE}/Kenney%20Future%20Narrow.ttf') format('truetype'); font-display: swap; }
11610
- @font-face { font-family: 'Kenney Pixel'; src: url('${FONT_BASE}/Kenney%20Pixel.ttf') format('truetype'); font-display: swap; }
11611
- @font-face { font-family: 'Kenney Blocks'; src: url('${FONT_BASE}/Kenney%20Blocks.ttf') format('truetype'); font-display: swap; }
11612
- @font-face { font-family: 'Kenney Mini'; src: url('${FONT_BASE}/Kenney%20Mini.ttf') format('truetype'); font-display: swap; }
11613
- .game-shell, .game-shell * { font-family: inherit; }
11614
- `;
11615
11622
  GameShell = ({
11616
11623
  appName = "Game",
11617
11624
  hud,
@@ -11638,10 +11645,12 @@ var init_GameShell = __esm({
11638
11645
  overflow: "hidden",
11639
11646
  background: "var(--color-background, #0a0a0f)",
11640
11647
  color: "var(--color-foreground, #e0e0e0)",
11641
- fontFamily: `'${font}', system-ui, sans-serif`
11648
+ // The fontFamily knob is a scoped override of the theme contract's
11649
+ // display slot: titles/numerics take the game face, body text keeps
11650
+ // the active theme's --font-family-body.
11651
+ "--font-family-display": `'${font}', ui-sans-serif, system-ui, sans-serif`
11642
11652
  },
11643
11653
  children: [
11644
- /* @__PURE__ */ jsx("style", { children: FONT_FACES }),
11645
11654
  backgroundAsset && /* @__PURE__ */ jsx(
11646
11655
  AtlasPanel,
11647
11656
  {
@@ -11679,6 +11688,7 @@ var init_GameShell = __esm({
11679
11688
  Typography,
11680
11689
  {
11681
11690
  as: "span",
11691
+ className: "font-display",
11682
11692
  style: {
11683
11693
  fontWeight: 700,
11684
11694
  fontSize: "1.05rem",
@@ -11759,6 +11769,11 @@ var init_molecules = __esm({
11759
11769
  init_puzzleObject();
11760
11770
  }
11761
11771
  });
11772
+ function themeBodyFont(el) {
11773
+ if (typeof getComputedStyle !== "function") return "system-ui, sans-serif";
11774
+ const v = getComputedStyle(el).getPropertyValue("--font-family-body").trim();
11775
+ return v || "system-ui, sans-serif";
11776
+ }
11762
11777
  function resolveColor2(color, ctx, fallback) {
11763
11778
  if (!color) return fallback;
11764
11779
  if (color.startsWith("var(")) {
@@ -11947,6 +11962,8 @@ function drawShape(ctx, shape, width, height, allShapes) {
11947
11962
  case "path": {
11948
11963
  if (!shape.path) break;
11949
11964
  const p = new Path2D(shape.path);
11965
+ ctx.lineJoin = "round";
11966
+ ctx.lineCap = "round";
11950
11967
  if (fill) {
11951
11968
  ctx.fillStyle = fill;
11952
11969
  ctx.fill(p);
@@ -11958,7 +11975,7 @@ function drawShape(ctx, shape, width, height, allShapes) {
11958
11975
  case "text": {
11959
11976
  if (shape.x == null || shape.y == null || !shape.text) break;
11960
11977
  ctx.fillStyle = stroke;
11961
- ctx.font = `${shape.fontSize ?? 14}px system-ui, sans-serif`;
11978
+ ctx.font = `${shape.fontSize ?? 14}px ${themeBodyFont(ctx.canvas)}`;
11962
11979
  ctx.textAlign = shape.align ?? "left";
11963
11980
  ctx.textBaseline = "middle";
11964
11981
  ctx.fillText(shape.text, shape.x, shape.y);
@@ -12155,7 +12172,7 @@ var init_LearningCanvas = __esm({
12155
12172
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
12156
12173
  ctx.clearRect(0, 0, width, height);
12157
12174
  if (backgroundColor) {
12158
- ctx.fillStyle = backgroundColor;
12175
+ ctx.fillStyle = resolveColor2(backgroundColor, ctx, backgroundColor);
12159
12176
  ctx.fillRect(0, 0, width, height);
12160
12177
  }
12161
12178
  for (const shape of derivedShapes) {
@@ -21692,7 +21709,22 @@ function eventStartDate(event, startField) {
21692
21709
  const raw = getNestedValue(event, startField);
21693
21710
  return new Date(raw ?? "");
21694
21711
  }
21695
- function generateDefaultTimeSlots(events2, startField) {
21712
+ function eventEndDate(event, endField) {
21713
+ const raw = getNestedValue(event, endField);
21714
+ if (raw === void 0 || raw === null || raw === "") return null;
21715
+ const end = new Date(raw);
21716
+ return Number.isNaN(end.getTime()) ? null : end;
21717
+ }
21718
+ function eventContinuesInSlot(event, day, slotTime, startField, endField) {
21719
+ const eventStart = eventStartDate(event, startField);
21720
+ const eventEnd = eventEndDate(event, endField);
21721
+ if (eventEnd === null || Number.isNaN(eventStart.getTime())) return false;
21722
+ const [slotHour] = slotTime.split(":").map(Number);
21723
+ const slotStart = new Date(day);
21724
+ slotStart.setHours(slotHour, 0, 0, 0);
21725
+ return slotStart.getTime() > eventStart.getTime() && slotStart.getTime() < eventEnd.getTime();
21726
+ }
21727
+ function generateDefaultTimeSlots(events2, startField, endField) {
21696
21728
  let first = DEFAULT_FIRST_HOUR;
21697
21729
  let last = DEFAULT_LAST_HOUR;
21698
21730
  for (const ev of events2) {
@@ -21701,6 +21733,11 @@ function generateDefaultTimeSlots(events2, startField) {
21701
21733
  const hour = start.getHours();
21702
21734
  if (hour < first) first = hour;
21703
21735
  if (hour > last) last = hour;
21736
+ const end = eventEndDate(ev, endField);
21737
+ if (end && end.toDateString() === start.toDateString()) {
21738
+ const endHour = end.getMinutes() === 0 && end.getSeconds() === 0 ? end.getHours() - 1 : end.getHours();
21739
+ if (endHour > last) last = endHour;
21740
+ }
21704
21741
  }
21705
21742
  const slots = [];
21706
21743
  for (let hour = first; hour <= last; hour++) {
@@ -21729,6 +21766,7 @@ function CalendarGrid({
21729
21766
  dayWindow = "auto",
21730
21767
  titleField = "title",
21731
21768
  startField = "startTime",
21769
+ endField = "endTime",
21732
21770
  colorField = "color",
21733
21771
  children,
21734
21772
  renderItem
@@ -21746,8 +21784,8 @@ function CalendarGrid({
21746
21784
  [resolvedWeekStart]
21747
21785
  );
21748
21786
  const resolvedTimeSlots = useMemo(
21749
- () => timeSlots ?? generateDefaultTimeSlots(evs, startField),
21750
- [timeSlots, evs, startField]
21787
+ () => timeSlots ?? generateDefaultTimeSlots(evs, startField, endField),
21788
+ [timeSlots, evs, startField, endField]
21751
21789
  );
21752
21790
  const visibleCount = useDayWindow(dayWindow);
21753
21791
  const [dayOffset, setDayOffset] = useState(0);
@@ -21907,12 +21945,15 @@ function CalendarGrid({
21907
21945
  const slotEvents = evs.filter(
21908
21946
  (ev) => eventInSlot(ev, day, time, startField)
21909
21947
  );
21948
+ const continuingEvents = evs.filter(
21949
+ (ev) => eventContinuesInSlot(ev, day, time, startField, endField)
21950
+ );
21910
21951
  const isToday = day.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
21911
21952
  return /* @__PURE__ */ jsx(
21912
21953
  TimeSlotCell,
21913
21954
  {
21914
21955
  time,
21915
- isOccupied: slotEvents.length > 0,
21956
+ isOccupied: slotEvents.length > 0 || continuingEvents.length > 0,
21916
21957
  onClick: () => handleSlotClick(day, time),
21917
21958
  className: cn(
21918
21959
  "border-l border-border",
@@ -21923,7 +21964,25 @@ function CalendarGrid({
21923
21964
  onPointerUp: clearLongPress,
21924
21965
  onPointerCancel: clearLongPress
21925
21966
  } : {},
21926
- children: /* @__PURE__ */ jsx(VStack, { gap: "xs", children: slotEvents.map(renderEvent) })
21967
+ children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
21968
+ slotEvents.map(renderEvent),
21969
+ continuingEvents.map((event) => {
21970
+ const color = getNestedValue(event, colorField);
21971
+ return /* @__PURE__ */ jsx(
21972
+ Box,
21973
+ {
21974
+ rounded: "sm",
21975
+ border: true,
21976
+ className: cn(
21977
+ "cursor-pointer h-2",
21978
+ color ? cn(color, "opacity-50") : "bg-primary/10 border-primary/20"
21979
+ ),
21980
+ onClick: (e) => handleEventClick(event, e)
21981
+ },
21982
+ `${event.id}-cont`
21983
+ );
21984
+ })
21985
+ ] })
21927
21986
  },
21928
21987
  `${day.toISOString()}-${time}`
21929
21988
  );
@@ -30449,6 +30508,9 @@ var init_MathCanvas = __esm({
30449
30508
  showAxes = true,
30450
30509
  showGrid = true,
30451
30510
  gridStep = 1,
30511
+ backgroundColor,
30512
+ gridColor = "var(--color-border, #9ca3af)",
30513
+ axisColor = "var(--color-muted-foreground, #374151)",
30452
30514
  showTickLabels = false,
30453
30515
  showCurveLabels = false,
30454
30516
  curves = [],
@@ -30503,11 +30565,11 @@ var init_MathCanvas = __esm({
30503
30565
  if (showGrid) {
30504
30566
  for (let x = Math.ceil(xMin / gridStep) * gridStep; x <= xMax; x += gridStep) {
30505
30567
  const px = mapX(x);
30506
- out.push({ type: "line", x1: px, y1: margin, x2: px, y2: height - margin, color: "#9ca3af", opacity: 0.35, lineWidth: 1 });
30568
+ out.push({ type: "line", x1: px, y1: margin, x2: px, y2: height - margin, color: gridColor, opacity: 0.35, lineWidth: 1 });
30507
30569
  }
30508
30570
  for (let y = Math.ceil(yMin / gridStep) * gridStep; y <= yMax; y += gridStep) {
30509
30571
  const py = mapY(y);
30510
- out.push({ type: "line", x1: margin, y1: py, x2: width - margin, y2: py, color: "#9ca3af", opacity: 0.35, lineWidth: 1 });
30572
+ out.push({ type: "line", x1: margin, y1: py, x2: width - margin, y2: py, color: gridColor, opacity: 0.35, lineWidth: 1 });
30511
30573
  }
30512
30574
  }
30513
30575
  if (showTickLabels) {
@@ -30578,8 +30640,8 @@ var init_MathCanvas = __esm({
30578
30640
  });
30579
30641
  }
30580
30642
  if (showAxes) {
30581
- out.push({ type: "line", x1: margin, y1: xAxisY, x2: width - margin, y2: xAxisY, color: "#374151", lineWidth: 2 });
30582
- out.push({ type: "line", x1: yAxisX, y1: margin, x2: yAxisX, y2: height - margin, color: "#374151", lineWidth: 2 });
30643
+ out.push({ type: "line", x1: margin, y1: xAxisY, x2: width - margin, y2: xAxisY, color: axisColor, lineWidth: 2 });
30644
+ out.push({ type: "line", x1: yAxisX, y1: margin, x2: yAxisX, y2: height - margin, color: axisColor, lineWidth: 2 });
30583
30645
  }
30584
30646
  for (const guide of guides) {
30585
30647
  const color = guide.color ?? "#9ca3af";
@@ -30602,23 +30664,36 @@ var init_MathCanvas = __esm({
30602
30664
  }
30603
30665
  for (const curve of curves) {
30604
30666
  if (!curve.samples || curve.samples.length < 2) continue;
30667
+ let d = "";
30668
+ let penDown = false;
30605
30669
  let lastInRange;
30606
30670
  for (let i = 1; i < curve.samples.length; i++) {
30607
30671
  const a = curve.samples[i - 1];
30608
30672
  const b = curve.samples[i];
30609
- if (a.x < xMin || a.x > xMax || b.x < xMin || b.x > xMax) continue;
30610
- out.push({
30611
- type: "line",
30612
- x1: mapX(a.x),
30613
- y1: mapY(a.y),
30614
- x2: mapX(b.x),
30615
- y2: mapY(b.y),
30616
- color: curve.color ?? "#2563eb",
30617
- lineWidth: 2,
30618
- dash: curve.dash
30619
- });
30620
- lastInRange = b;
30621
- }
30673
+ if (a.x < xMin && b.x < xMin || a.x > xMax && b.x > xMax) {
30674
+ penDown = false;
30675
+ continue;
30676
+ }
30677
+ const clip = (p, q, xLim) => {
30678
+ const t = q.x === p.x ? 0 : (xLim - p.x) / (q.x - p.x);
30679
+ return { x: xLim, y: p.y + t * (q.y - p.y) };
30680
+ };
30681
+ const ca = a.x < xMin ? clip(a, b, xMin) : a.x > xMax ? clip(a, b, xMax) : a;
30682
+ const cb = b.x < xMin ? clip(a, b, xMin) : b.x > xMax ? clip(a, b, xMax) : b;
30683
+ const pax = mapX(ca.x);
30684
+ const pay = mapY(ca.y);
30685
+ d += `${penDown ? "L" : "M"} ${pax} ${pay} L ${mapX(cb.x)} ${mapY(cb.y)} `;
30686
+ penDown = true;
30687
+ if (b.x >= xMin && b.x <= xMax) lastInRange = b;
30688
+ }
30689
+ if (!d) continue;
30690
+ out.push({
30691
+ type: "path",
30692
+ path: d,
30693
+ color: curve.color ?? "#2563eb",
30694
+ lineWidth: 2,
30695
+ dash: curve.dash
30696
+ });
30622
30697
  if (showCurveLabels && curve.label && lastInRange) {
30623
30698
  out.push({
30624
30699
  type: "text",
@@ -30733,6 +30808,8 @@ var init_MathCanvas = __esm({
30733
30808
  showAxes,
30734
30809
  showGrid,
30735
30810
  gridStep,
30811
+ gridColor,
30812
+ axisColor,
30736
30813
  showTickLabels,
30737
30814
  showCurveLabels,
30738
30815
  curves,
@@ -30752,6 +30829,7 @@ var init_MathCanvas = __esm({
30752
30829
  {
30753
30830
  width,
30754
30831
  height,
30832
+ backgroundColor,
30755
30833
  shapes: derivedShapes,
30756
30834
  readouts,
30757
30835
  traces,
@@ -31982,13 +32060,13 @@ var init_MapView = __esm({
31982
32060
  shadowSize: [41, 41]
31983
32061
  });
31984
32062
  L.Marker.prototype.options.icon = defaultIcon;
31985
- const { useEffect: useEffect65, useRef: useRef64, useCallback: useCallback97, useState: useState95 } = React87__default;
32063
+ const { useEffect: useEffect67, useRef: useRef64, useCallback: useCallback97, useState: useState95 } = React87__default;
31986
32064
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
31987
32065
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
31988
32066
  function MapUpdater({ centerLat, centerLng, zoom }) {
31989
32067
  const map = useMap();
31990
32068
  const prevRef = useRef64({ centerLat, centerLng, zoom });
31991
- useEffect65(() => {
32069
+ useEffect67(() => {
31992
32070
  const prev = prevRef.current;
31993
32071
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
31994
32072
  map.setView([centerLat, centerLng], zoom);
@@ -31999,7 +32077,7 @@ var init_MapView = __esm({
31999
32077
  }
32000
32078
  function MapClickHandler({ onMapClick }) {
32001
32079
  const map = useMap();
32002
- useEffect65(() => {
32080
+ useEffect67(() => {
32003
32081
  if (!onMapClick) return;
32004
32082
  const handler = (e) => {
32005
32083
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -32528,14 +32606,34 @@ var init_UploadDropZone = __esm({
32528
32606
  if (valid.length > 0) {
32529
32607
  onFiles?.(valid);
32530
32608
  if (action) {
32531
- eventBus.emit(`UI:${action}`, {
32532
- ...actionPayload,
32533
- files: valid.map((f3) => ({ name: f3.name, size: f3.size, type: f3.type }))
32609
+ void Promise.all(
32610
+ valid.map(
32611
+ (f3) => new Promise(
32612
+ (resolvePayload, rejectPayload) => {
32613
+ const reader = new FileReader();
32614
+ reader.onload = () => resolvePayload({
32615
+ name: f3.name,
32616
+ size: f3.size,
32617
+ type: f3.type,
32618
+ content: String(reader.result ?? "")
32619
+ });
32620
+ reader.onerror = () => rejectPayload(reader.error);
32621
+ reader.readAsDataURL(f3);
32622
+ }
32623
+ )
32624
+ )
32625
+ ).then((payloadFiles) => {
32626
+ eventBus.emit(`UI:${action}`, {
32627
+ ...actionPayload,
32628
+ files: payloadFiles
32629
+ });
32630
+ }).catch(() => {
32631
+ setError(t("Could not read the selected file"));
32534
32632
  });
32535
32633
  }
32536
32634
  }
32537
32635
  },
32538
- [validateFiles, onFiles, action, actionPayload, eventBus]
32636
+ [validateFiles, onFiles, action, actionPayload, eventBus, t]
32539
32637
  );
32540
32638
  const handleDragOver = (e) => {
32541
32639
  e.preventDefault();
@@ -42052,22 +42150,6 @@ var init_DataTable = __esm({
42052
42150
  DataTable.displayName = "DataTable";
42053
42151
  }
42054
42152
  });
42055
- function getFieldIcon(fieldName) {
42056
- const name = fieldName.toLowerCase();
42057
- if (name.includes("date") || name.includes("time")) return Calendar;
42058
- if (name.includes("status")) return Tag;
42059
- if (name.includes("priority")) return AlertCircle;
42060
- if (name.includes("progress") || name.includes("percent")) return TrendingUp;
42061
- if (name.includes("assignee") || name.includes("owner") || name.includes("user") || name.includes("member"))
42062
- return User;
42063
- if (name.includes("due")) return Clock;
42064
- if (name.includes("complete")) return CheckCircle2;
42065
- if (name.includes("budget") || name.includes("cost") || name.includes("price"))
42066
- return DollarSign;
42067
- if (name.includes("description") || name.includes("note") || name.includes("comment"))
42068
- return FileText;
42069
- return Package;
42070
- }
42071
42153
  function getBadgeVariant(fieldName, value) {
42072
42154
  const name = fieldName.toLowerCase();
42073
42155
  const val = String(value).toLowerCase();
@@ -42117,6 +42199,18 @@ function renderRichFieldValue(value, fieldName, fieldType, meta) {
42117
42199
  }
42118
42200
  ) });
42119
42201
  }
42202
+ if (fieldType === "url" && /^https?:\/\//i.test(str)) {
42203
+ return /* @__PURE__ */ jsx(
42204
+ "a",
42205
+ {
42206
+ href: str,
42207
+ target: "_blank",
42208
+ rel: "noreferrer",
42209
+ className: "text-primary hover:underline break-all",
42210
+ children: str
42211
+ }
42212
+ );
42213
+ }
42120
42214
  return str;
42121
42215
  }
42122
42216
  case "markdown":
@@ -42215,6 +42309,23 @@ function renderRichFieldValue(value, fieldName, fieldType, meta) {
42215
42309
  }
42216
42310
  return str;
42217
42311
  }
42312
+ case "boolean": {
42313
+ if (typeof value === "boolean") return value ? "Yes" : "No";
42314
+ if (str === "true") return "Yes";
42315
+ if (str === "false") return "No";
42316
+ return str;
42317
+ }
42318
+ case "array": {
42319
+ if (Array.isArray(value) && value.length > 0) {
42320
+ return /* @__PURE__ */ jsx(HStack, { gap: "xs", wrap: true, children: value.map((item, i) => /* @__PURE__ */ jsx(Badge, { variant: "default", children: String(item) }, i)) });
42321
+ }
42322
+ if (Array.isArray(value)) return "\u2014";
42323
+ return str;
42324
+ }
42325
+ case "email":
42326
+ return /* @__PURE__ */ jsx("a", { href: `mailto:${str}`, className: "text-primary hover:underline break-all", children: str });
42327
+ case "phone":
42328
+ return /* @__PURE__ */ jsx("a", { href: `tel:${str}`, className: "text-primary hover:underline", children: str });
42218
42329
  default:
42219
42330
  if (meta?.values && meta.values.length > 0 && meta.values.includes(str)) {
42220
42331
  return /* @__PURE__ */ jsx(Badge, { variant: getBadgeVariant(fieldName, str), children: humanizeEnumValue(str) });
@@ -42287,10 +42398,11 @@ var init_DetailPanel = __esm({
42287
42398
  avatar,
42288
42399
  sections: propSections,
42289
42400
  actions,
42290
- maxInlineActions,
42401
+ maxInlineActions = 2,
42291
42402
  backAction,
42292
42403
  footer,
42293
42404
  slideOver = false,
42405
+ showActions = true,
42294
42406
  className,
42295
42407
  entity,
42296
42408
  fields: propFields,
@@ -42338,9 +42450,6 @@ var init_DetailPanel = __esm({
42338
42450
  },
42339
42451
  [eventBus]
42340
42452
  );
42341
- const handleClose = useCallback(() => {
42342
- eventBus.emit("UI:CLOSE", {});
42343
- }, [eventBus]);
42344
42453
  const entityRecord = Array.isArray(entity) ? entity[0] : entity;
42345
42454
  const data = entityRecord ?? initialData;
42346
42455
  let title = propTitle;
@@ -42354,8 +42463,7 @@ var init_DetailPanel = __esm({
42354
42463
  const value = getNestedValue(normalizedData, field);
42355
42464
  return {
42356
42465
  label: labelFor(field),
42357
- value: formatFieldValue2(value, field),
42358
- icon: getFieldIcon(field)
42466
+ value: formatFieldValue2(value, field)
42359
42467
  };
42360
42468
  }
42361
42469
  return field;
@@ -42389,15 +42497,14 @@ var init_DetailPanel = __esm({
42389
42497
  (f3) => (!titleDerivedFromPrimary || f3 !== primaryField) && !statusFields.includes(f3) && !progressFields.includes(f3) && !metricFields.includes(f3) && !dateFields.includes(f3) && !descriptionFields.includes(f3)
42390
42498
  );
42391
42499
  sections = [];
42392
- if (statusFields.length > 0 || otherFields.length > 0) {
42500
+ if (otherFields.length > 0) {
42393
42501
  const overviewFields = [];
42394
- [...statusFields, ...otherFields].forEach((field) => {
42502
+ otherFields.forEach((field) => {
42395
42503
  const value = getNestedValue(normalizedData, field);
42396
42504
  if (value !== void 0 && value !== null) {
42397
42505
  overviewFields.push({
42398
42506
  label: labelFor(field),
42399
- value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field)),
42400
- icon: getFieldIcon(field)
42507
+ value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field))
42401
42508
  });
42402
42509
  }
42403
42510
  });
@@ -42412,8 +42519,7 @@ var init_DetailPanel = __esm({
42412
42519
  if (value !== void 0 && value !== null) {
42413
42520
  metricsFields.push({
42414
42521
  label: labelFor(field),
42415
- value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field)),
42416
- icon: getFieldIcon(field)
42522
+ value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field))
42417
42523
  });
42418
42524
  }
42419
42525
  });
@@ -42428,8 +42534,7 @@ var init_DetailPanel = __esm({
42428
42534
  if (value !== void 0 && value !== null) {
42429
42535
  timelineFields.push({
42430
42536
  label: labelFor(field),
42431
- value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field)),
42432
- icon: getFieldIcon(field)
42537
+ value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field))
42433
42538
  });
42434
42539
  }
42435
42540
  });
@@ -42444,8 +42549,7 @@ var init_DetailPanel = __esm({
42444
42549
  if (value !== void 0 && value !== null) {
42445
42550
  descFields.push({
42446
42551
  label: labelFor(field),
42447
- value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field)),
42448
- icon: getFieldIcon(field)
42552
+ value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field))
42449
42553
  });
42450
42554
  }
42451
42555
  });
@@ -42454,6 +42558,15 @@ var init_DetailPanel = __esm({
42454
42558
  }
42455
42559
  }
42456
42560
  }
42561
+ const renderSlot = useRenderSlot();
42562
+ const navStack = useNavStack();
42563
+ const { setCurrentLabel } = navStack;
42564
+ const resolvedTitle = normalizedData ? title : void 0;
42565
+ useEffect(() => {
42566
+ if (renderSlot === "main" && !slideOver && resolvedTitle) {
42567
+ setCurrentLabel(resolvedTitle);
42568
+ }
42569
+ }, [renderSlot, slideOver, resolvedTitle, setCurrentLabel]);
42457
42570
  if (isLoading) {
42458
42571
  return /* @__PURE__ */ jsx(
42459
42572
  LoadingState,
@@ -42492,8 +42605,7 @@ var init_DetailPanel = __esm({
42492
42605
  const value = normalizedData ? getNestedValue(normalizedData, field) : void 0;
42493
42606
  allFields.push({
42494
42607
  label: labelFor(field),
42495
- value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field)),
42496
- icon: getFieldIcon(field)
42608
+ value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field))
42497
42609
  });
42498
42610
  } else {
42499
42611
  allFields.push(field);
@@ -42505,24 +42617,50 @@ var init_DetailPanel = __esm({
42505
42617
  (a) => a.event === "CLOSE" || a.event === "CANCEL" || a.label?.toLowerCase() === "close"
42506
42618
  );
42507
42619
  const otherActions = actions?.filter((a) => a !== closeAction) ?? [];
42508
- const effectiveCloseAction = closeAction ?? { event: void 0};
42509
- const content = /* @__PURE__ */ jsx(Card, { variant: "elevated", children: /* @__PURE__ */ jsxs(VStack, { gap: "md", className: "p-6", children: [
42510
- /* @__PURE__ */ jsxs(HStack, { justify: "between", align: "center", gap: "xs", children: [
42511
- /* @__PURE__ */ jsx(HStack, { align: "center", gap: "xs", children: backAction && /* @__PURE__ */ jsx(
42512
- Button,
42620
+ const statusBadges = /* @__PURE__ */ jsxs(Fragment, { children: [
42621
+ normalizedData && effectiveFieldNames && effectiveFieldNames.filter(
42622
+ (f3) => f3.toLowerCase().includes("status") || f3.toLowerCase().includes("priority")
42623
+ ).map((field) => {
42624
+ const value = getNestedValue(normalizedData, field);
42625
+ if (!value) return null;
42626
+ return /* @__PURE__ */ jsx(
42627
+ Badge,
42513
42628
  {
42514
- variant: backAction.variant || "ghost",
42515
- size: "sm",
42516
- action: backAction.navigatesTo ? void 0 : backAction.event,
42517
- actionPayload: { row: normalizedData },
42518
- onClick: backAction.navigatesTo ? () => handleActionClick(backAction, normalizedData) : void 0,
42519
- icon: backAction.icon ?? ArrowLeft,
42520
- "data-testid": backAction.event ? `action-${backAction.event}` : "action-back",
42521
- children: backAction.label
42522
- }
42523
- ) }),
42524
- /* @__PURE__ */ jsxs(HStack, { justify: "end", align: "center", gap: "xs", children: [
42525
- (maxInlineActions != null ? otherActions.slice(0, maxInlineActions) : otherActions).map((action, idx) => /* @__PURE__ */ jsx(
42629
+ variant: getBadgeVariant(field, String(value)),
42630
+ children: humanizeEnumValue(String(value))
42631
+ },
42632
+ field
42633
+ );
42634
+ }),
42635
+ status && /* @__PURE__ */ jsx(Badge, { variant: status.variant ?? "default", children: status.label })
42636
+ ] });
42637
+ const content = /* @__PURE__ */ jsx(Card, { variant: "elevated", children: /* @__PURE__ */ jsxs(VStack, { gap: "md", className: "p-6", children: [
42638
+ /* @__PURE__ */ jsxs(HStack, { justify: "between", align: "start", gap: "md", children: [
42639
+ /* @__PURE__ */ jsxs(HStack, { align: "start", gap: "sm", className: "min-w-0", children: [
42640
+ backAction && /* @__PURE__ */ jsx(
42641
+ Button,
42642
+ {
42643
+ variant: backAction.variant || "ghost",
42644
+ size: "sm",
42645
+ action: backAction.navigatesTo ? void 0 : backAction.event,
42646
+ actionPayload: { row: normalizedData },
42647
+ onClick: backAction.navigatesTo ? () => handleActionClick(backAction, normalizedData) : void 0,
42648
+ icon: backAction.icon ?? ArrowLeft,
42649
+ "data-testid": backAction.event ? `action-${backAction.event}` : "action-back",
42650
+ children: backAction.label
42651
+ }
42652
+ ),
42653
+ avatar,
42654
+ /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "min-w-0", children: [
42655
+ /* @__PURE__ */ jsxs(HStack, { align: "center", gap: "sm", wrap: true, children: [
42656
+ /* @__PURE__ */ jsx(Typography, { variant: "h2", weight: "bold", children: title || "Details" }),
42657
+ statusBadges
42658
+ ] }),
42659
+ subtitle && /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: subtitle })
42660
+ ] })
42661
+ ] }),
42662
+ showActions && /* @__PURE__ */ jsxs(HStack, { justify: "end", align: "center", gap: "xs", className: "shrink-0", children: [
42663
+ otherActions.slice(0, maxInlineActions).map((action, idx) => /* @__PURE__ */ jsx(
42526
42664
  Button,
42527
42665
  {
42528
42666
  variant: action.variant || "secondary",
@@ -42537,7 +42675,7 @@ var init_DetailPanel = __esm({
42537
42675
  },
42538
42676
  idx
42539
42677
  )),
42540
- maxInlineActions != null && otherActions.length > maxInlineActions && /* @__PURE__ */ jsx(
42678
+ otherActions.length > maxInlineActions && /* @__PURE__ */ jsx(
42541
42679
  Menu,
42542
42680
  {
42543
42681
  position: "bottom-end",
@@ -42553,40 +42691,20 @@ var init_DetailPanel = __esm({
42553
42691
  }))
42554
42692
  }
42555
42693
  ),
42556
- /* @__PURE__ */ jsx(
42694
+ closeAction && /* @__PURE__ */ jsx(
42557
42695
  Button,
42558
42696
  {
42559
42697
  variant: "ghost",
42560
42698
  size: "sm",
42561
- action: effectiveCloseAction.event,
42699
+ action: closeAction.event,
42562
42700
  actionPayload: { row: normalizedData },
42563
- onClick: effectiveCloseAction.event ? void 0 : handleClose,
42701
+ onClick: closeAction.event ? void 0 : () => handleActionClick(closeAction, normalizedData),
42564
42702
  icon: X,
42565
- "data-testid": effectiveCloseAction.event ? `action-${effectiveCloseAction.event}` : "action-close"
42703
+ "data-testid": closeAction.event ? `action-${closeAction.event}` : "action-close"
42566
42704
  }
42567
42705
  )
42568
42706
  ] })
42569
42707
  ] }),
42570
- avatar,
42571
- /* @__PURE__ */ jsx(Typography, { variant: "h2", weight: "bold", children: title || "Details" }),
42572
- subtitle && /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: subtitle }),
42573
- /* @__PURE__ */ jsxs(HStack, { gap: "xs", wrap: true, children: [
42574
- normalizedData && effectiveFieldNames && effectiveFieldNames.filter(
42575
- (f3) => f3.toLowerCase().includes("status") || f3.toLowerCase().includes("priority")
42576
- ).map((field) => {
42577
- const value = getNestedValue(normalizedData, field);
42578
- if (!value) return null;
42579
- return /* @__PURE__ */ jsx(
42580
- Badge,
42581
- {
42582
- variant: getBadgeVariant(field, String(value)),
42583
- children: String(value)
42584
- },
42585
- field
42586
- );
42587
- }),
42588
- status && /* @__PURE__ */ jsx(Badge, { variant: status.variant ?? "default", children: status.label })
42589
- ] }),
42590
42708
  normalizedData && effectiveFieldNames && effectiveFieldNames.filter(
42591
42709
  (f3) => f3.toLowerCase().includes("progress") || f3.toLowerCase().includes("percent")
42592
42710
  ).map((field) => {
@@ -42619,9 +42737,10 @@ var init_DetailPanel = __esm({
42619
42737
  /* @__PURE__ */ jsx(
42620
42738
  Typography,
42621
42739
  {
42622
- variant: "small",
42623
- color: "secondary",
42740
+ variant: "caption",
42741
+ color: "muted",
42624
42742
  weight: "medium",
42743
+ className: "uppercase tracking-wider",
42625
42744
  children: field.label
42626
42745
  }
42627
42746
  ),
@@ -42690,7 +42809,7 @@ var init_DrawerSlot = __esm({
42690
42809
  position,
42691
42810
  width: size,
42692
42811
  className,
42693
- children
42812
+ children: /* @__PURE__ */ jsx(RenderSlotProvider, { slot: "drawer", children })
42694
42813
  }
42695
42814
  );
42696
42815
  };
@@ -44737,7 +44856,7 @@ var init_ModalSlot = __esm({
44737
44856
  title,
44738
44857
  size,
44739
44858
  className,
44740
- children
44859
+ children: /* @__PURE__ */ jsx(RenderSlotProvider, { slot: "modal", children })
44741
44860
  }
44742
44861
  );
44743
44862
  };
@@ -49140,7 +49259,10 @@ function MaybeTraitScope({
49140
49259
  }
49141
49260
  return /* @__PURE__ */ jsx(Fragment, { children });
49142
49261
  }
49143
- function UISlotComponent({
49262
+ function UISlotComponent(props) {
49263
+ return /* @__PURE__ */ jsx(RenderSlotProvider, { slot: props.slot, children: /* @__PURE__ */ jsx(UISlotComponentInner, { ...props }) });
49264
+ }
49265
+ function UISlotComponentInner({
49144
49266
  slot,
49145
49267
  portal = false,
49146
49268
  position,
@@ -50709,6 +50831,12 @@ var CurrentPagePathProvider = ({
50709
50831
  }) => /* @__PURE__ */ jsx(CurrentPagePathContext.Provider, { value, children });
50710
50832
  CurrentPagePathProvider.displayName = "CurrentPagePathProvider";
50711
50833
  var useCurrentPagePath2 = () => useContext(CurrentPagePathContext);
50834
+ var RenderSlotContext = createContext("main");
50835
+ var RenderSlotProvider4 = ({ slot, children }) => /* @__PURE__ */ jsx(RenderSlotContext.Provider, { value: slot, children });
50836
+ RenderSlotProvider4.displayName = "RenderSlotProvider";
50837
+ function useRenderSlot2() {
50838
+ return useContext(RenderSlotContext);
50839
+ }
50712
50840
  var EntitySchemaContext = createContext(null);
50713
50841
  function EntitySchemaProvider({
50714
50842
  entities,
@@ -51499,6 +51627,18 @@ function syncNavStack(state, pages, path, pending) {
51499
51627
  }
51500
51628
  return { state: { ...state, [page.orbital]: stack }, orbital: page.orbital };
51501
51629
  }
51630
+ function relabelCurrent(state, pages, path, label) {
51631
+ const normalized = normalizePath(path);
51632
+ const page = matchNavPage(pages, normalized);
51633
+ if (!page || !label) return state;
51634
+ const stack = state[page.orbital];
51635
+ if (!stack || stack.length === 0) return state;
51636
+ const idx = stack.findIndex((e) => e.href === normalized);
51637
+ if (idx < 0 || stack[idx].label === label) return state;
51638
+ const next = [...stack];
51639
+ next[idx] = { href: normalized, label };
51640
+ return { ...state, [page.orbital]: next };
51641
+ }
51502
51642
  function previousEntry(state, pages, path) {
51503
51643
  const page = matchNavPage(pages, normalizePath(path));
51504
51644
  if (!page) return null;
@@ -51515,10 +51655,11 @@ var INERT_API = {
51515
51655
  canGoBack: false,
51516
51656
  beginNavigate: () => void 0,
51517
51657
  back: () => void 0,
51518
- goTo: () => void 0
51658
+ goTo: () => void 0,
51659
+ setCurrentLabel: () => void 0
51519
51660
  };
51520
51661
  var NavStackContext = createContext(INERT_API);
51521
- function useNavStack2() {
51662
+ function useNavStack3() {
51522
51663
  return useContext(NavStackContext);
51523
51664
  }
51524
51665
  function loadStored(storageKey) {
@@ -51575,6 +51716,16 @@ var NavStackProvider = ({
51575
51716
  },
51576
51717
  [navigate]
51577
51718
  );
51719
+ const setCurrentLabel = useCallback(
51720
+ (label) => {
51721
+ setState((prev) => {
51722
+ const next = relabelCurrent(prev, pages, currentPath, label);
51723
+ if (next !== prev) persistStored(storageKey, next);
51724
+ return next;
51725
+ });
51726
+ },
51727
+ [pages, currentPath, storageKey]
51728
+ );
51578
51729
  const entries = useMemo(
51579
51730
  () => entriesFor(state, pages, currentPath),
51580
51731
  [state, pages, currentPath]
@@ -51585,9 +51736,10 @@ var NavStackProvider = ({
51585
51736
  canGoBack: previousEntry(state, pages, currentPath) !== null,
51586
51737
  beginNavigate,
51587
51738
  back,
51588
- goTo
51739
+ goTo,
51740
+ setCurrentLabel
51589
51741
  }),
51590
- [entries, state, pages, currentPath, beginNavigate, back, goTo]
51742
+ [entries, state, pages, currentPath, beginNavigate, back, goTo, setCurrentLabel]
51591
51743
  );
51592
51744
  return /* @__PURE__ */ jsx(NavStackContext.Provider, { value: api, children });
51593
51745
  };
@@ -51618,4 +51770,4 @@ var NavStackRouterBridge = ({
51618
51770
  };
51619
51771
  NavStackRouterBridge.displayName = "NavStackRouterBridge";
51620
51772
 
51621
- export { CurrentPagePathContext, CurrentPagePathProvider, EntityBindingContext, EntitySchemaProvider, EventBusContext2 as EventBusContext, EventBusProvider, GameAudioContext2 as GameAudioContext, GameAudioProvider2 as GameAudioProvider, NavStackProvider, NavStackRouterBridge, NavigationProvider2 as NavigationProvider, OfflineModeProvider, OrbitalProvider, OrbitalThemeProvider, SelectionContext, SelectionProvider, ServerBridgeProvider, TraitContext, TraitProvider, TraitScopeProvider3 as TraitScopeProvider, UserContext, UserProvider, VerificationProvider, comparePathSpecificity2 as comparePathSpecificity, extractRouteParams2 as extractRouteParams, findPageByName2 as findPageByName, findPageByPath2 as findPageByPath, getAllPages2 as getAllPages, getDefaultPage2 as getDefaultPage, matchPath2 as matchPath, matchPathAmong2 as matchPathAmong, pathMatches2 as pathMatches, useActivePage2 as useActivePage, useCurrentPagePath2 as useCurrentPagePath, useEntityBindingSnapshot2 as useEntityBindingSnapshot, useEntitySchema, useEntitySchemaOptional6 as useEntitySchemaOptional, useGameAudioContext2 as useGameAudioContext, useGameAudioContextOptional2 as useGameAudioContextOptional, useHasPermission, useHasRole, useInitPayload2 as useInitPayload, useNavStack2 as useNavStack, useNavigateTo2 as useNavigateTo, useNavigation2 as useNavigation, useNavigationId2 as useNavigationId, useNavigationState2 as useNavigationState, useOfflineMode, useOptionalOfflineMode, useSelection, useSelectionOptional, useServerBridge, useTrait, useTraitContext, useTraitScope2 as useTraitScope, useTraitScopeChain2 as useTraitScopeChain, useUser, useUserForEvaluation };
51773
+ export { CurrentPagePathContext, CurrentPagePathProvider, EntityBindingContext, EntitySchemaProvider, EventBusContext2 as EventBusContext, EventBusProvider, GameAudioContext2 as GameAudioContext, GameAudioProvider2 as GameAudioProvider, NavStackProvider, NavStackRouterBridge, NavigationProvider2 as NavigationProvider, OfflineModeProvider, OrbitalProvider, OrbitalThemeProvider, RenderSlotProvider4 as RenderSlotProvider, SelectionContext, SelectionProvider, ServerBridgeProvider, TraitContext, TraitProvider, TraitScopeProvider3 as TraitScopeProvider, UserContext, UserProvider, VerificationProvider, comparePathSpecificity2 as comparePathSpecificity, extractRouteParams2 as extractRouteParams, findPageByName2 as findPageByName, findPageByPath2 as findPageByPath, getAllPages2 as getAllPages, getDefaultPage2 as getDefaultPage, matchPath2 as matchPath, matchPathAmong2 as matchPathAmong, pathMatches2 as pathMatches, useActivePage2 as useActivePage, useCurrentPagePath2 as useCurrentPagePath, useEntityBindingSnapshot2 as useEntityBindingSnapshot, useEntitySchema, useEntitySchemaOptional6 as useEntitySchemaOptional, useGameAudioContext2 as useGameAudioContext, useGameAudioContextOptional2 as useGameAudioContextOptional, useHasPermission, useHasRole, useInitPayload2 as useInitPayload, useNavStack3 as useNavStack, useNavigateTo2 as useNavigateTo, useNavigation2 as useNavigation, useNavigationId2 as useNavigationId, useNavigationState2 as useNavigationState, useOfflineMode, useOptionalOfflineMode, useRenderSlot2 as useRenderSlot, useSelection, useSelectionOptional, useServerBridge, useTrait, useTraitContext, useTraitScope2 as useTraitScope, useTraitScopeChain2 as useTraitScopeChain, useUser, useUserForEvaluation };