@almadar/ui 5.124.0 → 5.125.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.
@@ -25581,13 +25581,13 @@ function DataGrid({
25581
25581
  }
25582
25582
  ),
25583
25583
  /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", className: "flex-1 min-w-0", children: [
25584
- titleValue !== void 0 && titleValue !== null && /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center", children: [
25584
+ titleValue !== void 0 && titleValue !== null && /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center min-w-0", children: [
25585
25585
  titleField?.icon && renderIconInput(titleField.icon, { size: "sm", className: "text-primary flex-shrink-0" }),
25586
25586
  /* @__PURE__ */ jsxRuntime.jsx(
25587
25587
  Typography,
25588
25588
  {
25589
25589
  variant: titleField?.variant === "h3" ? "h3" : "h4",
25590
- className: "font-semibold truncate",
25590
+ className: "font-semibold truncate min-w-0",
25591
25591
  children: String(titleValue)
25592
25592
  }
25593
25593
  )
@@ -25645,7 +25645,7 @@ function DataGrid({
25645
25645
  )
25646
25646
  ] }, field.name);
25647
25647
  }) }) }),
25648
- primaryActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "px-4 py-3 mt-auto border-t border-border", children: /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", className: "justify-end", children: [
25648
+ primaryActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "px-4 py-3 mt-auto border-t border-border", children: /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", className: "justify-end flex-wrap", children: [
25649
25649
  (maxInlineActions != null ? primaryActions.slice(0, maxInlineActions) : primaryActions).map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
25650
25650
  Button,
25651
25651
  {
@@ -30658,7 +30658,7 @@ function TableView({
30658
30658
  col.key
30659
30659
  );
30660
30660
  }),
30661
- hasActions && /* @__PURE__ */ jsxRuntime.jsx(Box, { "aria-hidden": true })
30661
+ hasActions && /* @__PURE__ */ jsxRuntime.jsx(Box, { "aria-hidden": true, className: "sticky right-0 bg-[var(--color-surface-subtle)]" })
30662
30662
  ]
30663
30663
  }
30664
30664
  );
@@ -30702,41 +30702,54 @@ function TableView({
30702
30702
  }
30703
30703
  return /* @__PURE__ */ jsxRuntime.jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: formatCell(raw, col.format) }) }, col.key);
30704
30704
  }),
30705
- itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "justify-end flex-shrink-0 opacity-60 group-hover:opacity-100 transition-opacity", children: [
30706
- (maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions).map((action, i) => /* @__PURE__ */ jsxRuntime.jsxs(
30707
- Button,
30708
- {
30709
- variant: action.variant ?? "ghost",
30710
- size: "sm",
30711
- onClick: handleActionClick(action, row),
30712
- "data-testid": `action-${action.event}`,
30713
- "data-row-id": String(row.id),
30714
- className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
30715
- children: [
30716
- action.icon && renderIconInput3(action.icon, { size: "xs", className: "mr-1" }),
30717
- action.label
30718
- ]
30719
- },
30720
- i
30721
- )),
30722
- maxInlineActions != null && itemActions.length > maxInlineActions && /* @__PURE__ */ jsxRuntime.jsx(
30723
- Menu,
30724
- {
30725
- position: "bottom-end",
30726
- trigger: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
30727
- items: itemActions.slice(maxInlineActions).map((action) => ({
30728
- label: action.label,
30729
- icon: action.icon,
30730
- event: action.event,
30731
- variant: action.variant === "danger" ? "danger" : "default",
30732
- onClick: () => eventBus.emit(`UI:${action.event}`, {
30733
- id: row.id,
30734
- row
30735
- })
30736
- }))
30737
- }
30738
- )
30739
- ] })
30705
+ itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
30706
+ HStack,
30707
+ {
30708
+ gap: "xs",
30709
+ className: cn(
30710
+ // Pinned: the fixed column tracks routinely overflow the caller's
30711
+ // scroll container, which used to leave the actions off-screen.
30712
+ // Opaque so scrolled cells pass underneath it.
30713
+ "justify-end flex-shrink-0 sticky right-0 z-[1] transition-colors",
30714
+ lk.striped && index % 2 === 1 ? "bg-[var(--color-surface-subtle)]" : "bg-[var(--color-card)] group-hover:bg-[var(--color-surface-subtle)]"
30715
+ ),
30716
+ children: [
30717
+ (maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions).map((action, i) => /* @__PURE__ */ jsxRuntime.jsxs(
30718
+ Button,
30719
+ {
30720
+ variant: action.variant ?? "ghost",
30721
+ size: "sm",
30722
+ onClick: handleActionClick(action, row),
30723
+ "data-testid": `action-${action.event}`,
30724
+ "data-row-id": String(row.id),
30725
+ className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
30726
+ children: [
30727
+ action.icon && renderIconInput3(action.icon, { size: "xs", className: "mr-1" }),
30728
+ action.label
30729
+ ]
30730
+ },
30731
+ i
30732
+ )),
30733
+ maxInlineActions != null && itemActions.length > maxInlineActions && /* @__PURE__ */ jsxRuntime.jsx(
30734
+ Menu,
30735
+ {
30736
+ position: "bottom-end",
30737
+ trigger: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
30738
+ items: itemActions.slice(maxInlineActions).map((action) => ({
30739
+ label: action.label,
30740
+ icon: action.icon,
30741
+ event: action.event,
30742
+ variant: action.variant === "danger" ? "danger" : "default",
30743
+ onClick: () => eventBus.emit(`UI:${action.event}`, {
30744
+ id: row.id,
30745
+ row
30746
+ })
30747
+ }))
30748
+ }
30749
+ )
30750
+ ]
30751
+ }
30752
+ )
30740
30753
  ]
30741
30754
  }
30742
30755
  );
@@ -39062,6 +39075,16 @@ function normalizeFieldDefs(fields) {
39062
39075
  return String(f3);
39063
39076
  });
39064
39077
  }
39078
+ function buildFieldLabelMap(fields) {
39079
+ const map = {};
39080
+ if (!fields) return map;
39081
+ for (const f3 of fields) {
39082
+ if (typeof f3 === "object" && "key" in f3 && f3.header !== void 0 && f3.header !== "") {
39083
+ map[f3.key] = f3.header;
39084
+ }
39085
+ }
39086
+ return map;
39087
+ }
39065
39088
  function buildFieldTypeMap(fields) {
39066
39089
  const map = {};
39067
39090
  if (!fields) return map;
@@ -39113,6 +39136,8 @@ var init_DetailPanel = __esm({
39113
39136
  };
39114
39137
  const effectiveFieldNames = isFieldDefArray(propFields) ? normalizeFieldDefs(propFields) : fieldNames;
39115
39138
  const fieldTypeMap = isFieldDefArray(propFields) ? buildFieldTypeMap(propFields) : {};
39139
+ const fieldLabelMap = isFieldDefArray(propFields) ? buildFieldLabelMap(propFields) : {};
39140
+ const labelFor = (field) => fieldLabelMap[field] ?? formatFieldLabel(field);
39116
39141
  const handleActionClick = React91.useCallback(
39117
39142
  (action, data2) => {
39118
39143
  if (action.navigatesTo) {
@@ -39148,7 +39173,7 @@ var init_DetailPanel = __esm({
39148
39173
  if (typeof field === "string") {
39149
39174
  const value = getNestedValue(normalizedData, field);
39150
39175
  return {
39151
- label: formatFieldLabel(field),
39176
+ label: labelFor(field),
39152
39177
  value: formatFieldValue(value, field),
39153
39178
  icon: getFieldIcon(field)
39154
39179
  };
@@ -39159,7 +39184,10 @@ var init_DetailPanel = __esm({
39159
39184
  }
39160
39185
  if (normalizedData && effectiveFieldNames) {
39161
39186
  const primaryField = effectiveFieldNames[0];
39162
- if (!title && primaryField && normalizedData[primaryField]) {
39187
+ const titleDerivedFromPrimary = Boolean(
39188
+ !title && primaryField && normalizedData[primaryField]
39189
+ );
39190
+ if (titleDerivedFromPrimary) {
39163
39191
  title = String(normalizedData[primaryField]);
39164
39192
  }
39165
39193
  const statusFields = effectiveFieldNames.filter(
@@ -39178,16 +39206,16 @@ var init_DetailPanel = __esm({
39178
39206
  (f3) => f3.toLowerCase().includes("description") || f3.toLowerCase().includes("note")
39179
39207
  );
39180
39208
  const otherFields = effectiveFieldNames.filter(
39181
- (f3) => f3 !== primaryField && !statusFields.includes(f3) && !progressFields.includes(f3) && !metricFields.includes(f3) && !dateFields.includes(f3) && !descriptionFields.includes(f3)
39209
+ (f3) => (!titleDerivedFromPrimary || f3 !== primaryField) && !statusFields.includes(f3) && !progressFields.includes(f3) && !metricFields.includes(f3) && !dateFields.includes(f3) && !descriptionFields.includes(f3)
39182
39210
  );
39183
39211
  sections = [];
39184
39212
  if (statusFields.length > 0 || otherFields.length > 0) {
39185
39213
  const overviewFields = [];
39186
- [...statusFields, ...otherFields.slice(0, 3)].forEach((field) => {
39214
+ [...statusFields, ...otherFields].forEach((field) => {
39187
39215
  const value = getNestedValue(normalizedData, field);
39188
39216
  if (value !== void 0 && value !== null) {
39189
39217
  overviewFields.push({
39190
- label: formatFieldLabel(field),
39218
+ label: labelFor(field),
39191
39219
  value: renderRichFieldValue(value, field, fieldTypeMap[field]),
39192
39220
  icon: getFieldIcon(field)
39193
39221
  });
@@ -39203,7 +39231,7 @@ var init_DetailPanel = __esm({
39203
39231
  const value = getNestedValue(normalizedData, field);
39204
39232
  if (value !== void 0 && value !== null) {
39205
39233
  metricsFields.push({
39206
- label: formatFieldLabel(field),
39234
+ label: labelFor(field),
39207
39235
  value: renderRichFieldValue(value, field, fieldTypeMap[field]),
39208
39236
  icon: getFieldIcon(field)
39209
39237
  });
@@ -39219,7 +39247,7 @@ var init_DetailPanel = __esm({
39219
39247
  const value = getNestedValue(normalizedData, field);
39220
39248
  if (value !== void 0 && value !== null) {
39221
39249
  timelineFields.push({
39222
- label: formatFieldLabel(field),
39250
+ label: labelFor(field),
39223
39251
  value: renderRichFieldValue(value, field, fieldTypeMap[field]),
39224
39252
  icon: getFieldIcon(field)
39225
39253
  });
@@ -39235,7 +39263,7 @@ var init_DetailPanel = __esm({
39235
39263
  const value = getNestedValue(normalizedData, field);
39236
39264
  if (value !== void 0 && value !== null) {
39237
39265
  descFields.push({
39238
- label: formatFieldLabel(field),
39266
+ label: labelFor(field),
39239
39267
  value: renderRichFieldValue(value, field, fieldTypeMap[field]),
39240
39268
  icon: getFieldIcon(field)
39241
39269
  });
@@ -39283,7 +39311,7 @@ var init_DetailPanel = __esm({
39283
39311
  if (typeof field === "string") {
39284
39312
  const value = normalizedData ? getNestedValue(normalizedData, field) : void 0;
39285
39313
  allFields.push({
39286
- label: formatFieldLabel(field),
39314
+ label: labelFor(field),
39287
39315
  value: renderRichFieldValue(value, field, fieldTypeMap[field]),
39288
39316
  icon: getFieldIcon(field)
39289
39317
  });
@@ -51686,11 +51714,9 @@ function OrbPreview({
51686
51714
  }, [parsedSchema]);
51687
51715
  const initialPageMatch = React91.useMemo(() => {
51688
51716
  if (!initialPagePath) return void 0;
51689
- for (const { page } of pages) {
51690
- const params = page.path ? providers.matchPath(page.path, initialPagePath) : null;
51691
- if (params !== null) return { name: page.name, params };
51692
- }
51693
- return void 0;
51717
+ const hit = providers.matchPathAmong(pages, initialPagePath, (entry) => entry.page.path);
51718
+ if (!hit) return void 0;
51719
+ return { name: hit.candidate.page.name, params: hit.params };
51694
51720
  }, [pages, initialPagePath]);
51695
51721
  const initialPageName = initialPageMatch?.name;
51696
51722
  const [currentPage, setCurrentPage] = React91.useState(initialPageName);
@@ -51704,16 +51730,9 @@ function OrbPreview({
51704
51730
  }
51705
51731
  }, [initialPagePath, initialPageName, initialPageMatch]);
51706
51732
  const handleNavigate = React91.useCallback((path) => {
51707
- let match;
51708
- let params = {};
51709
- for (const entry of pages) {
51710
- const m = entry.page.path ? providers.matchPath(entry.page.path, path) : null;
51711
- if (m !== null) {
51712
- match = entry;
51713
- params = m;
51714
- break;
51715
- }
51716
- }
51733
+ const hit = providers.matchPathAmong(pages, path, (entry) => entry.page.path);
51734
+ const match = hit?.candidate;
51735
+ const params = hit?.params ?? {};
51717
51736
  navLog.debug("handleNavigate", () => ({
51718
51737
  path,
51719
51738
  matched: match?.page.name ?? null,
package/dist/avl/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import * as React91 from 'react';
3
3
  import React91__default, { createContext, useState, useMemo, useRef, useEffect, useContext, useCallback, Suspense, useLayoutEffect, Profiler, useReducer, useSyncExternalStore, lazy, useId } from 'react';
4
- import { getAllPages, matchPath, OrbitalProvider, EventBusContext, useTraitScopeChain, ServerBridgeProvider, VerificationProvider, EntitySchemaProvider, OrbitalThemeProvider, useServerBridge, useEntitySchema, useEntitySchemaOptional, TraitScopeProvider, useCurrentPagePath, useGameAudioContextOptional } from '@almadar/ui/providers';
4
+ import { getAllPages, matchPathAmong, OrbitalProvider, EventBusContext, useTraitScopeChain, ServerBridgeProvider, VerificationProvider, EntitySchemaProvider, OrbitalThemeProvider, useServerBridge, useEntitySchema, useEntitySchemaOptional, TraitScopeProvider, useCurrentPagePath, useGameAudioContextOptional } from '@almadar/ui/providers';
5
5
  import { createLogger, setNamespaceLevel, isLogLevelEnabled } from '@almadar/logger';
6
6
  import ELK from 'elkjs/lib/elk.bundled.js';
7
7
  import { MarkerType, useReactFlow, Handle, Position, getBezierPath, EdgeLabelRenderer, useNodeId, ReactFlowProvider, BaseEdge, useNodesState, useEdgesState, ReactFlow, Controls, Background, BackgroundVariant } from '@xyflow/react';
@@ -25505,13 +25505,13 @@ function DataGrid({
25505
25505
  }
25506
25506
  ),
25507
25507
  /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "flex-1 min-w-0", children: [
25508
- titleValue !== void 0 && titleValue !== null && /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
25508
+ titleValue !== void 0 && titleValue !== null && /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center min-w-0", children: [
25509
25509
  titleField?.icon && renderIconInput(titleField.icon, { size: "sm", className: "text-primary flex-shrink-0" }),
25510
25510
  /* @__PURE__ */ jsx(
25511
25511
  Typography,
25512
25512
  {
25513
25513
  variant: titleField?.variant === "h3" ? "h3" : "h4",
25514
- className: "font-semibold truncate",
25514
+ className: "font-semibold truncate min-w-0",
25515
25515
  children: String(titleValue)
25516
25516
  }
25517
25517
  )
@@ -25569,7 +25569,7 @@ function DataGrid({
25569
25569
  )
25570
25570
  ] }, field.name);
25571
25571
  }) }) }),
25572
- primaryActions.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 py-3 mt-auto border-t border-border", children: /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-end", children: [
25572
+ primaryActions.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 py-3 mt-auto border-t border-border", children: /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-end flex-wrap", children: [
25573
25573
  (maxInlineActions != null ? primaryActions.slice(0, maxInlineActions) : primaryActions).map((action, idx) => /* @__PURE__ */ jsxs(
25574
25574
  Button,
25575
25575
  {
@@ -30582,7 +30582,7 @@ function TableView({
30582
30582
  col.key
30583
30583
  );
30584
30584
  }),
30585
- hasActions && /* @__PURE__ */ jsx(Box, { "aria-hidden": true })
30585
+ hasActions && /* @__PURE__ */ jsx(Box, { "aria-hidden": true, className: "sticky right-0 bg-[var(--color-surface-subtle)]" })
30586
30586
  ]
30587
30587
  }
30588
30588
  );
@@ -30626,41 +30626,54 @@ function TableView({
30626
30626
  }
30627
30627
  return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx("span", { className: "truncate", children: formatCell(raw, col.format) }) }, col.key);
30628
30628
  }),
30629
- itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "justify-end flex-shrink-0 opacity-60 group-hover:opacity-100 transition-opacity", children: [
30630
- (maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions).map((action, i) => /* @__PURE__ */ jsxs(
30631
- Button,
30632
- {
30633
- variant: action.variant ?? "ghost",
30634
- size: "sm",
30635
- onClick: handleActionClick(action, row),
30636
- "data-testid": `action-${action.event}`,
30637
- "data-row-id": String(row.id),
30638
- className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
30639
- children: [
30640
- action.icon && renderIconInput3(action.icon, { size: "xs", className: "mr-1" }),
30641
- action.label
30642
- ]
30643
- },
30644
- i
30645
- )),
30646
- maxInlineActions != null && itemActions.length > maxInlineActions && /* @__PURE__ */ jsx(
30647
- Menu,
30648
- {
30649
- position: "bottom-end",
30650
- trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
30651
- items: itemActions.slice(maxInlineActions).map((action) => ({
30652
- label: action.label,
30653
- icon: action.icon,
30654
- event: action.event,
30655
- variant: action.variant === "danger" ? "danger" : "default",
30656
- onClick: () => eventBus.emit(`UI:${action.event}`, {
30657
- id: row.id,
30658
- row
30659
- })
30660
- }))
30661
- }
30662
- )
30663
- ] })
30629
+ itemActions && itemActions.length > 0 && /* @__PURE__ */ jsxs(
30630
+ HStack,
30631
+ {
30632
+ gap: "xs",
30633
+ className: cn(
30634
+ // Pinned: the fixed column tracks routinely overflow the caller's
30635
+ // scroll container, which used to leave the actions off-screen.
30636
+ // Opaque so scrolled cells pass underneath it.
30637
+ "justify-end flex-shrink-0 sticky right-0 z-[1] transition-colors",
30638
+ lk.striped && index % 2 === 1 ? "bg-[var(--color-surface-subtle)]" : "bg-[var(--color-card)] group-hover:bg-[var(--color-surface-subtle)]"
30639
+ ),
30640
+ children: [
30641
+ (maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions).map((action, i) => /* @__PURE__ */ jsxs(
30642
+ Button,
30643
+ {
30644
+ variant: action.variant ?? "ghost",
30645
+ size: "sm",
30646
+ onClick: handleActionClick(action, row),
30647
+ "data-testid": `action-${action.event}`,
30648
+ "data-row-id": String(row.id),
30649
+ className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
30650
+ children: [
30651
+ action.icon && renderIconInput3(action.icon, { size: "xs", className: "mr-1" }),
30652
+ action.label
30653
+ ]
30654
+ },
30655
+ i
30656
+ )),
30657
+ maxInlineActions != null && itemActions.length > maxInlineActions && /* @__PURE__ */ jsx(
30658
+ Menu,
30659
+ {
30660
+ position: "bottom-end",
30661
+ trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
30662
+ items: itemActions.slice(maxInlineActions).map((action) => ({
30663
+ label: action.label,
30664
+ icon: action.icon,
30665
+ event: action.event,
30666
+ variant: action.variant === "danger" ? "danger" : "default",
30667
+ onClick: () => eventBus.emit(`UI:${action.event}`, {
30668
+ id: row.id,
30669
+ row
30670
+ })
30671
+ }))
30672
+ }
30673
+ )
30674
+ ]
30675
+ }
30676
+ )
30664
30677
  ]
30665
30678
  }
30666
30679
  );
@@ -38986,6 +38999,16 @@ function normalizeFieldDefs(fields) {
38986
38999
  return String(f3);
38987
39000
  });
38988
39001
  }
39002
+ function buildFieldLabelMap(fields) {
39003
+ const map = {};
39004
+ if (!fields) return map;
39005
+ for (const f3 of fields) {
39006
+ if (typeof f3 === "object" && "key" in f3 && f3.header !== void 0 && f3.header !== "") {
39007
+ map[f3.key] = f3.header;
39008
+ }
39009
+ }
39010
+ return map;
39011
+ }
38989
39012
  function buildFieldTypeMap(fields) {
38990
39013
  const map = {};
38991
39014
  if (!fields) return map;
@@ -39037,6 +39060,8 @@ var init_DetailPanel = __esm({
39037
39060
  };
39038
39061
  const effectiveFieldNames = isFieldDefArray(propFields) ? normalizeFieldDefs(propFields) : fieldNames;
39039
39062
  const fieldTypeMap = isFieldDefArray(propFields) ? buildFieldTypeMap(propFields) : {};
39063
+ const fieldLabelMap = isFieldDefArray(propFields) ? buildFieldLabelMap(propFields) : {};
39064
+ const labelFor = (field) => fieldLabelMap[field] ?? formatFieldLabel(field);
39040
39065
  const handleActionClick = useCallback(
39041
39066
  (action, data2) => {
39042
39067
  if (action.navigatesTo) {
@@ -39072,7 +39097,7 @@ var init_DetailPanel = __esm({
39072
39097
  if (typeof field === "string") {
39073
39098
  const value = getNestedValue(normalizedData, field);
39074
39099
  return {
39075
- label: formatFieldLabel(field),
39100
+ label: labelFor(field),
39076
39101
  value: formatFieldValue(value, field),
39077
39102
  icon: getFieldIcon(field)
39078
39103
  };
@@ -39083,7 +39108,10 @@ var init_DetailPanel = __esm({
39083
39108
  }
39084
39109
  if (normalizedData && effectiveFieldNames) {
39085
39110
  const primaryField = effectiveFieldNames[0];
39086
- if (!title && primaryField && normalizedData[primaryField]) {
39111
+ const titleDerivedFromPrimary = Boolean(
39112
+ !title && primaryField && normalizedData[primaryField]
39113
+ );
39114
+ if (titleDerivedFromPrimary) {
39087
39115
  title = String(normalizedData[primaryField]);
39088
39116
  }
39089
39117
  const statusFields = effectiveFieldNames.filter(
@@ -39102,16 +39130,16 @@ var init_DetailPanel = __esm({
39102
39130
  (f3) => f3.toLowerCase().includes("description") || f3.toLowerCase().includes("note")
39103
39131
  );
39104
39132
  const otherFields = effectiveFieldNames.filter(
39105
- (f3) => f3 !== primaryField && !statusFields.includes(f3) && !progressFields.includes(f3) && !metricFields.includes(f3) && !dateFields.includes(f3) && !descriptionFields.includes(f3)
39133
+ (f3) => (!titleDerivedFromPrimary || f3 !== primaryField) && !statusFields.includes(f3) && !progressFields.includes(f3) && !metricFields.includes(f3) && !dateFields.includes(f3) && !descriptionFields.includes(f3)
39106
39134
  );
39107
39135
  sections = [];
39108
39136
  if (statusFields.length > 0 || otherFields.length > 0) {
39109
39137
  const overviewFields = [];
39110
- [...statusFields, ...otherFields.slice(0, 3)].forEach((field) => {
39138
+ [...statusFields, ...otherFields].forEach((field) => {
39111
39139
  const value = getNestedValue(normalizedData, field);
39112
39140
  if (value !== void 0 && value !== null) {
39113
39141
  overviewFields.push({
39114
- label: formatFieldLabel(field),
39142
+ label: labelFor(field),
39115
39143
  value: renderRichFieldValue(value, field, fieldTypeMap[field]),
39116
39144
  icon: getFieldIcon(field)
39117
39145
  });
@@ -39127,7 +39155,7 @@ var init_DetailPanel = __esm({
39127
39155
  const value = getNestedValue(normalizedData, field);
39128
39156
  if (value !== void 0 && value !== null) {
39129
39157
  metricsFields.push({
39130
- label: formatFieldLabel(field),
39158
+ label: labelFor(field),
39131
39159
  value: renderRichFieldValue(value, field, fieldTypeMap[field]),
39132
39160
  icon: getFieldIcon(field)
39133
39161
  });
@@ -39143,7 +39171,7 @@ var init_DetailPanel = __esm({
39143
39171
  const value = getNestedValue(normalizedData, field);
39144
39172
  if (value !== void 0 && value !== null) {
39145
39173
  timelineFields.push({
39146
- label: formatFieldLabel(field),
39174
+ label: labelFor(field),
39147
39175
  value: renderRichFieldValue(value, field, fieldTypeMap[field]),
39148
39176
  icon: getFieldIcon(field)
39149
39177
  });
@@ -39159,7 +39187,7 @@ var init_DetailPanel = __esm({
39159
39187
  const value = getNestedValue(normalizedData, field);
39160
39188
  if (value !== void 0 && value !== null) {
39161
39189
  descFields.push({
39162
- label: formatFieldLabel(field),
39190
+ label: labelFor(field),
39163
39191
  value: renderRichFieldValue(value, field, fieldTypeMap[field]),
39164
39192
  icon: getFieldIcon(field)
39165
39193
  });
@@ -39207,7 +39235,7 @@ var init_DetailPanel = __esm({
39207
39235
  if (typeof field === "string") {
39208
39236
  const value = normalizedData ? getNestedValue(normalizedData, field) : void 0;
39209
39237
  allFields.push({
39210
- label: formatFieldLabel(field),
39238
+ label: labelFor(field),
39211
39239
  value: renderRichFieldValue(value, field, fieldTypeMap[field]),
39212
39240
  icon: getFieldIcon(field)
39213
39241
  });
@@ -51610,11 +51638,9 @@ function OrbPreview({
51610
51638
  }, [parsedSchema]);
51611
51639
  const initialPageMatch = useMemo(() => {
51612
51640
  if (!initialPagePath) return void 0;
51613
- for (const { page } of pages) {
51614
- const params = page.path ? matchPath(page.path, initialPagePath) : null;
51615
- if (params !== null) return { name: page.name, params };
51616
- }
51617
- return void 0;
51641
+ const hit = matchPathAmong(pages, initialPagePath, (entry) => entry.page.path);
51642
+ if (!hit) return void 0;
51643
+ return { name: hit.candidate.page.name, params: hit.params };
51618
51644
  }, [pages, initialPagePath]);
51619
51645
  const initialPageName = initialPageMatch?.name;
51620
51646
  const [currentPage, setCurrentPage] = useState(initialPageName);
@@ -51628,16 +51654,9 @@ function OrbPreview({
51628
51654
  }
51629
51655
  }, [initialPagePath, initialPageName, initialPageMatch]);
51630
51656
  const handleNavigate = useCallback((path) => {
51631
- let match;
51632
- let params = {};
51633
- for (const entry of pages) {
51634
- const m = entry.page.path ? matchPath(entry.page.path, path) : null;
51635
- if (m !== null) {
51636
- match = entry;
51637
- params = m;
51638
- break;
51639
- }
51640
- }
51657
+ const hit = matchPathAmong(pages, path, (entry) => entry.page.path);
51658
+ const match = hit?.candidate;
51659
+ const params = hit?.params ?? {};
51641
51660
  navLog.debug("handleNavigate", () => ({
51642
51661
  path,
51643
51662
  matched: match?.page.name ?? null,