@almadar/ui 5.155.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.
@@ -8308,10 +8308,21 @@ function ControlGrid({
8308
8308
  directionAssets,
8309
8309
  size = "md",
8310
8310
  disabled,
8311
+ visibility = "auto",
8311
8312
  className
8312
8313
  }) {
8313
8314
  const eventBus = useEventBus();
8314
8315
  const [active, setActive] = React85__namespace.useState(/* @__PURE__ */ new Set());
8316
+ const [coarse, setCoarse] = React85__namespace.useState(
8317
+ () => typeof window !== "undefined" && window.matchMedia("(pointer: coarse)").matches
8318
+ );
8319
+ React85__namespace.useEffect(() => {
8320
+ if (visibility !== "auto" || typeof window === "undefined") return;
8321
+ const mq = window.matchMedia("(pointer: coarse)");
8322
+ const onChange = (e) => setCoarse(e.matches);
8323
+ mq.addEventListener("change", onChange);
8324
+ return () => mq.removeEventListener("change", onChange);
8325
+ }, [visibility]);
8315
8326
  const handlePress = React85__namespace.useCallback(
8316
8327
  (id) => {
8317
8328
  setActive((prev) => new Set(prev).add(id));
@@ -8344,6 +8355,7 @@ function ControlGrid({
8344
8355
  },
8345
8356
  [kind, actionEvent, directionEvent, directionReleaseEvents, eventBus, onAction, onDirection]
8346
8357
  );
8358
+ if (visibility === "auto" && !coarse) return null;
8347
8359
  if (kind === "dpad") {
8348
8360
  const ds = dpadSizeMap[size];
8349
8361
  const dir = (d) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -8493,7 +8505,7 @@ function StatBadge({
8493
8505
  assetUrl,
8494
8506
  iconUrl,
8495
8507
  label,
8496
- value = 0,
8508
+ value,
8497
8509
  max,
8498
8510
  format = "number",
8499
8511
  icon,
@@ -8504,6 +8516,7 @@ function StatBadge({
8504
8516
  source: _source,
8505
8517
  field: _field
8506
8518
  }) {
8519
+ const hasValue = value !== void 0 && value !== null;
8507
8520
  const numValue = typeof value === "number" ? value : parseInt(String(value), 10) || 0;
8508
8521
  const resolvedAsset = iconUrl ?? assetUrl;
8509
8522
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -8517,8 +8530,8 @@ function StatBadge({
8517
8530
  ),
8518
8531
  children: [
8519
8532
  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,
8520
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground font-medium", children: label }),
8521
- format === "hearts" && max && /* @__PURE__ */ jsxRuntime.jsx(
8533
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground font-medium text-xs", children: label }),
8534
+ hasValue && format === "hearts" && max && /* @__PURE__ */ jsxRuntime.jsx(
8522
8535
  HealthBar,
8523
8536
  {
8524
8537
  current: numValue,
@@ -8527,7 +8540,7 @@ function StatBadge({
8527
8540
  size: size === "lg" ? "md" : "sm"
8528
8541
  }
8529
8542
  ),
8530
- format === "bar" && max && /* @__PURE__ */ jsxRuntime.jsx(
8543
+ hasValue && format === "bar" && max && /* @__PURE__ */ jsxRuntime.jsx(
8531
8544
  HealthBar,
8532
8545
  {
8533
8546
  current: numValue,
@@ -8536,14 +8549,15 @@ function StatBadge({
8536
8549
  size: size === "lg" ? "md" : "sm"
8537
8550
  }
8538
8551
  ),
8539
- format === "number" && /* @__PURE__ */ jsxRuntime.jsx(
8552
+ hasValue && format === "number" && /* @__PURE__ */ jsxRuntime.jsx(
8540
8553
  ScoreDisplay,
8541
8554
  {
8542
8555
  value: numValue,
8543
- size: size === "lg" ? "md" : "sm"
8556
+ size: size === "lg" ? "md" : "sm",
8557
+ className: "font-display"
8544
8558
  }
8545
8559
  ),
8546
- format === "text" && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "font-bold text-foreground", children: value })
8560
+ hasValue && format === "text" && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "font-bold text-foreground", children: value })
8547
8561
  ]
8548
8562
  }
8549
8563
  );
@@ -8559,6 +8573,7 @@ var init_StatBadge = __esm({
8559
8573
  init_HealthBar();
8560
8574
  init_ScoreDisplay();
8561
8575
  sizeMap6 = {
8576
+ xs: "text-xs px-1.5 py-0.5",
8562
8577
  sm: "text-xs px-2 py-1",
8563
8578
  md: "text-sm px-3 py-1.5",
8564
8579
  lg: "text-base px-4 py-2"
@@ -8601,6 +8616,7 @@ function GameHud({
8601
8616
  items,
8602
8617
  elements,
8603
8618
  size = "md",
8619
+ variant = "floating",
8604
8620
  className,
8605
8621
  transparent = true
8606
8622
  }) {
@@ -8615,7 +8631,7 @@ function GameHud({
8615
8631
  /* @__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)) })
8616
8632
  ] });
8617
8633
  }
8618
- if (position === "top" || position === "bottom") {
8634
+ if ((position === "top" || position === "bottom") && variant === "bar") {
8619
8635
  const mid = Math.ceil(stats.length / 2);
8620
8636
  const leftStats = stats.slice(0, mid);
8621
8637
  const rightStats = stats.slice(mid);
@@ -11729,7 +11745,7 @@ var init_StateJsonView = __esm({
11729
11745
  StateJsonView.displayName = "StateJsonView";
11730
11746
  }
11731
11747
  });
11732
- var FONT_BASE, GAME_FONTS, FONT_FACES, GameShell;
11748
+ var GAME_FONTS, GameShell;
11733
11749
  var init_GameShell = __esm({
11734
11750
  "components/game/templates/GameShell.tsx"() {
11735
11751
  init_cn();
@@ -11737,7 +11753,6 @@ var init_GameShell = __esm({
11737
11753
  init_Card();
11738
11754
  init_Typography();
11739
11755
  init_AtlasImage();
11740
- FONT_BASE = "https://almadar-kflow-assets.web.app/shared/_shared/kenney-fonts/fonts";
11741
11756
  GAME_FONTS = {
11742
11757
  future: "Kenney Future",
11743
11758
  "future-narrow": "Kenney Future Narrow",
@@ -11745,14 +11760,6 @@ var init_GameShell = __esm({
11745
11760
  blocks: "Kenney Blocks",
11746
11761
  mini: "Kenney Mini"
11747
11762
  };
11748
- FONT_FACES = `
11749
- @font-face { font-family: 'Kenney Future'; src: url('${FONT_BASE}/Kenney%20Future.ttf') format('truetype'); font-display: swap; }
11750
- @font-face { font-family: 'Kenney Future Narrow'; src: url('${FONT_BASE}/Kenney%20Future%20Narrow.ttf') format('truetype'); font-display: swap; }
11751
- @font-face { font-family: 'Kenney Pixel'; src: url('${FONT_BASE}/Kenney%20Pixel.ttf') format('truetype'); font-display: swap; }
11752
- @font-face { font-family: 'Kenney Blocks'; src: url('${FONT_BASE}/Kenney%20Blocks.ttf') format('truetype'); font-display: swap; }
11753
- @font-face { font-family: 'Kenney Mini'; src: url('${FONT_BASE}/Kenney%20Mini.ttf') format('truetype'); font-display: swap; }
11754
- .game-shell, .game-shell * { font-family: inherit; }
11755
- `;
11756
11763
  GameShell = ({
11757
11764
  appName = "Game",
11758
11765
  hud,
@@ -11779,10 +11786,12 @@ var init_GameShell = __esm({
11779
11786
  overflow: "hidden",
11780
11787
  background: "var(--color-background, #0a0a0f)",
11781
11788
  color: "var(--color-foreground, #e0e0e0)",
11782
- fontFamily: `'${font}', system-ui, sans-serif`
11789
+ // The fontFamily knob is a scoped override of the theme contract's
11790
+ // display slot: titles/numerics take the game face, body text keeps
11791
+ // the active theme's --font-family-body.
11792
+ "--font-family-display": `'${font}', ui-sans-serif, system-ui, sans-serif`
11783
11793
  },
11784
11794
  children: [
11785
- /* @__PURE__ */ jsxRuntime.jsx("style", { children: FONT_FACES }),
11786
11795
  backgroundAsset && /* @__PURE__ */ jsxRuntime.jsx(
11787
11796
  AtlasPanel,
11788
11797
  {
@@ -11820,6 +11829,7 @@ var init_GameShell = __esm({
11820
11829
  Typography,
11821
11830
  {
11822
11831
  as: "span",
11832
+ className: "font-display",
11823
11833
  style: {
11824
11834
  fontWeight: 700,
11825
11835
  fontSize: "1.05rem",
@@ -11900,6 +11910,11 @@ var init_molecules = __esm({
11900
11910
  init_puzzleObject();
11901
11911
  }
11902
11912
  });
11913
+ function themeBodyFont(el) {
11914
+ if (typeof getComputedStyle !== "function") return "system-ui, sans-serif";
11915
+ const v = getComputedStyle(el).getPropertyValue("--font-family-body").trim();
11916
+ return v || "system-ui, sans-serif";
11917
+ }
11903
11918
  function resolveColor2(color, ctx, fallback) {
11904
11919
  if (!color) return fallback;
11905
11920
  if (color.startsWith("var(")) {
@@ -12099,7 +12114,7 @@ function drawShape(ctx, shape, width, height, allShapes) {
12099
12114
  case "text": {
12100
12115
  if (shape.x == null || shape.y == null || !shape.text) break;
12101
12116
  ctx.fillStyle = stroke;
12102
- ctx.font = `${shape.fontSize ?? 14}px system-ui, sans-serif`;
12117
+ ctx.font = `${shape.fontSize ?? 14}px ${themeBodyFont(ctx.canvas)}`;
12103
12118
  ctx.textAlign = shape.align ?? "left";
12104
12119
  ctx.textBaseline = "middle";
12105
12120
  ctx.fillText(shape.text, shape.x, shape.y);
@@ -21333,7 +21348,22 @@ function eventStartDate(event, startField) {
21333
21348
  const raw = getNestedValue(event, startField);
21334
21349
  return new Date(raw ?? "");
21335
21350
  }
21336
- function generateDefaultTimeSlots(events2, startField) {
21351
+ function eventEndDate(event, endField) {
21352
+ const raw = getNestedValue(event, endField);
21353
+ if (raw === void 0 || raw === null || raw === "") return null;
21354
+ const end = new Date(raw);
21355
+ return Number.isNaN(end.getTime()) ? null : end;
21356
+ }
21357
+ function eventContinuesInSlot(event, day, slotTime, startField, endField) {
21358
+ const eventStart = eventStartDate(event, startField);
21359
+ const eventEnd = eventEndDate(event, endField);
21360
+ if (eventEnd === null || Number.isNaN(eventStart.getTime())) return false;
21361
+ const [slotHour] = slotTime.split(":").map(Number);
21362
+ const slotStart = new Date(day);
21363
+ slotStart.setHours(slotHour, 0, 0, 0);
21364
+ return slotStart.getTime() > eventStart.getTime() && slotStart.getTime() < eventEnd.getTime();
21365
+ }
21366
+ function generateDefaultTimeSlots(events2, startField, endField) {
21337
21367
  let first = DEFAULT_FIRST_HOUR;
21338
21368
  let last = DEFAULT_LAST_HOUR;
21339
21369
  for (const ev of events2) {
@@ -21342,6 +21372,11 @@ function generateDefaultTimeSlots(events2, startField) {
21342
21372
  const hour = start.getHours();
21343
21373
  if (hour < first) first = hour;
21344
21374
  if (hour > last) last = hour;
21375
+ const end = eventEndDate(ev, endField);
21376
+ if (end && end.toDateString() === start.toDateString()) {
21377
+ const endHour = end.getMinutes() === 0 && end.getSeconds() === 0 ? end.getHours() - 1 : end.getHours();
21378
+ if (endHour > last) last = endHour;
21379
+ }
21345
21380
  }
21346
21381
  const slots = [];
21347
21382
  for (let hour = first; hour <= last; hour++) {
@@ -21370,6 +21405,7 @@ function CalendarGrid({
21370
21405
  dayWindow = "auto",
21371
21406
  titleField = "title",
21372
21407
  startField = "startTime",
21408
+ endField = "endTime",
21373
21409
  colorField = "color",
21374
21410
  children,
21375
21411
  renderItem
@@ -21387,8 +21423,8 @@ function CalendarGrid({
21387
21423
  [resolvedWeekStart]
21388
21424
  );
21389
21425
  const resolvedTimeSlots = React85.useMemo(
21390
- () => timeSlots ?? generateDefaultTimeSlots(evs, startField),
21391
- [timeSlots, evs, startField]
21426
+ () => timeSlots ?? generateDefaultTimeSlots(evs, startField, endField),
21427
+ [timeSlots, evs, startField, endField]
21392
21428
  );
21393
21429
  const visibleCount = useDayWindow(dayWindow);
21394
21430
  const [dayOffset, setDayOffset] = React85.useState(0);
@@ -21548,12 +21584,15 @@ function CalendarGrid({
21548
21584
  const slotEvents = evs.filter(
21549
21585
  (ev) => eventInSlot(ev, day, time, startField)
21550
21586
  );
21587
+ const continuingEvents = evs.filter(
21588
+ (ev) => eventContinuesInSlot(ev, day, time, startField, endField)
21589
+ );
21551
21590
  const isToday = day.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
21552
21591
  return /* @__PURE__ */ jsxRuntime.jsx(
21553
21592
  TimeSlotCell,
21554
21593
  {
21555
21594
  time,
21556
- isOccupied: slotEvents.length > 0,
21595
+ isOccupied: slotEvents.length > 0 || continuingEvents.length > 0,
21557
21596
  onClick: () => handleSlotClick(day, time),
21558
21597
  className: cn(
21559
21598
  "border-l border-border",
@@ -21564,7 +21603,25 @@ function CalendarGrid({
21564
21603
  onPointerUp: clearLongPress,
21565
21604
  onPointerCancel: clearLongPress
21566
21605
  } : {},
21567
- children: /* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "xs", children: slotEvents.map(renderEvent) })
21606
+ children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
21607
+ slotEvents.map(renderEvent),
21608
+ continuingEvents.map((event) => {
21609
+ const color = getNestedValue(event, colorField);
21610
+ return /* @__PURE__ */ jsxRuntime.jsx(
21611
+ Box,
21612
+ {
21613
+ rounded: "sm",
21614
+ border: true,
21615
+ className: cn(
21616
+ "cursor-pointer h-2",
21617
+ color ? cn(color, "opacity-50") : "bg-primary/10 border-primary/20"
21618
+ ),
21619
+ onClick: (e) => handleEventClick(event, e)
21620
+ },
21621
+ `${event.id}-cont`
21622
+ );
21623
+ })
21624
+ ] })
21568
21625
  },
21569
21626
  `${day.toISOString()}-${time}`
21570
21627
  );
@@ -31545,13 +31602,13 @@ var init_MapView = __esm({
31545
31602
  shadowSize: [41, 41]
31546
31603
  });
31547
31604
  L.Marker.prototype.options.icon = defaultIcon;
31548
- const { useEffect: useEffect61, useRef: useRef63, useCallback: useCallback90, useState: useState92 } = React85__namespace.default;
31605
+ const { useEffect: useEffect63, useRef: useRef63, useCallback: useCallback90, useState: useState92 } = React85__namespace.default;
31549
31606
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
31550
31607
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
31551
31608
  function MapUpdater({ centerLat, centerLng, zoom }) {
31552
31609
  const map = useMap();
31553
31610
  const prevRef = useRef63({ centerLat, centerLng, zoom });
31554
- useEffect61(() => {
31611
+ useEffect63(() => {
31555
31612
  const prev = prevRef.current;
31556
31613
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
31557
31614
  map.setView([centerLat, centerLng], zoom);
@@ -31562,7 +31619,7 @@ var init_MapView = __esm({
31562
31619
  }
31563
31620
  function MapClickHandler({ onMapClick }) {
31564
31621
  const map = useMap();
31565
- useEffect61(() => {
31622
+ useEffect63(() => {
31566
31623
  if (!onMapClick) return;
31567
31624
  const handler = (e) => {
31568
31625
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -32091,14 +32148,34 @@ var init_UploadDropZone = __esm({
32091
32148
  if (valid.length > 0) {
32092
32149
  onFiles?.(valid);
32093
32150
  if (action) {
32094
- eventBus.emit(`UI:${action}`, {
32095
- ...actionPayload,
32096
- files: valid.map((f3) => ({ name: f3.name, size: f3.size, type: f3.type }))
32151
+ void Promise.all(
32152
+ valid.map(
32153
+ (f3) => new Promise(
32154
+ (resolvePayload, rejectPayload) => {
32155
+ const reader = new FileReader();
32156
+ reader.onload = () => resolvePayload({
32157
+ name: f3.name,
32158
+ size: f3.size,
32159
+ type: f3.type,
32160
+ content: String(reader.result ?? "")
32161
+ });
32162
+ reader.onerror = () => rejectPayload(reader.error);
32163
+ reader.readAsDataURL(f3);
32164
+ }
32165
+ )
32166
+ )
32167
+ ).then((payloadFiles) => {
32168
+ eventBus.emit(`UI:${action}`, {
32169
+ ...actionPayload,
32170
+ files: payloadFiles
32171
+ });
32172
+ }).catch(() => {
32173
+ setError(t("Could not read the selected file"));
32097
32174
  });
32098
32175
  }
32099
32176
  }
32100
32177
  },
32101
- [validateFiles, onFiles, action, actionPayload, eventBus]
32178
+ [validateFiles, onFiles, action, actionPayload, eventBus, t]
32102
32179
  );
32103
32180
  const handleDragOver = (e) => {
32104
32181
  e.preventDefault();
@@ -41477,22 +41554,6 @@ var init_DataTable = __esm({
41477
41554
  DataTable.displayName = "DataTable";
41478
41555
  }
41479
41556
  });
41480
- function getFieldIcon(fieldName) {
41481
- const name = fieldName.toLowerCase();
41482
- if (name.includes("date") || name.includes("time")) return LucideIcons2.Calendar;
41483
- if (name.includes("status")) return LucideIcons2.Tag;
41484
- if (name.includes("priority")) return LucideIcons2.AlertCircle;
41485
- if (name.includes("progress") || name.includes("percent")) return LucideIcons2.TrendingUp;
41486
- if (name.includes("assignee") || name.includes("owner") || name.includes("user") || name.includes("member"))
41487
- return LucideIcons2.User;
41488
- if (name.includes("due")) return LucideIcons2.Clock;
41489
- if (name.includes("complete")) return LucideIcons2.CheckCircle2;
41490
- if (name.includes("budget") || name.includes("cost") || name.includes("price"))
41491
- return LucideIcons2.DollarSign;
41492
- if (name.includes("description") || name.includes("note") || name.includes("comment"))
41493
- return LucideIcons2.FileText;
41494
- return LucideIcons2.Package;
41495
- }
41496
41557
  function getBadgeVariant(fieldName, value) {
41497
41558
  const name = fieldName.toLowerCase();
41498
41559
  const val = String(value).toLowerCase();
@@ -41542,6 +41603,18 @@ function renderRichFieldValue(value, fieldName, fieldType, meta) {
41542
41603
  }
41543
41604
  ) });
41544
41605
  }
41606
+ if (fieldType === "url" && /^https?:\/\//i.test(str)) {
41607
+ return /* @__PURE__ */ jsxRuntime.jsx(
41608
+ "a",
41609
+ {
41610
+ href: str,
41611
+ target: "_blank",
41612
+ rel: "noreferrer",
41613
+ className: "text-primary hover:underline break-all",
41614
+ children: str
41615
+ }
41616
+ );
41617
+ }
41545
41618
  return str;
41546
41619
  }
41547
41620
  case "markdown":
@@ -41640,6 +41713,23 @@ function renderRichFieldValue(value, fieldName, fieldType, meta) {
41640
41713
  }
41641
41714
  return str;
41642
41715
  }
41716
+ case "boolean": {
41717
+ if (typeof value === "boolean") return value ? "Yes" : "No";
41718
+ if (str === "true") return "Yes";
41719
+ if (str === "false") return "No";
41720
+ return str;
41721
+ }
41722
+ case "array": {
41723
+ if (Array.isArray(value) && value.length > 0) {
41724
+ return /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", wrap: true, children: value.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", children: String(item) }, i)) });
41725
+ }
41726
+ if (Array.isArray(value)) return "\u2014";
41727
+ return str;
41728
+ }
41729
+ case "email":
41730
+ return /* @__PURE__ */ jsxRuntime.jsx("a", { href: `mailto:${str}`, className: "text-primary hover:underline break-all", children: str });
41731
+ case "phone":
41732
+ return /* @__PURE__ */ jsxRuntime.jsx("a", { href: `tel:${str}`, className: "text-primary hover:underline", children: str });
41643
41733
  default:
41644
41734
  if (meta?.values && meta.values.length > 0 && meta.values.includes(str)) {
41645
41735
  return /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: getBadgeVariant(fieldName, str), children: humanizeEnumValue(str) });
@@ -41712,10 +41802,11 @@ var init_DetailPanel = __esm({
41712
41802
  avatar,
41713
41803
  sections: propSections,
41714
41804
  actions,
41715
- maxInlineActions,
41805
+ maxInlineActions = 2,
41716
41806
  backAction,
41717
41807
  footer,
41718
41808
  slideOver = false,
41809
+ showActions = true,
41719
41810
  className,
41720
41811
  entity,
41721
41812
  fields: propFields,
@@ -41763,9 +41854,6 @@ var init_DetailPanel = __esm({
41763
41854
  },
41764
41855
  [eventBus]
41765
41856
  );
41766
- const handleClose = React85.useCallback(() => {
41767
- eventBus.emit("UI:CLOSE", {});
41768
- }, [eventBus]);
41769
41857
  const entityRecord = Array.isArray(entity) ? entity[0] : entity;
41770
41858
  const data = entityRecord ?? initialData;
41771
41859
  let title = propTitle;
@@ -41779,8 +41867,7 @@ var init_DetailPanel = __esm({
41779
41867
  const value = getNestedValue(normalizedData, field);
41780
41868
  return {
41781
41869
  label: labelFor(field),
41782
- value: formatFieldValue2(value, field),
41783
- icon: getFieldIcon(field)
41870
+ value: formatFieldValue2(value, field)
41784
41871
  };
41785
41872
  }
41786
41873
  return field;
@@ -41814,15 +41901,14 @@ var init_DetailPanel = __esm({
41814
41901
  (f3) => (!titleDerivedFromPrimary || f3 !== primaryField) && !statusFields.includes(f3) && !progressFields.includes(f3) && !metricFields.includes(f3) && !dateFields.includes(f3) && !descriptionFields.includes(f3)
41815
41902
  );
41816
41903
  sections = [];
41817
- if (statusFields.length > 0 || otherFields.length > 0) {
41904
+ if (otherFields.length > 0) {
41818
41905
  const overviewFields = [];
41819
- [...statusFields, ...otherFields].forEach((field) => {
41906
+ otherFields.forEach((field) => {
41820
41907
  const value = getNestedValue(normalizedData, field);
41821
41908
  if (value !== void 0 && value !== null) {
41822
41909
  overviewFields.push({
41823
41910
  label: labelFor(field),
41824
- value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field)),
41825
- icon: getFieldIcon(field)
41911
+ value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field))
41826
41912
  });
41827
41913
  }
41828
41914
  });
@@ -41837,8 +41923,7 @@ var init_DetailPanel = __esm({
41837
41923
  if (value !== void 0 && value !== null) {
41838
41924
  metricsFields.push({
41839
41925
  label: labelFor(field),
41840
- value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field)),
41841
- icon: getFieldIcon(field)
41926
+ value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field))
41842
41927
  });
41843
41928
  }
41844
41929
  });
@@ -41853,8 +41938,7 @@ var init_DetailPanel = __esm({
41853
41938
  if (value !== void 0 && value !== null) {
41854
41939
  timelineFields.push({
41855
41940
  label: labelFor(field),
41856
- value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field)),
41857
- icon: getFieldIcon(field)
41941
+ value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field))
41858
41942
  });
41859
41943
  }
41860
41944
  });
@@ -41869,8 +41953,7 @@ var init_DetailPanel = __esm({
41869
41953
  if (value !== void 0 && value !== null) {
41870
41954
  descFields.push({
41871
41955
  label: labelFor(field),
41872
- value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field)),
41873
- icon: getFieldIcon(field)
41956
+ value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field))
41874
41957
  });
41875
41958
  }
41876
41959
  });
@@ -41879,6 +41962,15 @@ var init_DetailPanel = __esm({
41879
41962
  }
41880
41963
  }
41881
41964
  }
41965
+ const renderSlot = providers.useRenderSlot();
41966
+ const navStack = providers.useNavStack();
41967
+ const { setCurrentLabel } = navStack;
41968
+ const resolvedTitle = normalizedData ? title : void 0;
41969
+ React85.useEffect(() => {
41970
+ if (renderSlot === "main" && !slideOver && resolvedTitle) {
41971
+ setCurrentLabel(resolvedTitle);
41972
+ }
41973
+ }, [renderSlot, slideOver, resolvedTitle, setCurrentLabel]);
41882
41974
  if (isLoading) {
41883
41975
  return /* @__PURE__ */ jsxRuntime.jsx(
41884
41976
  LoadingState,
@@ -41917,8 +42009,7 @@ var init_DetailPanel = __esm({
41917
42009
  const value = normalizedData ? getNestedValue(normalizedData, field) : void 0;
41918
42010
  allFields.push({
41919
42011
  label: labelFor(field),
41920
- value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field)),
41921
- icon: getFieldIcon(field)
42012
+ value: renderRichFieldValue(value, field, fieldTypeMap[field], metaFor(field))
41922
42013
  });
41923
42014
  } else {
41924
42015
  allFields.push(field);
@@ -41930,24 +42021,50 @@ var init_DetailPanel = __esm({
41930
42021
  (a) => a.event === "CLOSE" || a.event === "CANCEL" || a.label?.toLowerCase() === "close"
41931
42022
  );
41932
42023
  const otherActions = actions?.filter((a) => a !== closeAction) ?? [];
41933
- const effectiveCloseAction = closeAction ?? { event: void 0};
41934
- const content = /* @__PURE__ */ jsxRuntime.jsx(Card, { variant: "elevated", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "md", className: "p-6", children: [
41935
- /* @__PURE__ */ jsxRuntime.jsxs(HStack, { justify: "between", align: "center", gap: "xs", children: [
41936
- /* @__PURE__ */ jsxRuntime.jsx(HStack, { align: "center", gap: "xs", children: backAction && /* @__PURE__ */ jsxRuntime.jsx(
41937
- Button,
42024
+ const statusBadges = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
42025
+ normalizedData && effectiveFieldNames && effectiveFieldNames.filter(
42026
+ (f3) => f3.toLowerCase().includes("status") || f3.toLowerCase().includes("priority")
42027
+ ).map((field) => {
42028
+ const value = getNestedValue(normalizedData, field);
42029
+ if (!value) return null;
42030
+ return /* @__PURE__ */ jsxRuntime.jsx(
42031
+ Badge,
41938
42032
  {
41939
- variant: backAction.variant || "ghost",
41940
- size: "sm",
41941
- action: backAction.navigatesTo ? void 0 : backAction.event,
41942
- actionPayload: { row: normalizedData },
41943
- onClick: backAction.navigatesTo ? () => handleActionClick(backAction, normalizedData) : void 0,
41944
- icon: backAction.icon ?? LucideIcons2.ArrowLeft,
41945
- "data-testid": backAction.event ? `action-${backAction.event}` : "action-back",
41946
- children: backAction.label
41947
- }
41948
- ) }),
41949
- /* @__PURE__ */ jsxRuntime.jsxs(HStack, { justify: "end", align: "center", gap: "xs", children: [
41950
- (maxInlineActions != null ? otherActions.slice(0, maxInlineActions) : otherActions).map((action, idx) => /* @__PURE__ */ jsxRuntime.jsx(
42033
+ variant: getBadgeVariant(field, String(value)),
42034
+ children: humanizeEnumValue(String(value))
42035
+ },
42036
+ field
42037
+ );
42038
+ }),
42039
+ status && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: status.variant ?? "default", children: status.label })
42040
+ ] });
42041
+ const content = /* @__PURE__ */ jsxRuntime.jsx(Card, { variant: "elevated", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "md", className: "p-6", children: [
42042
+ /* @__PURE__ */ jsxRuntime.jsxs(HStack, { justify: "between", align: "start", gap: "md", children: [
42043
+ /* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "start", gap: "sm", className: "min-w-0", children: [
42044
+ backAction && /* @__PURE__ */ jsxRuntime.jsx(
42045
+ Button,
42046
+ {
42047
+ variant: backAction.variant || "ghost",
42048
+ size: "sm",
42049
+ action: backAction.navigatesTo ? void 0 : backAction.event,
42050
+ actionPayload: { row: normalizedData },
42051
+ onClick: backAction.navigatesTo ? () => handleActionClick(backAction, normalizedData) : void 0,
42052
+ icon: backAction.icon ?? LucideIcons2.ArrowLeft,
42053
+ "data-testid": backAction.event ? `action-${backAction.event}` : "action-back",
42054
+ children: backAction.label
42055
+ }
42056
+ ),
42057
+ avatar,
42058
+ /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", className: "min-w-0", children: [
42059
+ /* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "center", gap: "sm", wrap: true, children: [
42060
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h2", weight: "bold", children: title || "Details" }),
42061
+ statusBadges
42062
+ ] }),
42063
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "secondary", children: subtitle })
42064
+ ] })
42065
+ ] }),
42066
+ showActions && /* @__PURE__ */ jsxRuntime.jsxs(HStack, { justify: "end", align: "center", gap: "xs", className: "shrink-0", children: [
42067
+ otherActions.slice(0, maxInlineActions).map((action, idx) => /* @__PURE__ */ jsxRuntime.jsx(
41951
42068
  Button,
41952
42069
  {
41953
42070
  variant: action.variant || "secondary",
@@ -41962,7 +42079,7 @@ var init_DetailPanel = __esm({
41962
42079
  },
41963
42080
  idx
41964
42081
  )),
41965
- maxInlineActions != null && otherActions.length > maxInlineActions && /* @__PURE__ */ jsxRuntime.jsx(
42082
+ otherActions.length > maxInlineActions && /* @__PURE__ */ jsxRuntime.jsx(
41966
42083
  Menu,
41967
42084
  {
41968
42085
  position: "bottom-end",
@@ -41978,40 +42095,20 @@ var init_DetailPanel = __esm({
41978
42095
  }))
41979
42096
  }
41980
42097
  ),
41981
- /* @__PURE__ */ jsxRuntime.jsx(
42098
+ closeAction && /* @__PURE__ */ jsxRuntime.jsx(
41982
42099
  Button,
41983
42100
  {
41984
42101
  variant: "ghost",
41985
42102
  size: "sm",
41986
- action: effectiveCloseAction.event,
42103
+ action: closeAction.event,
41987
42104
  actionPayload: { row: normalizedData },
41988
- onClick: effectiveCloseAction.event ? void 0 : handleClose,
42105
+ onClick: closeAction.event ? void 0 : () => handleActionClick(closeAction, normalizedData),
41989
42106
  icon: LucideIcons2.X,
41990
- "data-testid": effectiveCloseAction.event ? `action-${effectiveCloseAction.event}` : "action-close"
42107
+ "data-testid": closeAction.event ? `action-${closeAction.event}` : "action-close"
41991
42108
  }
41992
42109
  )
41993
42110
  ] })
41994
42111
  ] }),
41995
- avatar,
41996
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h2", weight: "bold", children: title || "Details" }),
41997
- subtitle && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "secondary", children: subtitle }),
41998
- /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", wrap: true, children: [
41999
- normalizedData && effectiveFieldNames && effectiveFieldNames.filter(
42000
- (f3) => f3.toLowerCase().includes("status") || f3.toLowerCase().includes("priority")
42001
- ).map((field) => {
42002
- const value = getNestedValue(normalizedData, field);
42003
- if (!value) return null;
42004
- return /* @__PURE__ */ jsxRuntime.jsx(
42005
- Badge,
42006
- {
42007
- variant: getBadgeVariant(field, String(value)),
42008
- children: String(value)
42009
- },
42010
- field
42011
- );
42012
- }),
42013
- status && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: status.variant ?? "default", children: status.label })
42014
- ] }),
42015
42112
  normalizedData && effectiveFieldNames && effectiveFieldNames.filter(
42016
42113
  (f3) => f3.toLowerCase().includes("progress") || f3.toLowerCase().includes("percent")
42017
42114
  ).map((field) => {
@@ -42044,9 +42141,10 @@ var init_DetailPanel = __esm({
42044
42141
  /* @__PURE__ */ jsxRuntime.jsx(
42045
42142
  Typography,
42046
42143
  {
42047
- variant: "small",
42048
- color: "secondary",
42144
+ variant: "caption",
42145
+ color: "muted",
42049
42146
  weight: "medium",
42147
+ className: "uppercase tracking-wider",
42050
42148
  children: field.label
42051
42149
  }
42052
42150
  ),
@@ -42115,7 +42213,7 @@ var init_DrawerSlot = __esm({
42115
42213
  position,
42116
42214
  width: size,
42117
42215
  className,
42118
- children
42216
+ children: /* @__PURE__ */ jsxRuntime.jsx(providers.RenderSlotProvider, { slot: "drawer", children })
42119
42217
  }
42120
42218
  );
42121
42219
  };
@@ -44162,7 +44260,7 @@ var init_ModalSlot = __esm({
44162
44260
  title,
44163
44261
  size,
44164
44262
  className,
44165
- children
44263
+ children: /* @__PURE__ */ jsxRuntime.jsx(providers.RenderSlotProvider, { slot: "modal", children })
44166
44264
  }
44167
44265
  );
44168
44266
  };
@@ -48584,7 +48682,10 @@ function MaybeTraitScope({
48584
48682
  }
48585
48683
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
48586
48684
  }
48587
- function UISlotComponent({
48685
+ function UISlotComponent(props) {
48686
+ return /* @__PURE__ */ jsxRuntime.jsx(providers.RenderSlotProvider, { slot: props.slot, children: /* @__PURE__ */ jsxRuntime.jsx(UISlotComponentInner, { ...props }) });
48687
+ }
48688
+ function UISlotComponentInner({
48588
48689
  slot,
48589
48690
  portal = false,
48590
48691
  position,