@almadar/ui 5.133.0 → 5.135.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.
@@ -186,6 +186,7 @@ function collectDrawnItems(nodes) {
186
186
  case "draw-sprite":
187
187
  case "draw-shape":
188
188
  case "draw-text":
189
+ case "draw-group":
189
190
  if (isValidScenePos(n.position)) out.push({ pos: n.position, id: n.id });
190
191
  break;
191
192
  case "draw-sprite-layer":
@@ -794,6 +795,13 @@ function ModelLoader({
794
795
  }
795
796
  );
796
797
  }
798
+ var mesh3dLog = logger.createLogger("almadar:ui:drawable-3d");
799
+ var warnedUnsupported = /* @__PURE__ */ new Set();
800
+ var warnUnsupported3d = (kind) => {
801
+ if (warnedUnsupported.has(kind)) return;
802
+ warnedUnsupported.add(kind);
803
+ mesh3dLog.warn("unsupported drawable kind on the 3D backend \u2014 skipped", { kind });
804
+ };
797
805
  var CrossOriginTextureLoader = class extends THREE9__namespace.TextureLoader {
798
806
  constructor() {
799
807
  super();
@@ -966,6 +974,10 @@ function Shape3D({ node, projector }) {
966
974
  geometry = /* @__PURE__ */ jsxRuntime.jsx("shapeGeometry", { args: [s] });
967
975
  break;
968
976
  }
977
+ case "path": {
978
+ warnUnsupported3d("draw-shape:path");
979
+ return null;
980
+ }
969
981
  default:
970
982
  return null;
971
983
  }
@@ -1004,6 +1016,9 @@ function Drawable3D({ node, projector }) {
1004
1016
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: node.items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(Shape3D, { node: item, projector }, i)) });
1005
1017
  case "draw-text-layer":
1006
1018
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: node.items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(Text3D, { node: item, projector }, i)) });
1019
+ case "draw-group":
1020
+ warnUnsupported3d("draw-group");
1021
+ return null;
1007
1022
  }
1008
1023
  }
1009
1024
 
@@ -2795,6 +2810,53 @@ var Box = React3__default.default.forwardRef(
2795
2810
  }
2796
2811
  );
2797
2812
  Box.displayName = "Box";
2813
+
2814
+ // lib/format.ts
2815
+ function formatDate(value) {
2816
+ if (!value) return "";
2817
+ const d = new Date(String(value));
2818
+ if (isNaN(d.getTime())) return String(value);
2819
+ return d.toLocaleDateString(void 0, { year: "numeric", month: "short", day: "numeric" });
2820
+ }
2821
+ function formatTime(value) {
2822
+ if (!value) return "";
2823
+ const d = new Date(String(value));
2824
+ if (isNaN(d.getTime())) return String(value);
2825
+ return d.toLocaleTimeString(void 0, { hour: "numeric", minute: "2-digit" });
2826
+ }
2827
+ function formatDateTime(value) {
2828
+ if (!value) return "";
2829
+ const d = new Date(String(value));
2830
+ if (isNaN(d.getTime())) return String(value);
2831
+ return `${formatDate(value)} ${formatTime(value)}`;
2832
+ }
2833
+ function asYesNo(value) {
2834
+ return value === false || value === 0 || String(value) === "false" ? "No" : "Yes";
2835
+ }
2836
+ function formatValue(value, format) {
2837
+ if (value === void 0 || value === null) return "";
2838
+ if (typeof value === "boolean") return asYesNo(value);
2839
+ switch (format) {
2840
+ case "date":
2841
+ return formatDate(value);
2842
+ case "time":
2843
+ return formatTime(value);
2844
+ case "datetime":
2845
+ return formatDateTime(value);
2846
+ case "currency":
2847
+ return typeof value === "number" ? `$${value.toFixed(2)}` : String(value);
2848
+ case "number":
2849
+ return typeof value === "number" ? value.toLocaleString() : String(value);
2850
+ case "percent":
2851
+ return typeof value === "number" ? `${Math.round(value)}%` : String(value);
2852
+ case "boolean":
2853
+ return asYesNo(value);
2854
+ default:
2855
+ return String(value);
2856
+ }
2857
+ }
2858
+
2859
+ // components/core/atoms/Typography.tsx
2798
2860
  var variantStyles = {
2799
2861
  h1: "text-4xl font-bold tracking-tight text-foreground",
2800
2862
  h2: "text-3xl font-bold tracking-tight text-foreground",
@@ -2882,11 +2944,16 @@ var Typography = ({
2882
2944
  id,
2883
2945
  className,
2884
2946
  style,
2947
+ format,
2885
2948
  content,
2886
2949
  children
2887
2950
  }) => {
2888
2951
  const variant = variantProp ?? (level ? `h${level}` : "body1");
2889
2952
  const Component2 = as || defaultElements[variant];
2953
+ let body = children ?? content;
2954
+ if (format !== void 0 && format !== "none" && (typeof body === "string" || typeof body === "number" || body instanceof Date)) {
2955
+ body = formatValue(body, format);
2956
+ }
2890
2957
  return React3__default.default.createElement(
2891
2958
  Component2,
2892
2959
  {
@@ -2903,7 +2970,7 @@ var Typography = ({
2903
2970
  ),
2904
2971
  style
2905
2972
  },
2906
- children ?? content
2973
+ body
2907
2974
  );
2908
2975
  };
2909
2976
  Typography.displayName = "Typography";
@@ -3,7 +3,7 @@ import React__default, { Component, ReactNode, ErrorInfo } from 'react';
3
3
  import { ScenePos, EventEmit, JsonObject, OrbitalSchema } from '@almadar/core';
4
4
  import * as THREE from 'three';
5
5
  import { QuadraticBezierCurve3 } from 'three';
6
- import { D as DrawableNode } from '../../../paintDispatch-BXJgISot.cjs';
6
+ import { D as DrawableNode } from '../../../paintDispatch-Bl2sfRFb.cjs';
7
7
  import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
8
8
  import { I as IsometricTile, a as IsometricUnit, b as IsometricFeature, A as ApplicationLevelData, O as OrbitalLevelData, T as TraitLevelData, c as TransitionLevelData } from '../../../avl-schema-parser-B8Onmfsu.cjs';
9
9
  export { U as UnitAnimationState } from '../../../avl-schema-parser-B8Onmfsu.cjs';
@@ -3,7 +3,7 @@ import React__default, { Component, ReactNode, ErrorInfo } from 'react';
3
3
  import { ScenePos, EventEmit, JsonObject, OrbitalSchema } from '@almadar/core';
4
4
  import * as THREE from 'three';
5
5
  import { QuadraticBezierCurve3 } from 'three';
6
- import { D as DrawableNode } from '../../../paintDispatch-BXJgISot.js';
6
+ import { D as DrawableNode } from '../../../paintDispatch-Bl2sfRFb.js';
7
7
  import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
8
8
  import { I as IsometricTile, a as IsometricUnit, b as IsometricFeature, A as ApplicationLevelData, O as OrbitalLevelData, T as TraitLevelData, c as TransitionLevelData } from '../../../avl-schema-parser-B8Onmfsu.js';
9
9
  export { U as UnitAnimationState } from '../../../avl-schema-parser-B8Onmfsu.js';
@@ -162,6 +162,7 @@ function collectDrawnItems(nodes) {
162
162
  case "draw-sprite":
163
163
  case "draw-shape":
164
164
  case "draw-text":
165
+ case "draw-group":
165
166
  if (isValidScenePos(n.position)) out.push({ pos: n.position, id: n.id });
166
167
  break;
167
168
  case "draw-sprite-layer":
@@ -770,6 +771,13 @@ function ModelLoader({
770
771
  }
771
772
  );
772
773
  }
774
+ var mesh3dLog = createLogger("almadar:ui:drawable-3d");
775
+ var warnedUnsupported = /* @__PURE__ */ new Set();
776
+ var warnUnsupported3d = (kind) => {
777
+ if (warnedUnsupported.has(kind)) return;
778
+ warnedUnsupported.add(kind);
779
+ mesh3dLog.warn("unsupported drawable kind on the 3D backend \u2014 skipped", { kind });
780
+ };
773
781
  var CrossOriginTextureLoader = class extends THREE9.TextureLoader {
774
782
  constructor() {
775
783
  super();
@@ -942,6 +950,10 @@ function Shape3D({ node, projector }) {
942
950
  geometry = /* @__PURE__ */ jsx("shapeGeometry", { args: [s] });
943
951
  break;
944
952
  }
953
+ case "path": {
954
+ warnUnsupported3d("draw-shape:path");
955
+ return null;
956
+ }
945
957
  default:
946
958
  return null;
947
959
  }
@@ -980,6 +992,9 @@ function Drawable3D({ node, projector }) {
980
992
  return /* @__PURE__ */ jsx(Fragment, { children: node.items.map((item, i) => /* @__PURE__ */ jsx(Shape3D, { node: item, projector }, i)) });
981
993
  case "draw-text-layer":
982
994
  return /* @__PURE__ */ jsx(Fragment, { children: node.items.map((item, i) => /* @__PURE__ */ jsx(Text3D, { node: item, projector }, i)) });
995
+ case "draw-group":
996
+ warnUnsupported3d("draw-group");
997
+ return null;
983
998
  }
984
999
  }
985
1000
 
@@ -2771,6 +2786,53 @@ var Box = React3.forwardRef(
2771
2786
  }
2772
2787
  );
2773
2788
  Box.displayName = "Box";
2789
+
2790
+ // lib/format.ts
2791
+ function formatDate(value) {
2792
+ if (!value) return "";
2793
+ const d = new Date(String(value));
2794
+ if (isNaN(d.getTime())) return String(value);
2795
+ return d.toLocaleDateString(void 0, { year: "numeric", month: "short", day: "numeric" });
2796
+ }
2797
+ function formatTime(value) {
2798
+ if (!value) return "";
2799
+ const d = new Date(String(value));
2800
+ if (isNaN(d.getTime())) return String(value);
2801
+ return d.toLocaleTimeString(void 0, { hour: "numeric", minute: "2-digit" });
2802
+ }
2803
+ function formatDateTime(value) {
2804
+ if (!value) return "";
2805
+ const d = new Date(String(value));
2806
+ if (isNaN(d.getTime())) return String(value);
2807
+ return `${formatDate(value)} ${formatTime(value)}`;
2808
+ }
2809
+ function asYesNo(value) {
2810
+ return value === false || value === 0 || String(value) === "false" ? "No" : "Yes";
2811
+ }
2812
+ function formatValue(value, format) {
2813
+ if (value === void 0 || value === null) return "";
2814
+ if (typeof value === "boolean") return asYesNo(value);
2815
+ switch (format) {
2816
+ case "date":
2817
+ return formatDate(value);
2818
+ case "time":
2819
+ return formatTime(value);
2820
+ case "datetime":
2821
+ return formatDateTime(value);
2822
+ case "currency":
2823
+ return typeof value === "number" ? `$${value.toFixed(2)}` : String(value);
2824
+ case "number":
2825
+ return typeof value === "number" ? value.toLocaleString() : String(value);
2826
+ case "percent":
2827
+ return typeof value === "number" ? `${Math.round(value)}%` : String(value);
2828
+ case "boolean":
2829
+ return asYesNo(value);
2830
+ default:
2831
+ return String(value);
2832
+ }
2833
+ }
2834
+
2835
+ // components/core/atoms/Typography.tsx
2774
2836
  var variantStyles = {
2775
2837
  h1: "text-4xl font-bold tracking-tight text-foreground",
2776
2838
  h2: "text-3xl font-bold tracking-tight text-foreground",
@@ -2858,11 +2920,16 @@ var Typography = ({
2858
2920
  id,
2859
2921
  className,
2860
2922
  style,
2923
+ format,
2861
2924
  content,
2862
2925
  children
2863
2926
  }) => {
2864
2927
  const variant = variantProp ?? (level ? `h${level}` : "body1");
2865
2928
  const Component2 = as || defaultElements[variant];
2929
+ let body = children ?? content;
2930
+ if (format !== void 0 && format !== "none" && (typeof body === "string" || typeof body === "number" || body instanceof Date)) {
2931
+ body = formatValue(body, format);
2932
+ }
2866
2933
  return React3.createElement(
2867
2934
  Component2,
2868
2935
  {
@@ -2879,7 +2946,7 @@ var Typography = ({
2879
2946
  ),
2880
2947
  style
2881
2948
  },
2882
- children ?? content
2949
+ body
2883
2950
  );
2884
2951
  };
2885
2952
  Typography.displayName = "Typography";
@@ -790,6 +790,83 @@ function clearVerification() {
790
790
  }
791
791
  exposeOnWindow();
792
792
 
793
+ // lib/format.ts
794
+ function humanizeFieldName(name) {
795
+ return name.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/[_-]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()).replace(/\b([A-Z])([A-Z]+)\b/g, (_, first, rest) => first + rest.toLowerCase()).trim();
796
+ }
797
+ function humanizeEnumValue(value) {
798
+ return /^[a-z0-9]+(?:[_-][a-z0-9]+)+$/.test(value) ? humanizeFieldName(value) : value;
799
+ }
800
+ function formatDate(value) {
801
+ if (!value) return "";
802
+ const d = new Date(String(value));
803
+ if (isNaN(d.getTime())) return String(value);
804
+ return d.toLocaleDateString(void 0, { year: "numeric", month: "short", day: "numeric" });
805
+ }
806
+ function formatTime(value) {
807
+ if (!value) return "";
808
+ const d = new Date(String(value));
809
+ if (isNaN(d.getTime())) return String(value);
810
+ return d.toLocaleTimeString(void 0, { hour: "numeric", minute: "2-digit" });
811
+ }
812
+ function formatDateTime(value) {
813
+ if (!value) return "";
814
+ const d = new Date(String(value));
815
+ if (isNaN(d.getTime())) return String(value);
816
+ return `${formatDate(value)} ${formatTime(value)}`;
817
+ }
818
+ function asYesNo(value) {
819
+ return value === false || value === 0 || String(value) === "false" ? "No" : "Yes";
820
+ }
821
+ function formatValue(value, format) {
822
+ if (value === void 0 || value === null) return "";
823
+ if (typeof value === "boolean") return asYesNo(value);
824
+ switch (format) {
825
+ case "date":
826
+ return formatDate(value);
827
+ case "time":
828
+ return formatTime(value);
829
+ case "datetime":
830
+ return formatDateTime(value);
831
+ case "currency":
832
+ return typeof value === "number" ? `$${value.toFixed(2)}` : String(value);
833
+ case "number":
834
+ return typeof value === "number" ? value.toLocaleString() : String(value);
835
+ case "percent":
836
+ return typeof value === "number" ? `${Math.round(value)}%` : String(value);
837
+ case "boolean":
838
+ return asYesNo(value);
839
+ default:
840
+ return String(value);
841
+ }
842
+ }
843
+ function compareCellValues(a, b) {
844
+ const aEmpty = a === null || a === void 0 || a === "";
845
+ const bEmpty = b === null || b === void 0 || b === "";
846
+ if (aEmpty || bEmpty) return aEmpty && bEmpty ? 0 : aEmpty ? 1 : -1;
847
+ if (typeof a === "number" && typeof b === "number") return a - b;
848
+ if (typeof a === "boolean" && typeof b === "boolean") return Number(a) - Number(b);
849
+ const aNum = Number(a);
850
+ const bNum = Number(b);
851
+ if (Number.isFinite(aNum) && Number.isFinite(bNum)) return aNum - bNum;
852
+ const aTime = dateLikeTime(a);
853
+ const bTime = dateLikeTime(b);
854
+ if (aTime !== null && bTime !== null) return aTime - bTime;
855
+ return String(a).localeCompare(String(b));
856
+ }
857
+ function dateLikeTime(value) {
858
+ if (value instanceof Date) return value.getTime();
859
+ const text = String(value);
860
+ if (!/\d/.test(text) || !/[-/:T]/.test(text)) return null;
861
+ const time = Date.parse(text);
862
+ return Number.isNaN(time) ? null : time;
863
+ }
864
+ function sortRows(rows, field, direction = "asc") {
865
+ if (!field) return rows;
866
+ const dir = direction === "desc" ? -1 : 1;
867
+ return [...rows].sort((a, b) => dir * compareCellValues(a?.[field], b?.[field]));
868
+ }
869
+
793
870
  // lib/getNestedValue.ts
794
871
  function getNestedValue(obj, path) {
795
872
  if (obj === null || obj === void 0 || !path) {
@@ -1863,6 +1940,7 @@ exports.clearTicks = clearTicks;
1863
1940
  exports.clearTraits = clearTraits;
1864
1941
  exports.clearVerification = clearVerification;
1865
1942
  exports.cn = cn;
1943
+ exports.compareCellValues = compareCellValues;
1866
1944
  exports.computeJazariLayout = computeJazariLayout;
1867
1945
  exports.debug = debug;
1868
1946
  exports.debugCollision = debugCollision;
@@ -1879,8 +1957,12 @@ exports.debugWarn = debugWarn;
1879
1957
  exports.eightPointedStarPath = eightPointedStarPath;
1880
1958
  exports.extractOutputsFromTransitions = extractOutputsFromTransitions;
1881
1959
  exports.extractStateMachine = extractStateMachine;
1960
+ exports.formatDate = formatDate;
1961
+ exports.formatDateTime = formatDateTime;
1882
1962
  exports.formatGuard = formatGuard;
1883
1963
  exports.formatNestedFieldLabel = formatNestedFieldLabel;
1964
+ exports.formatTime = formatTime;
1965
+ exports.formatValue = formatValue;
1884
1966
  exports.gearTeethPath = gearTeethPath;
1885
1967
  exports.getAllChecks = getAllChecks;
1886
1968
  exports.getAllTicks = getAllTicks;
@@ -1905,6 +1987,8 @@ exports.getTrait = getTrait;
1905
1987
  exports.getTraitSnapshots = getTraitSnapshots;
1906
1988
  exports.getTransitions = getTransitions;
1907
1989
  exports.getTransitionsForTrait = getTransitionsForTrait;
1990
+ exports.humanizeEnumValue = humanizeEnumValue;
1991
+ exports.humanizeFieldName = humanizeFieldName;
1908
1992
  exports.initDebugShortcut = initDebugShortcut;
1909
1993
  exports.isDebugEnabled = isDebugEnabled;
1910
1994
  exports.lockIconPath = lockIconPath;
@@ -1931,6 +2015,7 @@ exports.renderStateMachineToSvg = renderStateMachineToSvg;
1931
2015
  exports.setDebugEnabled = setDebugEnabled;
1932
2016
  exports.setEntityProvider = setEntityProvider;
1933
2017
  exports.setTickActive = setTickActive;
2018
+ exports.sortRows = sortRows;
1934
2019
  exports.subscribeToDebugEvents = subscribeToDebugEvents;
1935
2020
  exports.subscribeToGuardChanges = subscribeToGuardChanges;
1936
2021
  exports.subscribeToTickChanges = subscribeToTickChanges;
@@ -1,7 +1,7 @@
1
- export { C as ContentSegment, D as DEFAULT_CONFIG, a as DomEntityBox, b as DomLayoutData, c as DomOutputsBox, d as DomStateNode, e as DomTransitionLabel, f as DomTransitionPath, E as EntityDefinition, R as RenderOptions, S as StateDefinition, g as StateMachineDefinition, T as TraitSnapshotGetter, h as TransitionDefinition, V as VisualizerConfig, i as bindCanvasCapture, j as bindEventBus, k as bindLastDrawables, l as bindTraitStateGetter, m as clearVerification, n as cn, o as extractOutputsFromTransitions, p as extractStateMachine, q as formatGuard, r as getAllChecks, s as getBridgeHealth, t as getEffectSummary, u as getSnapshot, v as getSummary, w as getTraitSnapshots, x as getTransitions, y as getTransitionsForTrait, z as parseContentSegments, A as parseMarkdownWithCodeBlocks, B as recordServerResponse, F as recordTransition, G as registerCheck, H as registerTraitSnapshot, I as renderStateMachineToDomData, J as renderStateMachineToSvg, K as subscribeToVerification, L as updateAssetStatus, M as updateBridgeHealth, N as updateCheck, O as waitForTransition } from '../cn-D3H9UzCW.cjs';
1
+ export { C as ContentSegment, D as DEFAULT_CONFIG, a as DomEntityBox, b as DomLayoutData, c as DomOutputsBox, d as DomStateNode, e as DomTransitionLabel, f as DomTransitionPath, E as EntityDefinition, R as RenderOptions, S as StateDefinition, g as StateMachineDefinition, T as TraitSnapshotGetter, h as TransitionDefinition, V as VisualizerConfig, i as bindCanvasCapture, j as bindEventBus, k as bindLastDrawables, l as bindTraitStateGetter, m as clearVerification, n as cn, o as extractOutputsFromTransitions, p as extractStateMachine, q as formatGuard, r as getAllChecks, s as getBridgeHealth, t as getEffectSummary, u as getSnapshot, v as getSummary, w as getTraitSnapshots, x as getTransitions, y as getTransitionsForTrait, z as parseContentSegments, A as parseMarkdownWithCodeBlocks, B as recordServerResponse, F as recordTransition, G as registerCheck, H as registerTraitSnapshot, I as renderStateMachineToDomData, J as renderStateMachineToSvg, K as subscribeToVerification, L as updateAssetStatus, M as updateBridgeHealth, N as updateCheck, O as waitForTransition } from '../cn-B8GXqrtp.cjs';
2
2
  import { FieldValue, EntityRow, EventPayload } from '@almadar/core';
3
3
  export { AssetLoadStatus, BridgeHealth, CheckStatus, EffectTrace, EventLogEntry, OrbitalVerificationAPI, ServerResponseTrace, TraitStateSnapshot, TransitionTrace, VerificationCheck, VerificationSnapshot, VerificationSummary } from '@almadar/core';
4
- import '../paintDispatch-BXJgISot.cjs';
4
+ import '../paintDispatch-Bl2sfRFb.cjs';
5
5
  import 'clsx';
6
6
 
7
7
  /**
@@ -283,6 +283,53 @@ declare function onDebugToggle(listener: DebugToggleListener): () => void;
283
283
  */
284
284
  declare function initDebugShortcut(): () => void;
285
285
 
286
+ /**
287
+ * Shared field-name + value formatting — the single owner of the humanize and
288
+ * format vocabulary previously duplicated across DataTable, DataGrid, CardGrid,
289
+ * DataList, TableView, DetailPanel, List, and UISlotRenderer.
290
+ */
291
+
292
+ type ValueFormat = 'none' | 'date' | 'time' | 'datetime' | 'number' | 'currency' | 'percent' | 'boolean';
293
+ /**
294
+ * Convert a camelCase, PascalCase, ALLCAPS, snake_case, or kebab-case field
295
+ * name to a human-readable header: "estimatedDelivery" → "Estimated Delivery",
296
+ * "PURCHASEPRICE" → "Purchase Price", "is_active" → "Is Active".
297
+ */
298
+ declare function humanizeFieldName(name: string): string;
299
+ /**
300
+ * Badge/label-position enum values: a lowercase token chain joined by `_` or
301
+ * `-` renders as spaced Title Case ("checked_in" → "Checked In"). Any other
302
+ * shape (ids, emails, mixed case, single words) passes through unchanged —
303
+ * a stated formatting contract, applied only where call sites opt in.
304
+ */
305
+ declare function humanizeEnumValue(value: string): string;
306
+ declare function formatDate(value: FieldValue | undefined): string;
307
+ declare function formatTime(value: FieldValue | undefined): string;
308
+ declare function formatDateTime(value: FieldValue | undefined): string;
309
+ /**
310
+ * Format a field value for display. Booleans always render Yes/No regardless
311
+ * of the declared format (a raw `true`/`false` cell is never intended output).
312
+ */
313
+ declare function formatValue(value: FieldValue | undefined, format?: string): string;
314
+ /** Sort direction for {@link sortRows}. */
315
+ type SortDirection = 'asc' | 'desc';
316
+ /**
317
+ * Order two cell values by their own type, never by what the field is called.
318
+ *
319
+ * Numbers compare numerically, date-like strings chronologically, everything
320
+ * else by locale string order. `null`/`undefined` sort last in both directions
321
+ * so empty cells never displace real data at the top of a list.
322
+ */
323
+ declare function compareCellValues(a: FieldValue | undefined, b: FieldValue | undefined): number;
324
+ /**
325
+ * Return a new array ordered by `field`. Non-mutating, and a no-op without a
326
+ * field so callers can pass the prop through unconditionally.
327
+ *
328
+ * NOTE: this orders only the rows already fetched. A collection larger than its
329
+ * `limit` still needs ordering at the data layer — see `L-NO-COLLECTION-ORDERING`.
330
+ */
331
+ declare function sortRows<T extends Record<string, FieldValue | undefined>>(rows: readonly T[], field?: string, direction?: SortDirection): readonly T[];
332
+
286
333
  /**
287
334
  * Get Nested Value Utility
288
335
  *
@@ -502,4 +549,4 @@ declare function eightPointedStarPath(cx: number, cy: number, outerR: number, in
502
549
  */
503
550
  declare function arrowheadPath(size: number): string;
504
551
 
505
- export { ApiError, type DebugEvent, type DebugEventType, type EntitySnapshot, type EntityState, type GuardContext, type GuardEvaluation, JAZARI_COLORS, type JazariArmLayout, type JazariEffectInfo, type JazariGearLayout, type JazariGuardInfo, type JazariLayout, type LayoutInput, type LayoutState, type LayoutTransition, type PersistentEntityInfo, type RuntimeEntity, type TickExecution, type TraitDebugInfo, type TraitGuard, type TraitTransition, apiClient, arrowheadPath, brainIconPath, clearDebugEvents, clearEntityProvider, clearGuardHistory, clearTicks, clearTraits, computeJazariLayout, debug, debugCollision, debugError, debugGameState, debugGroup, debugGroupEnd, debugInput, debugPhysics, debugTable, debugTime, debugTimeEnd, debugWarn, eightPointedStarPath, formatNestedFieldLabel, gearTeethPath, getAllTicks, getAllTraits, getDebugEvents, getEntitiesByType, getEntityById, getEntitySnapshot, getEventsBySource, getEventsByType, getGuardEvaluationsForTrait, getGuardHistory, getNestedValue, getRecentEvents, getRecentGuardEvaluations, getTick, getTrait, initDebugShortcut, isDebugEnabled, lockIconPath, logDebugEvent, logEffectExecuted, logError, logEventFired, logInfo, logStateChange, logWarning, onDebugToggle, pipeIconPath, recordGuardEvaluation, registerTick, registerTrait, setDebugEnabled, setEntityProvider, setTickActive, subscribeToDebugEvents, subscribeToGuardChanges, subscribeToTickChanges, subscribeToTraitChanges, toggleDebug, unregisterTick, unregisterTrait, updateGuardResult, updateTickExecution, updateTraitState };
552
+ export { ApiError, type DebugEvent, type DebugEventType, type EntitySnapshot, type EntityState, type GuardContext, type GuardEvaluation, JAZARI_COLORS, type JazariArmLayout, type JazariEffectInfo, type JazariGearLayout, type JazariGuardInfo, type JazariLayout, type LayoutInput, type LayoutState, type LayoutTransition, type PersistentEntityInfo, type RuntimeEntity, type SortDirection, type TickExecution, type TraitDebugInfo, type TraitGuard, type TraitTransition, type ValueFormat, apiClient, arrowheadPath, brainIconPath, clearDebugEvents, clearEntityProvider, clearGuardHistory, clearTicks, clearTraits, compareCellValues, computeJazariLayout, debug, debugCollision, debugError, debugGameState, debugGroup, debugGroupEnd, debugInput, debugPhysics, debugTable, debugTime, debugTimeEnd, debugWarn, eightPointedStarPath, formatDate, formatDateTime, formatNestedFieldLabel, formatTime, formatValue, gearTeethPath, getAllTicks, getAllTraits, getDebugEvents, getEntitiesByType, getEntityById, getEntitySnapshot, getEventsBySource, getEventsByType, getGuardEvaluationsForTrait, getGuardHistory, getNestedValue, getRecentEvents, getRecentGuardEvaluations, getTick, getTrait, humanizeEnumValue, humanizeFieldName, initDebugShortcut, isDebugEnabled, lockIconPath, logDebugEvent, logEffectExecuted, logError, logEventFired, logInfo, logStateChange, logWarning, onDebugToggle, pipeIconPath, recordGuardEvaluation, registerTick, registerTrait, setDebugEnabled, setEntityProvider, setTickActive, sortRows, subscribeToDebugEvents, subscribeToGuardChanges, subscribeToTickChanges, subscribeToTraitChanges, toggleDebug, unregisterTick, unregisterTrait, updateGuardResult, updateTickExecution, updateTraitState };
@@ -1,7 +1,7 @@
1
- export { C as ContentSegment, D as DEFAULT_CONFIG, a as DomEntityBox, b as DomLayoutData, c as DomOutputsBox, d as DomStateNode, e as DomTransitionLabel, f as DomTransitionPath, E as EntityDefinition, R as RenderOptions, S as StateDefinition, g as StateMachineDefinition, T as TraitSnapshotGetter, h as TransitionDefinition, V as VisualizerConfig, i as bindCanvasCapture, j as bindEventBus, k as bindLastDrawables, l as bindTraitStateGetter, m as clearVerification, n as cn, o as extractOutputsFromTransitions, p as extractStateMachine, q as formatGuard, r as getAllChecks, s as getBridgeHealth, t as getEffectSummary, u as getSnapshot, v as getSummary, w as getTraitSnapshots, x as getTransitions, y as getTransitionsForTrait, z as parseContentSegments, A as parseMarkdownWithCodeBlocks, B as recordServerResponse, F as recordTransition, G as registerCheck, H as registerTraitSnapshot, I as renderStateMachineToDomData, J as renderStateMachineToSvg, K as subscribeToVerification, L as updateAssetStatus, M as updateBridgeHealth, N as updateCheck, O as waitForTransition } from '../cn-Dm0VrLRG.js';
1
+ export { C as ContentSegment, D as DEFAULT_CONFIG, a as DomEntityBox, b as DomLayoutData, c as DomOutputsBox, d as DomStateNode, e as DomTransitionLabel, f as DomTransitionPath, E as EntityDefinition, R as RenderOptions, S as StateDefinition, g as StateMachineDefinition, T as TraitSnapshotGetter, h as TransitionDefinition, V as VisualizerConfig, i as bindCanvasCapture, j as bindEventBus, k as bindLastDrawables, l as bindTraitStateGetter, m as clearVerification, n as cn, o as extractOutputsFromTransitions, p as extractStateMachine, q as formatGuard, r as getAllChecks, s as getBridgeHealth, t as getEffectSummary, u as getSnapshot, v as getSummary, w as getTraitSnapshots, x as getTransitions, y as getTransitionsForTrait, z as parseContentSegments, A as parseMarkdownWithCodeBlocks, B as recordServerResponse, F as recordTransition, G as registerCheck, H as registerTraitSnapshot, I as renderStateMachineToDomData, J as renderStateMachineToSvg, K as subscribeToVerification, L as updateAssetStatus, M as updateBridgeHealth, N as updateCheck, O as waitForTransition } from '../cn-CZq0uJLA.js';
2
2
  import { FieldValue, EntityRow, EventPayload } from '@almadar/core';
3
3
  export { AssetLoadStatus, BridgeHealth, CheckStatus, EffectTrace, EventLogEntry, OrbitalVerificationAPI, ServerResponseTrace, TraitStateSnapshot, TransitionTrace, VerificationCheck, VerificationSnapshot, VerificationSummary } from '@almadar/core';
4
- import '../paintDispatch-BXJgISot.js';
4
+ import '../paintDispatch-Bl2sfRFb.js';
5
5
  import 'clsx';
6
6
 
7
7
  /**
@@ -283,6 +283,53 @@ declare function onDebugToggle(listener: DebugToggleListener): () => void;
283
283
  */
284
284
  declare function initDebugShortcut(): () => void;
285
285
 
286
+ /**
287
+ * Shared field-name + value formatting — the single owner of the humanize and
288
+ * format vocabulary previously duplicated across DataTable, DataGrid, CardGrid,
289
+ * DataList, TableView, DetailPanel, List, and UISlotRenderer.
290
+ */
291
+
292
+ type ValueFormat = 'none' | 'date' | 'time' | 'datetime' | 'number' | 'currency' | 'percent' | 'boolean';
293
+ /**
294
+ * Convert a camelCase, PascalCase, ALLCAPS, snake_case, or kebab-case field
295
+ * name to a human-readable header: "estimatedDelivery" → "Estimated Delivery",
296
+ * "PURCHASEPRICE" → "Purchase Price", "is_active" → "Is Active".
297
+ */
298
+ declare function humanizeFieldName(name: string): string;
299
+ /**
300
+ * Badge/label-position enum values: a lowercase token chain joined by `_` or
301
+ * `-` renders as spaced Title Case ("checked_in" → "Checked In"). Any other
302
+ * shape (ids, emails, mixed case, single words) passes through unchanged —
303
+ * a stated formatting contract, applied only where call sites opt in.
304
+ */
305
+ declare function humanizeEnumValue(value: string): string;
306
+ declare function formatDate(value: FieldValue | undefined): string;
307
+ declare function formatTime(value: FieldValue | undefined): string;
308
+ declare function formatDateTime(value: FieldValue | undefined): string;
309
+ /**
310
+ * Format a field value for display. Booleans always render Yes/No regardless
311
+ * of the declared format (a raw `true`/`false` cell is never intended output).
312
+ */
313
+ declare function formatValue(value: FieldValue | undefined, format?: string): string;
314
+ /** Sort direction for {@link sortRows}. */
315
+ type SortDirection = 'asc' | 'desc';
316
+ /**
317
+ * Order two cell values by their own type, never by what the field is called.
318
+ *
319
+ * Numbers compare numerically, date-like strings chronologically, everything
320
+ * else by locale string order. `null`/`undefined` sort last in both directions
321
+ * so empty cells never displace real data at the top of a list.
322
+ */
323
+ declare function compareCellValues(a: FieldValue | undefined, b: FieldValue | undefined): number;
324
+ /**
325
+ * Return a new array ordered by `field`. Non-mutating, and a no-op without a
326
+ * field so callers can pass the prop through unconditionally.
327
+ *
328
+ * NOTE: this orders only the rows already fetched. A collection larger than its
329
+ * `limit` still needs ordering at the data layer — see `L-NO-COLLECTION-ORDERING`.
330
+ */
331
+ declare function sortRows<T extends Record<string, FieldValue | undefined>>(rows: readonly T[], field?: string, direction?: SortDirection): readonly T[];
332
+
286
333
  /**
287
334
  * Get Nested Value Utility
288
335
  *
@@ -502,4 +549,4 @@ declare function eightPointedStarPath(cx: number, cy: number, outerR: number, in
502
549
  */
503
550
  declare function arrowheadPath(size: number): string;
504
551
 
505
- export { ApiError, type DebugEvent, type DebugEventType, type EntitySnapshot, type EntityState, type GuardContext, type GuardEvaluation, JAZARI_COLORS, type JazariArmLayout, type JazariEffectInfo, type JazariGearLayout, type JazariGuardInfo, type JazariLayout, type LayoutInput, type LayoutState, type LayoutTransition, type PersistentEntityInfo, type RuntimeEntity, type TickExecution, type TraitDebugInfo, type TraitGuard, type TraitTransition, apiClient, arrowheadPath, brainIconPath, clearDebugEvents, clearEntityProvider, clearGuardHistory, clearTicks, clearTraits, computeJazariLayout, debug, debugCollision, debugError, debugGameState, debugGroup, debugGroupEnd, debugInput, debugPhysics, debugTable, debugTime, debugTimeEnd, debugWarn, eightPointedStarPath, formatNestedFieldLabel, gearTeethPath, getAllTicks, getAllTraits, getDebugEvents, getEntitiesByType, getEntityById, getEntitySnapshot, getEventsBySource, getEventsByType, getGuardEvaluationsForTrait, getGuardHistory, getNestedValue, getRecentEvents, getRecentGuardEvaluations, getTick, getTrait, initDebugShortcut, isDebugEnabled, lockIconPath, logDebugEvent, logEffectExecuted, logError, logEventFired, logInfo, logStateChange, logWarning, onDebugToggle, pipeIconPath, recordGuardEvaluation, registerTick, registerTrait, setDebugEnabled, setEntityProvider, setTickActive, subscribeToDebugEvents, subscribeToGuardChanges, subscribeToTickChanges, subscribeToTraitChanges, toggleDebug, unregisterTick, unregisterTrait, updateGuardResult, updateTickExecution, updateTraitState };
552
+ export { ApiError, type DebugEvent, type DebugEventType, type EntitySnapshot, type EntityState, type GuardContext, type GuardEvaluation, JAZARI_COLORS, type JazariArmLayout, type JazariEffectInfo, type JazariGearLayout, type JazariGuardInfo, type JazariLayout, type LayoutInput, type LayoutState, type LayoutTransition, type PersistentEntityInfo, type RuntimeEntity, type SortDirection, type TickExecution, type TraitDebugInfo, type TraitGuard, type TraitTransition, type ValueFormat, apiClient, arrowheadPath, brainIconPath, clearDebugEvents, clearEntityProvider, clearGuardHistory, clearTicks, clearTraits, compareCellValues, computeJazariLayout, debug, debugCollision, debugError, debugGameState, debugGroup, debugGroupEnd, debugInput, debugPhysics, debugTable, debugTime, debugTimeEnd, debugWarn, eightPointedStarPath, formatDate, formatDateTime, formatNestedFieldLabel, formatTime, formatValue, gearTeethPath, getAllTicks, getAllTraits, getDebugEvents, getEntitiesByType, getEntityById, getEntitySnapshot, getEventsBySource, getEventsByType, getGuardEvaluationsForTrait, getGuardHistory, getNestedValue, getRecentEvents, getRecentGuardEvaluations, getTick, getTrait, humanizeEnumValue, humanizeFieldName, initDebugShortcut, isDebugEnabled, lockIconPath, logDebugEvent, logEffectExecuted, logError, logEventFired, logInfo, logStateChange, logWarning, onDebugToggle, pipeIconPath, recordGuardEvaluation, registerTick, registerTrait, setDebugEnabled, setEntityProvider, setTickActive, sortRows, subscribeToDebugEvents, subscribeToGuardChanges, subscribeToTickChanges, subscribeToTraitChanges, toggleDebug, unregisterTick, unregisterTrait, updateGuardResult, updateTickExecution, updateTraitState };
package/dist/lib/index.js CHANGED
@@ -788,6 +788,83 @@ function clearVerification() {
788
788
  }
789
789
  exposeOnWindow();
790
790
 
791
+ // lib/format.ts
792
+ function humanizeFieldName(name) {
793
+ return name.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/[_-]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()).replace(/\b([A-Z])([A-Z]+)\b/g, (_, first, rest) => first + rest.toLowerCase()).trim();
794
+ }
795
+ function humanizeEnumValue(value) {
796
+ return /^[a-z0-9]+(?:[_-][a-z0-9]+)+$/.test(value) ? humanizeFieldName(value) : value;
797
+ }
798
+ function formatDate(value) {
799
+ if (!value) return "";
800
+ const d = new Date(String(value));
801
+ if (isNaN(d.getTime())) return String(value);
802
+ return d.toLocaleDateString(void 0, { year: "numeric", month: "short", day: "numeric" });
803
+ }
804
+ function formatTime(value) {
805
+ if (!value) return "";
806
+ const d = new Date(String(value));
807
+ if (isNaN(d.getTime())) return String(value);
808
+ return d.toLocaleTimeString(void 0, { hour: "numeric", minute: "2-digit" });
809
+ }
810
+ function formatDateTime(value) {
811
+ if (!value) return "";
812
+ const d = new Date(String(value));
813
+ if (isNaN(d.getTime())) return String(value);
814
+ return `${formatDate(value)} ${formatTime(value)}`;
815
+ }
816
+ function asYesNo(value) {
817
+ return value === false || value === 0 || String(value) === "false" ? "No" : "Yes";
818
+ }
819
+ function formatValue(value, format) {
820
+ if (value === void 0 || value === null) return "";
821
+ if (typeof value === "boolean") return asYesNo(value);
822
+ switch (format) {
823
+ case "date":
824
+ return formatDate(value);
825
+ case "time":
826
+ return formatTime(value);
827
+ case "datetime":
828
+ return formatDateTime(value);
829
+ case "currency":
830
+ return typeof value === "number" ? `$${value.toFixed(2)}` : String(value);
831
+ case "number":
832
+ return typeof value === "number" ? value.toLocaleString() : String(value);
833
+ case "percent":
834
+ return typeof value === "number" ? `${Math.round(value)}%` : String(value);
835
+ case "boolean":
836
+ return asYesNo(value);
837
+ default:
838
+ return String(value);
839
+ }
840
+ }
841
+ function compareCellValues(a, b) {
842
+ const aEmpty = a === null || a === void 0 || a === "";
843
+ const bEmpty = b === null || b === void 0 || b === "";
844
+ if (aEmpty || bEmpty) return aEmpty && bEmpty ? 0 : aEmpty ? 1 : -1;
845
+ if (typeof a === "number" && typeof b === "number") return a - b;
846
+ if (typeof a === "boolean" && typeof b === "boolean") return Number(a) - Number(b);
847
+ const aNum = Number(a);
848
+ const bNum = Number(b);
849
+ if (Number.isFinite(aNum) && Number.isFinite(bNum)) return aNum - bNum;
850
+ const aTime = dateLikeTime(a);
851
+ const bTime = dateLikeTime(b);
852
+ if (aTime !== null && bTime !== null) return aTime - bTime;
853
+ return String(a).localeCompare(String(b));
854
+ }
855
+ function dateLikeTime(value) {
856
+ if (value instanceof Date) return value.getTime();
857
+ const text = String(value);
858
+ if (!/\d/.test(text) || !/[-/:T]/.test(text)) return null;
859
+ const time = Date.parse(text);
860
+ return Number.isNaN(time) ? null : time;
861
+ }
862
+ function sortRows(rows, field, direction = "asc") {
863
+ if (!field) return rows;
864
+ const dir = direction === "desc" ? -1 : 1;
865
+ return [...rows].sort((a, b) => dir * compareCellValues(a?.[field], b?.[field]));
866
+ }
867
+
791
868
  // lib/getNestedValue.ts
792
869
  function getNestedValue(obj, path) {
793
870
  if (obj === null || obj === void 0 || !path) {
@@ -1844,4 +1921,4 @@ var JAZARI_COLORS = {
1844
1921
  darkBg: "#1a1a2e"
1845
1922
  };
1846
1923
 
1847
- export { ApiError, DEFAULT_CONFIG, JAZARI_COLORS, apiClient, arrowheadPath, bindCanvasCapture, bindEventBus, bindLastDrawables, bindTraitStateGetter, brainIconPath, clearDebugEvents, clearEntityProvider, clearGuardHistory, clearTicks, clearTraits, clearVerification, cn, computeJazariLayout, debug, debugCollision, debugError, debugGameState, debugGroup, debugGroupEnd, debugInput, debugPhysics, debugTable, debugTime, debugTimeEnd, debugWarn, eightPointedStarPath, extractOutputsFromTransitions, extractStateMachine, formatGuard, formatNestedFieldLabel, gearTeethPath, getAllChecks, getAllTicks, getAllTraits, getBridgeHealth, getDebugEvents, getEffectSummary, getEntitiesByType, getEntityById, getEntitySnapshot, getEventsBySource, getEventsByType, getGuardEvaluationsForTrait, getGuardHistory, getNestedValue, getRecentEvents, getRecentGuardEvaluations, getSnapshot, getSummary, getTick, getTrait, getTraitSnapshots, getTransitions, getTransitionsForTrait, initDebugShortcut, isDebugEnabled, lockIconPath, logDebugEvent, logEffectExecuted, logError, logEventFired, logInfo, logStateChange, logWarning, onDebugToggle, parseContentSegments, parseMarkdownWithCodeBlocks, pipeIconPath, recordGuardEvaluation, recordServerResponse, recordTransition, registerCheck, registerTick, registerTrait, registerTraitSnapshot, renderStateMachineToDomData, renderStateMachineToSvg, setDebugEnabled, setEntityProvider, setTickActive, subscribeToDebugEvents, subscribeToGuardChanges, subscribeToTickChanges, subscribeToTraitChanges, subscribeToVerification, toggleDebug, unregisterTick, unregisterTrait, updateAssetStatus, updateBridgeHealth, updateCheck, updateGuardResult, updateTickExecution, updateTraitState, waitForTransition };
1924
+ export { ApiError, DEFAULT_CONFIG, JAZARI_COLORS, apiClient, arrowheadPath, bindCanvasCapture, bindEventBus, bindLastDrawables, bindTraitStateGetter, brainIconPath, clearDebugEvents, clearEntityProvider, clearGuardHistory, clearTicks, clearTraits, clearVerification, cn, compareCellValues, computeJazariLayout, debug, debugCollision, debugError, debugGameState, debugGroup, debugGroupEnd, debugInput, debugPhysics, debugTable, debugTime, debugTimeEnd, debugWarn, eightPointedStarPath, extractOutputsFromTransitions, extractStateMachine, formatDate, formatDateTime, formatGuard, formatNestedFieldLabel, formatTime, formatValue, gearTeethPath, getAllChecks, getAllTicks, getAllTraits, getBridgeHealth, getDebugEvents, getEffectSummary, getEntitiesByType, getEntityById, getEntitySnapshot, getEventsBySource, getEventsByType, getGuardEvaluationsForTrait, getGuardHistory, getNestedValue, getRecentEvents, getRecentGuardEvaluations, getSnapshot, getSummary, getTick, getTrait, getTraitSnapshots, getTransitions, getTransitionsForTrait, humanizeEnumValue, humanizeFieldName, initDebugShortcut, isDebugEnabled, lockIconPath, logDebugEvent, logEffectExecuted, logError, logEventFired, logInfo, logStateChange, logWarning, onDebugToggle, parseContentSegments, parseMarkdownWithCodeBlocks, pipeIconPath, recordGuardEvaluation, recordServerResponse, recordTransition, registerCheck, registerTick, registerTrait, registerTraitSnapshot, renderStateMachineToDomData, renderStateMachineToSvg, setDebugEnabled, setEntityProvider, setTickActive, sortRows, subscribeToDebugEvents, subscribeToGuardChanges, subscribeToTickChanges, subscribeToTraitChanges, subscribeToVerification, toggleDebug, unregisterTick, unregisterTrait, updateAssetStatus, updateBridgeHealth, updateCheck, updateGuardResult, updateTickExecution, updateTraitState, waitForTransition };