@almadar/ui 5.154.0 → 5.156.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.
@@ -11609,10 +11609,21 @@ function ControlGrid({
11609
11609
  directionAssets,
11610
11610
  size = "md",
11611
11611
  disabled,
11612
+ visibility = "auto",
11612
11613
  className
11613
11614
  }) {
11614
11615
  const eventBus = useEventBus();
11615
11616
  const [active, setActive] = React94__namespace.useState(/* @__PURE__ */ new Set());
11617
+ const [coarse, setCoarse] = React94__namespace.useState(
11618
+ () => typeof window !== "undefined" && window.matchMedia("(pointer: coarse)").matches
11619
+ );
11620
+ React94__namespace.useEffect(() => {
11621
+ if (visibility !== "auto" || typeof window === "undefined") return;
11622
+ const mq = window.matchMedia("(pointer: coarse)");
11623
+ const onChange = (e) => setCoarse(e.matches);
11624
+ mq.addEventListener("change", onChange);
11625
+ return () => mq.removeEventListener("change", onChange);
11626
+ }, [visibility]);
11616
11627
  const handlePress = React94__namespace.useCallback(
11617
11628
  (id) => {
11618
11629
  setActive((prev) => new Set(prev).add(id));
@@ -11645,6 +11656,7 @@ function ControlGrid({
11645
11656
  },
11646
11657
  [kind, actionEvent, directionEvent, directionReleaseEvents, eventBus, onAction, onDirection]
11647
11658
  );
11659
+ if (visibility === "auto" && !coarse) return null;
11648
11660
  if (kind === "dpad") {
11649
11661
  const ds = dpadSizeMap[size];
11650
11662
  const dir = (d) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -11794,7 +11806,7 @@ function StatBadge({
11794
11806
  assetUrl,
11795
11807
  iconUrl,
11796
11808
  label,
11797
- value = 0,
11809
+ value,
11798
11810
  max,
11799
11811
  format = "number",
11800
11812
  icon,
@@ -11805,6 +11817,7 @@ function StatBadge({
11805
11817
  source: _source,
11806
11818
  field: _field
11807
11819
  }) {
11820
+ const hasValue = value !== void 0 && value !== null;
11808
11821
  const numValue = typeof value === "number" ? value : parseInt(String(value), 10) || 0;
11809
11822
  const resolvedAsset = iconUrl ?? assetUrl;
11810
11823
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -11818,8 +11831,8 @@ function StatBadge({
11818
11831
  ),
11819
11832
  children: [
11820
11833
  resolvedAsset ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl: resolvedAsset, icon: "image", size: 16, className: "flex-shrink-0" }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", className: "flex-shrink-0 text-lg", children: typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, className: "w-4 h-4" }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, className: "w-4 h-4" }) }) : null,
11821
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground font-medium", children: label }),
11822
- format === "hearts" && max && /* @__PURE__ */ jsxRuntime.jsx(
11834
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground font-medium text-xs", children: label }),
11835
+ hasValue && format === "hearts" && max && /* @__PURE__ */ jsxRuntime.jsx(
11823
11836
  HealthBar,
11824
11837
  {
11825
11838
  current: numValue,
@@ -11828,7 +11841,7 @@ function StatBadge({
11828
11841
  size: size === "lg" ? "md" : "sm"
11829
11842
  }
11830
11843
  ),
11831
- format === "bar" && max && /* @__PURE__ */ jsxRuntime.jsx(
11844
+ hasValue && format === "bar" && max && /* @__PURE__ */ jsxRuntime.jsx(
11832
11845
  HealthBar,
11833
11846
  {
11834
11847
  current: numValue,
@@ -11837,14 +11850,15 @@ function StatBadge({
11837
11850
  size: size === "lg" ? "md" : "sm"
11838
11851
  }
11839
11852
  ),
11840
- format === "number" && /* @__PURE__ */ jsxRuntime.jsx(
11853
+ hasValue && format === "number" && /* @__PURE__ */ jsxRuntime.jsx(
11841
11854
  ScoreDisplay,
11842
11855
  {
11843
11856
  value: numValue,
11844
- size: size === "lg" ? "md" : "sm"
11857
+ size: size === "lg" ? "md" : "sm",
11858
+ className: "font-display"
11845
11859
  }
11846
11860
  ),
11847
- format === "text" && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "font-bold text-foreground", children: value })
11861
+ hasValue && format === "text" && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "font-bold text-foreground", children: value })
11848
11862
  ]
11849
11863
  }
11850
11864
  );
@@ -11860,6 +11874,7 @@ var init_StatBadge = __esm({
11860
11874
  init_HealthBar();
11861
11875
  init_ScoreDisplay();
11862
11876
  sizeMap6 = {
11877
+ xs: "text-xs px-1.5 py-0.5",
11863
11878
  sm: "text-xs px-2 py-1",
11864
11879
  md: "text-sm px-3 py-1.5",
11865
11880
  lg: "text-base px-4 py-2"
@@ -11902,6 +11917,7 @@ function GameHud({
11902
11917
  items,
11903
11918
  elements,
11904
11919
  size = "md",
11920
+ variant = "floating",
11905
11921
  className,
11906
11922
  transparent = true
11907
11923
  }) {
@@ -11916,7 +11932,7 @@ function GameHud({
11916
11932
  /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx(StatBadge, { ...stat, size }, i)) })
11917
11933
  ] });
11918
11934
  }
11919
- if (position === "top" || position === "bottom") {
11935
+ if ((position === "top" || position === "bottom") && variant === "bar") {
11920
11936
  const mid = Math.ceil(stats.length / 2);
11921
11937
  const leftStats = stats.slice(0, mid);
11922
11938
  const rightStats = stats.slice(mid);
@@ -15137,7 +15153,7 @@ var init_StateJsonView = __esm({
15137
15153
  StateJsonView.displayName = "StateJsonView";
15138
15154
  }
15139
15155
  });
15140
- var FONT_BASE, GAME_FONTS, FONT_FACES, GameShell;
15156
+ var GAME_FONTS, GameShell;
15141
15157
  var init_GameShell = __esm({
15142
15158
  "components/game/templates/GameShell.tsx"() {
15143
15159
  init_cn();
@@ -15145,7 +15161,6 @@ var init_GameShell = __esm({
15145
15161
  init_Card();
15146
15162
  init_Typography();
15147
15163
  init_AtlasImage();
15148
- FONT_BASE = "https://almadar-kflow-assets.web.app/shared/_shared/kenney-fonts/fonts";
15149
15164
  GAME_FONTS = {
15150
15165
  future: "Kenney Future",
15151
15166
  "future-narrow": "Kenney Future Narrow",
@@ -15153,14 +15168,6 @@ var init_GameShell = __esm({
15153
15168
  blocks: "Kenney Blocks",
15154
15169
  mini: "Kenney Mini"
15155
15170
  };
15156
- FONT_FACES = `
15157
- @font-face { font-family: 'Kenney Future'; src: url('${FONT_BASE}/Kenney%20Future.ttf') format('truetype'); font-display: swap; }
15158
- @font-face { font-family: 'Kenney Future Narrow'; src: url('${FONT_BASE}/Kenney%20Future%20Narrow.ttf') format('truetype'); font-display: swap; }
15159
- @font-face { font-family: 'Kenney Pixel'; src: url('${FONT_BASE}/Kenney%20Pixel.ttf') format('truetype'); font-display: swap; }
15160
- @font-face { font-family: 'Kenney Blocks'; src: url('${FONT_BASE}/Kenney%20Blocks.ttf') format('truetype'); font-display: swap; }
15161
- @font-face { font-family: 'Kenney Mini'; src: url('${FONT_BASE}/Kenney%20Mini.ttf') format('truetype'); font-display: swap; }
15162
- .game-shell, .game-shell * { font-family: inherit; }
15163
- `;
15164
15171
  GameShell = ({
15165
15172
  appName = "Game",
15166
15173
  hud,
@@ -15187,10 +15194,12 @@ var init_GameShell = __esm({
15187
15194
  overflow: "hidden",
15188
15195
  background: "var(--color-background, #0a0a0f)",
15189
15196
  color: "var(--color-foreground, #e0e0e0)",
15190
- fontFamily: `'${font}', system-ui, sans-serif`
15197
+ // The fontFamily knob is a scoped override of the theme contract's
15198
+ // display slot: titles/numerics take the game face, body text keeps
15199
+ // the active theme's --font-family-body.
15200
+ "--font-family-display": `'${font}', ui-sans-serif, system-ui, sans-serif`
15191
15201
  },
15192
15202
  children: [
15193
- /* @__PURE__ */ jsxRuntime.jsx("style", { children: FONT_FACES }),
15194
15203
  backgroundAsset && /* @__PURE__ */ jsxRuntime.jsx(
15195
15204
  AtlasPanel,
15196
15205
  {
@@ -15228,6 +15237,7 @@ var init_GameShell = __esm({
15228
15237
  Typography,
15229
15238
  {
15230
15239
  as: "span",
15240
+ className: "font-display",
15231
15241
  style: {
15232
15242
  fontWeight: 700,
15233
15243
  fontSize: "1.05rem",
@@ -15308,6 +15318,11 @@ var init_molecules = __esm({
15308
15318
  init_puzzleObject();
15309
15319
  }
15310
15320
  });
15321
+ function themeBodyFont(el) {
15322
+ if (typeof getComputedStyle !== "function") return "system-ui, sans-serif";
15323
+ const v = getComputedStyle(el).getPropertyValue("--font-family-body").trim();
15324
+ return v || "system-ui, sans-serif";
15325
+ }
15311
15326
  function resolveColor2(color, ctx, fallback) {
15312
15327
  if (!color) return fallback;
15313
15328
  if (color.startsWith("var(")) {
@@ -15507,7 +15522,7 @@ function drawShape(ctx, shape, width, height, allShapes) {
15507
15522
  case "text": {
15508
15523
  if (shape.x == null || shape.y == null || !shape.text) break;
15509
15524
  ctx.fillStyle = stroke;
15510
- ctx.font = `${shape.fontSize ?? 14}px system-ui, sans-serif`;
15525
+ ctx.font = `${shape.fontSize ?? 14}px ${themeBodyFont(ctx.canvas)}`;
15511
15526
  ctx.textAlign = shape.align ?? "left";
15512
15527
  ctx.textBaseline = "middle";
15513
15528
  ctx.fillText(shape.text, shape.x, shape.y);
@@ -24031,7 +24046,22 @@ function eventStartDate(event, startField) {
24031
24046
  const raw = getNestedValue(event, startField);
24032
24047
  return new Date(raw ?? "");
24033
24048
  }
24034
- function generateDefaultTimeSlots(events2, startField) {
24049
+ function eventEndDate(event, endField) {
24050
+ const raw = getNestedValue(event, endField);
24051
+ if (raw === void 0 || raw === null || raw === "") return null;
24052
+ const end = new Date(raw);
24053
+ return Number.isNaN(end.getTime()) ? null : end;
24054
+ }
24055
+ function eventContinuesInSlot(event, day, slotTime, startField, endField) {
24056
+ const eventStart = eventStartDate(event, startField);
24057
+ const eventEnd = eventEndDate(event, endField);
24058
+ if (eventEnd === null || Number.isNaN(eventStart.getTime())) return false;
24059
+ const [slotHour] = slotTime.split(":").map(Number);
24060
+ const slotStart = new Date(day);
24061
+ slotStart.setHours(slotHour, 0, 0, 0);
24062
+ return slotStart.getTime() > eventStart.getTime() && slotStart.getTime() < eventEnd.getTime();
24063
+ }
24064
+ function generateDefaultTimeSlots(events2, startField, endField) {
24035
24065
  let first = DEFAULT_FIRST_HOUR;
24036
24066
  let last = DEFAULT_LAST_HOUR;
24037
24067
  for (const ev of events2) {
@@ -24040,6 +24070,11 @@ function generateDefaultTimeSlots(events2, startField) {
24040
24070
  const hour = start.getHours();
24041
24071
  if (hour < first) first = hour;
24042
24072
  if (hour > last) last = hour;
24073
+ const end = eventEndDate(ev, endField);
24074
+ if (end && end.toDateString() === start.toDateString()) {
24075
+ const endHour = end.getMinutes() === 0 && end.getSeconds() === 0 ? end.getHours() - 1 : end.getHours();
24076
+ if (endHour > last) last = endHour;
24077
+ }
24043
24078
  }
24044
24079
  const slots = [];
24045
24080
  for (let hour = first; hour <= last; hour++) {
@@ -24068,6 +24103,7 @@ function CalendarGrid({
24068
24103
  dayWindow = "auto",
24069
24104
  titleField = "title",
24070
24105
  startField = "startTime",
24106
+ endField = "endTime",
24071
24107
  colorField = "color",
24072
24108
  children,
24073
24109
  renderItem
@@ -24085,8 +24121,8 @@ function CalendarGrid({
24085
24121
  [resolvedWeekStart]
24086
24122
  );
24087
24123
  const resolvedTimeSlots = React94.useMemo(
24088
- () => timeSlots ?? generateDefaultTimeSlots(evs, startField),
24089
- [timeSlots, evs, startField]
24124
+ () => timeSlots ?? generateDefaultTimeSlots(evs, startField, endField),
24125
+ [timeSlots, evs, startField, endField]
24090
24126
  );
24091
24127
  const visibleCount = useDayWindow(dayWindow);
24092
24128
  const [dayOffset, setDayOffset] = React94.useState(0);
@@ -24246,12 +24282,15 @@ function CalendarGrid({
24246
24282
  const slotEvents = evs.filter(
24247
24283
  (ev) => eventInSlot(ev, day, time, startField)
24248
24284
  );
24285
+ const continuingEvents = evs.filter(
24286
+ (ev) => eventContinuesInSlot(ev, day, time, startField, endField)
24287
+ );
24249
24288
  const isToday = day.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
24250
24289
  return /* @__PURE__ */ jsxRuntime.jsx(
24251
24290
  TimeSlotCell,
24252
24291
  {
24253
24292
  time,
24254
- isOccupied: slotEvents.length > 0,
24293
+ isOccupied: slotEvents.length > 0 || continuingEvents.length > 0,
24255
24294
  onClick: () => handleSlotClick(day, time),
24256
24295
  className: cn(
24257
24296
  "border-l border-border",
@@ -24262,7 +24301,25 @@ function CalendarGrid({
24262
24301
  onPointerUp: clearLongPress,
24263
24302
  onPointerCancel: clearLongPress
24264
24303
  } : {},
24265
- children: /* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "xs", children: slotEvents.map(renderEvent) })
24304
+ children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
24305
+ slotEvents.map(renderEvent),
24306
+ continuingEvents.map((event) => {
24307
+ const color = getNestedValue(event, colorField);
24308
+ return /* @__PURE__ */ jsxRuntime.jsx(
24309
+ Box,
24310
+ {
24311
+ rounded: "sm",
24312
+ border: true,
24313
+ className: cn(
24314
+ "cursor-pointer h-2",
24315
+ color ? cn(color, "opacity-50") : "bg-primary/10 border-primary/20"
24316
+ ),
24317
+ onClick: (e) => handleEventClick(event, e)
24318
+ },
24319
+ `${event.id}-cont`
24320
+ );
24321
+ })
24322
+ ] })
24266
24323
  },
24267
24324
  `${day.toISOString()}-${time}`
24268
24325
  );
@@ -34321,13 +34378,13 @@ var init_MapView = __esm({
34321
34378
  shadowSize: [41, 41]
34322
34379
  });
34323
34380
  L.Marker.prototype.options.icon = defaultIcon;
34324
- const { useEffect: useEffect65, useRef: useRef65, useCallback: useCallback96, useState: useState100 } = React94__namespace.default;
34381
+ const { useEffect: useEffect67, useRef: useRef65, useCallback: useCallback96, useState: useState100 } = React94__namespace.default;
34325
34382
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
34326
34383
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
34327
34384
  function MapUpdater({ centerLat, centerLng, zoom }) {
34328
34385
  const map = useMap();
34329
34386
  const prevRef = useRef65({ centerLat, centerLng, zoom });
34330
- useEffect65(() => {
34387
+ useEffect67(() => {
34331
34388
  const prev = prevRef.current;
34332
34389
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
34333
34390
  map.setView([centerLat, centerLng], zoom);
@@ -34338,7 +34395,7 @@ var init_MapView = __esm({
34338
34395
  }
34339
34396
  function MapClickHandler({ onMapClick }) {
34340
34397
  const map = useMap();
34341
- useEffect65(() => {
34398
+ useEffect67(() => {
34342
34399
  if (!onMapClick) return;
34343
34400
  const handler = (e) => {
34344
34401
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -34867,14 +34924,34 @@ var init_UploadDropZone = __esm({
34867
34924
  if (valid.length > 0) {
34868
34925
  onFiles?.(valid);
34869
34926
  if (action) {
34870
- eventBus.emit(`UI:${action}`, {
34871
- ...actionPayload,
34872
- files: valid.map((f3) => ({ name: f3.name, size: f3.size, type: f3.type }))
34927
+ void Promise.all(
34928
+ valid.map(
34929
+ (f3) => new Promise(
34930
+ (resolvePayload, rejectPayload) => {
34931
+ const reader = new FileReader();
34932
+ reader.onload = () => resolvePayload({
34933
+ name: f3.name,
34934
+ size: f3.size,
34935
+ type: f3.type,
34936
+ content: String(reader.result ?? "")
34937
+ });
34938
+ reader.onerror = () => rejectPayload(reader.error);
34939
+ reader.readAsDataURL(f3);
34940
+ }
34941
+ )
34942
+ )
34943
+ ).then((payloadFiles) => {
34944
+ eventBus.emit(`UI:${action}`, {
34945
+ ...actionPayload,
34946
+ files: payloadFiles
34947
+ });
34948
+ }).catch(() => {
34949
+ setError(t("Could not read the selected file"));
34873
34950
  });
34874
34951
  }
34875
34952
  }
34876
34953
  },
34877
- [validateFiles, onFiles, action, actionPayload, eventBus]
34954
+ [validateFiles, onFiles, action, actionPayload, eventBus, t]
34878
34955
  );
34879
34956
  const handleDragOver = (e) => {
34880
34957
  e.preventDefault();
@@ -43982,22 +44059,6 @@ var init_DataTable = __esm({
43982
44059
  DataTable.displayName = "DataTable";
43983
44060
  }
43984
44061
  });
43985
- function getFieldIcon(fieldName) {
43986
- const name = fieldName.toLowerCase();
43987
- if (name.includes("date") || name.includes("time")) return LucideIcons2.Calendar;
43988
- if (name.includes("status")) return LucideIcons2.Tag;
43989
- if (name.includes("priority")) return LucideIcons2.AlertCircle;
43990
- if (name.includes("progress") || name.includes("percent")) return LucideIcons2.TrendingUp;
43991
- if (name.includes("assignee") || name.includes("owner") || name.includes("user") || name.includes("member"))
43992
- return LucideIcons2.User;
43993
- if (name.includes("due")) return LucideIcons2.Clock;
43994
- if (name.includes("complete")) return LucideIcons2.CheckCircle2;
43995
- if (name.includes("budget") || name.includes("cost") || name.includes("price"))
43996
- return LucideIcons2.DollarSign;
43997
- if (name.includes("description") || name.includes("note") || name.includes("comment"))
43998
- return LucideIcons2.FileText;
43999
- return LucideIcons2.Package;
44000
- }
44001
44062
  function getBadgeVariant(fieldName, value) {
44002
44063
  const name = fieldName.toLowerCase();
44003
44064
  const val = String(value).toLowerCase();
@@ -44047,6 +44108,18 @@ function renderRichFieldValue(value, fieldName, fieldType, meta) {
44047
44108
  }
44048
44109
  ) });
44049
44110
  }
44111
+ if (fieldType === "url" && /^https?:\/\//i.test(str)) {
44112
+ return /* @__PURE__ */ jsxRuntime.jsx(
44113
+ "a",
44114
+ {
44115
+ href: str,
44116
+ target: "_blank",
44117
+ rel: "noreferrer",
44118
+ className: "text-primary hover:underline break-all",
44119
+ children: str
44120
+ }
44121
+ );
44122
+ }
44050
44123
  return str;
44051
44124
  }
44052
44125
  case "markdown":
@@ -44145,6 +44218,23 @@ function renderRichFieldValue(value, fieldName, fieldType, meta) {
44145
44218
  }
44146
44219
  return str;
44147
44220
  }
44221
+ case "boolean": {
44222
+ if (typeof value === "boolean") return value ? "Yes" : "No";
44223
+ if (str === "true") return "Yes";
44224
+ if (str === "false") return "No";
44225
+ return str;
44226
+ }
44227
+ case "array": {
44228
+ if (Array.isArray(value) && value.length > 0) {
44229
+ return /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", wrap: true, children: value.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", children: String(item) }, i)) });
44230
+ }
44231
+ if (Array.isArray(value)) return "\u2014";
44232
+ return str;
44233
+ }
44234
+ case "email":
44235
+ return /* @__PURE__ */ jsxRuntime.jsx("a", { href: `mailto:${str}`, className: "text-primary hover:underline break-all", children: str });
44236
+ case "phone":
44237
+ return /* @__PURE__ */ jsxRuntime.jsx("a", { href: `tel:${str}`, className: "text-primary hover:underline", children: str });
44148
44238
  default:
44149
44239
  if (meta?.values && meta.values.length > 0 && meta.values.includes(str)) {
44150
44240
  return /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: getBadgeVariant(fieldName, str), children: humanizeEnumValue(str) });
@@ -44217,10 +44307,11 @@ var init_DetailPanel = __esm({
44217
44307
  avatar,
44218
44308
  sections: propSections,
44219
44309
  actions,
44220
- maxInlineActions,
44310
+ maxInlineActions = 2,
44221
44311
  backAction,
44222
44312
  footer,
44223
44313
  slideOver = false,
44314
+ showActions = true,
44224
44315
  className,
44225
44316
  entity,
44226
44317
  fields: propFields,
@@ -44268,9 +44359,6 @@ var init_DetailPanel = __esm({
44268
44359
  },
44269
44360
  [eventBus]
44270
44361
  );
44271
- const handleClose = React94.useCallback(() => {
44272
- eventBus.emit("UI:CLOSE", {});
44273
- }, [eventBus]);
44274
44362
  const entityRecord = Array.isArray(entity) ? entity[0] : entity;
44275
44363
  const data = entityRecord ?? initialData;
44276
44364
  let title = propTitle;
@@ -44284,8 +44372,7 @@ var init_DetailPanel = __esm({
44284
44372
  const value = getNestedValue(normalizedData, field);
44285
44373
  return {
44286
44374
  label: labelFor(field),
44287
- value: formatFieldValue2(value, field),
44288
- icon: getFieldIcon(field)
44375
+ value: formatFieldValue2(value, field)
44289
44376
  };
44290
44377
  }
44291
44378
  return field;
@@ -44319,15 +44406,14 @@ var init_DetailPanel = __esm({
44319
44406
  (f3) => (!titleDerivedFromPrimary || f3 !== primaryField) && !statusFields.includes(f3) && !progressFields.includes(f3) && !metricFields.includes(f3) && !dateFields.includes(f3) && !descriptionFields.includes(f3)
44320
44407
  );
44321
44408
  sections = [];
44322
- if (statusFields.length > 0 || otherFields.length > 0) {
44409
+ if (otherFields.length > 0) {
44323
44410
  const overviewFields = [];
44324
- [...statusFields, ...otherFields].forEach((field) => {
44411
+ otherFields.forEach((field) => {
44325
44412
  const value = getNestedValue(normalizedData, field);
44326
44413
  if (value !== void 0 && value !== null) {
44327
44414
  overviewFields.push({
44328
44415
  label: labelFor(field),
44329
- value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field)),
44330
- icon: getFieldIcon(field)
44416
+ value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field))
44331
44417
  });
44332
44418
  }
44333
44419
  });
@@ -44342,8 +44428,7 @@ var init_DetailPanel = __esm({
44342
44428
  if (value !== void 0 && value !== null) {
44343
44429
  metricsFields.push({
44344
44430
  label: labelFor(field),
44345
- value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field)),
44346
- icon: getFieldIcon(field)
44431
+ value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field))
44347
44432
  });
44348
44433
  }
44349
44434
  });
@@ -44358,8 +44443,7 @@ var init_DetailPanel = __esm({
44358
44443
  if (value !== void 0 && value !== null) {
44359
44444
  timelineFields.push({
44360
44445
  label: labelFor(field),
44361
- value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field)),
44362
- icon: getFieldIcon(field)
44446
+ value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field))
44363
44447
  });
44364
44448
  }
44365
44449
  });
@@ -44374,8 +44458,7 @@ var init_DetailPanel = __esm({
44374
44458
  if (value !== void 0 && value !== null) {
44375
44459
  descFields.push({
44376
44460
  label: labelFor(field),
44377
- value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field)),
44378
- icon: getFieldIcon(field)
44461
+ value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field))
44379
44462
  });
44380
44463
  }
44381
44464
  });
@@ -44384,6 +44467,15 @@ var init_DetailPanel = __esm({
44384
44467
  }
44385
44468
  }
44386
44469
  }
44470
+ const renderSlot = providers.useRenderSlot();
44471
+ const navStack = providers.useNavStack();
44472
+ const { setCurrentLabel } = navStack;
44473
+ const resolvedTitle = normalizedData ? title : void 0;
44474
+ React94.useEffect(() => {
44475
+ if (renderSlot === "main" && !slideOver && resolvedTitle) {
44476
+ setCurrentLabel(resolvedTitle);
44477
+ }
44478
+ }, [renderSlot, slideOver, resolvedTitle, setCurrentLabel]);
44387
44479
  if (isLoading) {
44388
44480
  return /* @__PURE__ */ jsxRuntime.jsx(
44389
44481
  LoadingState,
@@ -44422,8 +44514,7 @@ var init_DetailPanel = __esm({
44422
44514
  const value = normalizedData ? getNestedValue(normalizedData, field) : void 0;
44423
44515
  allFields.push({
44424
44516
  label: labelFor(field),
44425
- value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field)),
44426
- icon: getFieldIcon(field)
44517
+ value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field))
44427
44518
  });
44428
44519
  } else {
44429
44520
  allFields.push(field);
@@ -44435,24 +44526,50 @@ var init_DetailPanel = __esm({
44435
44526
  (a) => a.event === "CLOSE" || a.event === "CANCEL" || a.label?.toLowerCase() === "close"
44436
44527
  );
44437
44528
  const otherActions = actions?.filter((a) => a !== closeAction) ?? [];
44438
- const effectiveCloseAction = closeAction ?? { event: void 0};
44439
- const content = /* @__PURE__ */ jsxRuntime.jsx(Card, { variant: "elevated", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "md", className: "p-6", children: [
44440
- /* @__PURE__ */ jsxRuntime.jsxs(HStack, { justify: "between", align: "center", gap: "xs", children: [
44441
- /* @__PURE__ */ jsxRuntime.jsx(HStack, { align: "center", gap: "xs", children: backAction && /* @__PURE__ */ jsxRuntime.jsx(
44442
- Button,
44529
+ const statusBadges = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
44530
+ normalizedData && effectiveFieldNames && effectiveFieldNames.filter(
44531
+ (f3) => f3.toLowerCase().includes("status") || f3.toLowerCase().includes("priority")
44532
+ ).map((field) => {
44533
+ const value = getNestedValue(normalizedData, field);
44534
+ if (!value) return null;
44535
+ return /* @__PURE__ */ jsxRuntime.jsx(
44536
+ Badge,
44443
44537
  {
44444
- variant: backAction.variant || "ghost",
44445
- size: "sm",
44446
- action: backAction.navigatesTo ? void 0 : backAction.event,
44447
- actionPayload: { row: normalizedData },
44448
- onClick: backAction.navigatesTo ? () => handleActionClick(backAction, normalizedData) : void 0,
44449
- icon: backAction.icon ?? LucideIcons2.ArrowLeft,
44450
- "data-testid": backAction.event ? `action-${backAction.event}` : "action-back",
44451
- children: backAction.label
44452
- }
44453
- ) }),
44454
- /* @__PURE__ */ jsxRuntime.jsxs(HStack, { justify: "end", align: "center", gap: "xs", children: [
44455
- (maxInlineActions != null ? otherActions.slice(0, maxInlineActions) : otherActions).map((action, idx) => /* @__PURE__ */ jsxRuntime.jsx(
44538
+ variant: getBadgeVariant(field, String(value)),
44539
+ children: humanizeEnumValue(String(value))
44540
+ },
44541
+ field
44542
+ );
44543
+ }),
44544
+ status && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: status.variant ?? "default", children: status.label })
44545
+ ] });
44546
+ const content = /* @__PURE__ */ jsxRuntime.jsx(Card, { variant: "elevated", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "md", className: "p-6", children: [
44547
+ /* @__PURE__ */ jsxRuntime.jsxs(HStack, { justify: "between", align: "start", gap: "md", children: [
44548
+ /* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "start", gap: "sm", className: "min-w-0", children: [
44549
+ backAction && /* @__PURE__ */ jsxRuntime.jsx(
44550
+ Button,
44551
+ {
44552
+ variant: backAction.variant || "ghost",
44553
+ size: "sm",
44554
+ action: backAction.navigatesTo ? void 0 : backAction.event,
44555
+ actionPayload: { row: normalizedData },
44556
+ onClick: backAction.navigatesTo ? () => handleActionClick(backAction, normalizedData) : void 0,
44557
+ icon: backAction.icon ?? LucideIcons2.ArrowLeft,
44558
+ "data-testid": backAction.event ? `action-${backAction.event}` : "action-back",
44559
+ children: backAction.label
44560
+ }
44561
+ ),
44562
+ avatar,
44563
+ /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", className: "min-w-0", children: [
44564
+ /* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "center", gap: "sm", wrap: true, children: [
44565
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h2", weight: "bold", children: title || "Details" }),
44566
+ statusBadges
44567
+ ] }),
44568
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "secondary", children: subtitle })
44569
+ ] })
44570
+ ] }),
44571
+ showActions && /* @__PURE__ */ jsxRuntime.jsxs(HStack, { justify: "end", align: "center", gap: "xs", className: "shrink-0", children: [
44572
+ otherActions.slice(0, maxInlineActions).map((action, idx) => /* @__PURE__ */ jsxRuntime.jsx(
44456
44573
  Button,
44457
44574
  {
44458
44575
  variant: action.variant || "secondary",
@@ -44467,7 +44584,7 @@ var init_DetailPanel = __esm({
44467
44584
  },
44468
44585
  idx
44469
44586
  )),
44470
- maxInlineActions != null && otherActions.length > maxInlineActions && /* @__PURE__ */ jsxRuntime.jsx(
44587
+ otherActions.length > maxInlineActions && /* @__PURE__ */ jsxRuntime.jsx(
44471
44588
  Menu,
44472
44589
  {
44473
44590
  position: "bottom-end",
@@ -44483,40 +44600,20 @@ var init_DetailPanel = __esm({
44483
44600
  }))
44484
44601
  }
44485
44602
  ),
44486
- /* @__PURE__ */ jsxRuntime.jsx(
44603
+ closeAction && /* @__PURE__ */ jsxRuntime.jsx(
44487
44604
  Button,
44488
44605
  {
44489
44606
  variant: "ghost",
44490
44607
  size: "sm",
44491
- action: effectiveCloseAction.event,
44608
+ action: closeAction.event,
44492
44609
  actionPayload: { row: normalizedData },
44493
- onClick: effectiveCloseAction.event ? void 0 : handleClose,
44610
+ onClick: closeAction.event ? void 0 : () => handleActionClick(closeAction, normalizedData),
44494
44611
  icon: LucideIcons2.X,
44495
- "data-testid": effectiveCloseAction.event ? `action-${effectiveCloseAction.event}` : "action-close"
44612
+ "data-testid": closeAction.event ? `action-${closeAction.event}` : "action-close"
44496
44613
  }
44497
44614
  )
44498
44615
  ] })
44499
44616
  ] }),
44500
- avatar,
44501
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h2", weight: "bold", children: title || "Details" }),
44502
- subtitle && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "secondary", children: subtitle }),
44503
- /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", wrap: true, children: [
44504
- normalizedData && effectiveFieldNames && effectiveFieldNames.filter(
44505
- (f3) => f3.toLowerCase().includes("status") || f3.toLowerCase().includes("priority")
44506
- ).map((field) => {
44507
- const value = getNestedValue(normalizedData, field);
44508
- if (!value) return null;
44509
- return /* @__PURE__ */ jsxRuntime.jsx(
44510
- Badge,
44511
- {
44512
- variant: getBadgeVariant(field, String(value)),
44513
- children: String(value)
44514
- },
44515
- field
44516
- );
44517
- }),
44518
- status && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: status.variant ?? "default", children: status.label })
44519
- ] }),
44520
44617
  normalizedData && effectiveFieldNames && effectiveFieldNames.filter(
44521
44618
  (f3) => f3.toLowerCase().includes("progress") || f3.toLowerCase().includes("percent")
44522
44619
  ).map((field) => {
@@ -44549,9 +44646,10 @@ var init_DetailPanel = __esm({
44549
44646
  /* @__PURE__ */ jsxRuntime.jsx(
44550
44647
  Typography,
44551
44648
  {
44552
- variant: "small",
44553
- color: "secondary",
44649
+ variant: "caption",
44650
+ color: "muted",
44554
44651
  weight: "medium",
44652
+ className: "uppercase tracking-wider",
44555
44653
  children: field.label
44556
44654
  }
44557
44655
  ),
@@ -44620,7 +44718,7 @@ var init_DrawerSlot = __esm({
44620
44718
  position,
44621
44719
  width: size,
44622
44720
  className,
44623
- children
44721
+ children: /* @__PURE__ */ jsxRuntime.jsx(providers.RenderSlotProvider, { slot: "drawer", children })
44624
44722
  }
44625
44723
  );
44626
44724
  };
@@ -46667,7 +46765,7 @@ var init_ModalSlot = __esm({
46667
46765
  title,
46668
46766
  size,
46669
46767
  className,
46670
- children
46768
+ children: /* @__PURE__ */ jsxRuntime.jsx(providers.RenderSlotProvider, { slot: "modal", children })
46671
46769
  }
46672
46770
  );
46673
46771
  };
@@ -51089,7 +51187,10 @@ function MaybeTraitScope({
51089
51187
  }
51090
51188
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
51091
51189
  }
51092
- function UISlotComponent({
51190
+ function UISlotComponent(props) {
51191
+ return /* @__PURE__ */ jsxRuntime.jsx(providers.RenderSlotProvider, { slot: props.slot, children: /* @__PURE__ */ jsxRuntime.jsx(UISlotComponentInner, { ...props }) });
51192
+ }
51193
+ function UISlotComponentInner({
51093
51194
  slot,
51094
51195
  portal = false,
51095
51196
  position,