@almadar/ui 5.134.0 → 5.136.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.
Files changed (31) hide show
  1. package/dist/{TraitProvider-Ch79cUcb.d.cts → EntityBindingContext-CD9ZoXb4.d.cts} +30 -2
  2. package/dist/{TraitProvider-Ch79cUcb.d.ts → EntityBindingContext-CD9ZoXb4.d.ts} +30 -2
  3. package/dist/avl/index.cjs +819 -429
  4. package/dist/avl/index.js +820 -430
  5. package/dist/{cn-Dm0VrLRG.d.ts → cn-CCaph5o9.d.ts} +1 -1
  6. package/dist/{cn-D3H9UzCW.d.cts → cn-CL0kdshO.d.cts} +1 -1
  7. package/dist/components/index.cjs +1649 -1482
  8. package/dist/components/index.d.cts +105 -202
  9. package/dist/components/index.d.ts +105 -202
  10. package/dist/components/index.js +705 -533
  11. package/dist/lib/drawable/three/index.cjs +16 -0
  12. package/dist/lib/drawable/three/index.d.cts +1 -1
  13. package/dist/lib/drawable/three/index.d.ts +1 -1
  14. package/dist/lib/drawable/three/index.js +16 -0
  15. package/dist/lib/index.cjs +28 -0
  16. package/dist/lib/index.d.cts +21 -3
  17. package/dist/lib/index.d.ts +21 -3
  18. package/dist/lib/index.js +27 -1
  19. package/dist/marketing/index.cjs +1 -0
  20. package/dist/marketing/index.js +1 -0
  21. package/dist/{paintDispatch-BXJgISot.d.cts → paintDispatch-DXygiK7M.d.cts} +39 -10
  22. package/dist/{paintDispatch-BXJgISot.d.ts → paintDispatch-DXygiK7M.d.ts} +39 -10
  23. package/dist/providers/index.cjs +701 -323
  24. package/dist/providers/index.d.cts +3 -3
  25. package/dist/providers/index.d.ts +3 -3
  26. package/dist/providers/index.js +698 -322
  27. package/dist/runtime/index.cjs +819 -429
  28. package/dist/runtime/index.d.cts +5 -2
  29. package/dist/runtime/index.d.ts +5 -2
  30. package/dist/runtime/index.js +820 -430
  31. package/package.json +6 -5
@@ -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":
@@ -559,6 +560,7 @@ function getAtlas(url, onReady) {
559
560
  onReady();
560
561
  }).catch(() => {
561
562
  atlasCache.set(url, null);
563
+ onReady();
562
564
  });
563
565
  return void 0;
564
566
  }
@@ -794,6 +796,13 @@ function ModelLoader({
794
796
  }
795
797
  );
796
798
  }
799
+ var mesh3dLog = logger.createLogger("almadar:ui:drawable-3d");
800
+ var warnedUnsupported = /* @__PURE__ */ new Set();
801
+ var warnUnsupported3d = (kind) => {
802
+ if (warnedUnsupported.has(kind)) return;
803
+ warnedUnsupported.add(kind);
804
+ mesh3dLog.warn("unsupported drawable kind on the 3D backend \u2014 skipped", { kind });
805
+ };
797
806
  var CrossOriginTextureLoader = class extends THREE9__namespace.TextureLoader {
798
807
  constructor() {
799
808
  super();
@@ -966,6 +975,10 @@ function Shape3D({ node, projector }) {
966
975
  geometry = /* @__PURE__ */ jsxRuntime.jsx("shapeGeometry", { args: [s] });
967
976
  break;
968
977
  }
978
+ case "path": {
979
+ warnUnsupported3d("draw-shape:path");
980
+ return null;
981
+ }
969
982
  default:
970
983
  return null;
971
984
  }
@@ -1004,6 +1017,9 @@ function Drawable3D({ node, projector }) {
1004
1017
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: node.items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(Shape3D, { node: item, projector }, i)) });
1005
1018
  case "draw-text-layer":
1006
1019
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: node.items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(Text3D, { node: item, projector }, i)) });
1020
+ case "draw-group":
1021
+ warnUnsupported3d("draw-group");
1022
+ return null;
1007
1023
  }
1008
1024
  }
1009
1025
 
@@ -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-DXygiK7M.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-DXygiK7M.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":
@@ -535,6 +536,7 @@ function getAtlas(url, onReady) {
535
536
  onReady();
536
537
  }).catch(() => {
537
538
  atlasCache.set(url, null);
539
+ onReady();
538
540
  });
539
541
  return void 0;
540
542
  }
@@ -770,6 +772,13 @@ function ModelLoader({
770
772
  }
771
773
  );
772
774
  }
775
+ var mesh3dLog = createLogger("almadar:ui:drawable-3d");
776
+ var warnedUnsupported = /* @__PURE__ */ new Set();
777
+ var warnUnsupported3d = (kind) => {
778
+ if (warnedUnsupported.has(kind)) return;
779
+ warnedUnsupported.add(kind);
780
+ mesh3dLog.warn("unsupported drawable kind on the 3D backend \u2014 skipped", { kind });
781
+ };
773
782
  var CrossOriginTextureLoader = class extends THREE9.TextureLoader {
774
783
  constructor() {
775
784
  super();
@@ -942,6 +951,10 @@ function Shape3D({ node, projector }) {
942
951
  geometry = /* @__PURE__ */ jsx("shapeGeometry", { args: [s] });
943
952
  break;
944
953
  }
954
+ case "path": {
955
+ warnUnsupported3d("draw-shape:path");
956
+ return null;
957
+ }
945
958
  default:
946
959
  return null;
947
960
  }
@@ -980,6 +993,9 @@ function Drawable3D({ node, projector }) {
980
993
  return /* @__PURE__ */ jsx(Fragment, { children: node.items.map((item, i) => /* @__PURE__ */ jsx(Shape3D, { node: item, projector }, i)) });
981
994
  case "draw-text-layer":
982
995
  return /* @__PURE__ */ jsx(Fragment, { children: node.items.map((item, i) => /* @__PURE__ */ jsx(Text3D, { node: item, projector }, i)) });
996
+ case "draw-group":
997
+ warnUnsupported3d("draw-group");
998
+ return null;
983
999
  }
984
1000
  }
985
1001
 
@@ -840,6 +840,32 @@ function formatValue(value, format) {
840
840
  return String(value);
841
841
  }
842
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
+ }
843
869
 
844
870
  // lib/getNestedValue.ts
845
871
  function getNestedValue(obj, path) {
@@ -1914,6 +1940,7 @@ exports.clearTicks = clearTicks;
1914
1940
  exports.clearTraits = clearTraits;
1915
1941
  exports.clearVerification = clearVerification;
1916
1942
  exports.cn = cn;
1943
+ exports.compareCellValues = compareCellValues;
1917
1944
  exports.computeJazariLayout = computeJazariLayout;
1918
1945
  exports.debug = debug;
1919
1946
  exports.debugCollision = debugCollision;
@@ -1988,6 +2015,7 @@ exports.renderStateMachineToSvg = renderStateMachineToSvg;
1988
2015
  exports.setDebugEnabled = setDebugEnabled;
1989
2016
  exports.setEntityProvider = setEntityProvider;
1990
2017
  exports.setTickActive = setTickActive;
2018
+ exports.sortRows = sortRows;
1991
2019
  exports.subscribeToDebugEvents = subscribeToDebugEvents;
1992
2020
  exports.subscribeToGuardChanges = subscribeToGuardChanges;
1993
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-CL0kdshO.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-DXygiK7M.cjs';
5
5
  import 'clsx';
6
6
 
7
7
  /**
@@ -311,6 +311,24 @@ declare function formatDateTime(value: FieldValue | undefined): string;
311
311
  * of the declared format (a raw `true`/`false` cell is never intended output).
312
312
  */
313
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[];
314
332
 
315
333
  /**
316
334
  * Get Nested Value Utility
@@ -531,4 +549,4 @@ declare function eightPointedStarPath(cx: number, cy: number, outerR: number, in
531
549
  */
532
550
  declare function arrowheadPath(size: number): string;
533
551
 
534
- 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, type ValueFormat, apiClient, arrowheadPath, brainIconPath, clearDebugEvents, clearEntityProvider, clearGuardHistory, clearTicks, clearTraits, 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, 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-CCaph5o9.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-DXygiK7M.js';
5
5
  import 'clsx';
6
6
 
7
7
  /**
@@ -311,6 +311,24 @@ declare function formatDateTime(value: FieldValue | undefined): string;
311
311
  * of the declared format (a raw `true`/`false` cell is never intended output).
312
312
  */
313
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[];
314
332
 
315
333
  /**
316
334
  * Get Nested Value Utility
@@ -531,4 +549,4 @@ declare function eightPointedStarPath(cx: number, cy: number, outerR: number, in
531
549
  */
532
550
  declare function arrowheadPath(size: number): string;
533
551
 
534
- 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, type ValueFormat, apiClient, arrowheadPath, brainIconPath, clearDebugEvents, clearEntityProvider, clearGuardHistory, clearTicks, clearTraits, 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, 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
@@ -838,6 +838,32 @@ function formatValue(value, format) {
838
838
  return String(value);
839
839
  }
840
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
+ }
841
867
 
842
868
  // lib/getNestedValue.ts
843
869
  function getNestedValue(obj, path) {
@@ -1895,4 +1921,4 @@ var JAZARI_COLORS = {
1895
1921
  darkBg: "#1a1a2e"
1896
1922
  };
1897
1923
 
1898
- 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, 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, 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 };
@@ -3351,6 +3351,7 @@ function getAtlas(url, onReady) {
3351
3351
  onReady();
3352
3352
  }).catch(() => {
3353
3353
  atlasCache.set(url, null);
3354
+ onReady();
3354
3355
  });
3355
3356
  return void 0;
3356
3357
  }
@@ -3330,6 +3330,7 @@ function getAtlas(url, onReady) {
3330
3330
  onReady();
3331
3331
  }).catch(() => {
3332
3332
  atlasCache.set(url, null);
3333
+ onReady();
3333
3334
  });
3334
3335
  return void 0;
3335
3336
  }
@@ -76,9 +76,9 @@ interface DrawSpriteProps extends DrawableBase {
76
76
  asset: Asset;
77
77
  /** How the sprite aligns to its projected position. Default `'top-left'`. */
78
78
  anchor?: DrawableAnchor;
79
- /** Draw width in world units (fractions of `projector.tileWidth`); omittedresolved source width in px. */
79
+ /** Draw width in world units (fractions of `projector.tileWidth`). Omittedone cell on tile grids (`flat`/`iso`/`hex`); native source px on `free`/`side`. */
80
80
  width?: number;
81
- /** Draw height in world units (fractions of `projector.tileWidth`); omittedresolved source height in px. */
81
+ /** Draw height in world units (fractions of `projector.tileWidth`). Omittedone cell on tile grids (`flat`/`iso`/`hex`); native source px on `free`/`side`. */
82
82
  height?: number;
83
83
  /** Explicit atlas sub-rect override (px); omitted → resolved from `asset.atlas`/`asset.sprite`. */
84
84
  frame?: BlitSrc;
@@ -100,16 +100,16 @@ interface DrawSpriteProps extends DrawableBase {
100
100
  * ONE descriptor (`DrawShapeProps`, grounded in core `ScenePos`) with TWO
101
101
  * backends: `paintShape` (2D, here) and an R3F ground-plane mesh (`Shape3D` in
102
102
  * `lib/drawable/mesh3d`, kept OUT of this file so the 2D path never pulls R3F).
103
- * Paints a cell footprint, an axis-aligned rect, an ellipse, or a poly at a scene
104
- * position, fill and/or stroke. Genre uses (tile fallback, iso/hex diamond
105
- * fallback, cell highlight, feature disc, unit selection ring, unit fallback
106
- * circle, ground/ghost discs, solid backgrounds, side-view platform rects) are
107
- * all this atom with different `shape`/`anchor`/geometry — composed in `.lolo`,
108
- * not here. The React component renders `null`; it exists so the pattern pipeline
103
+ * Paints a cell footprint, an axis-aligned rect, an ellipse, a poly, or an SVG
104
+ * path at a scene position, fill and/or stroke. Genre uses (tile fallback, iso/hex
105
+ * diamond fallback, cell highlight, feature disc, unit selection ring, unit
106
+ * fallback circle, ground/ghost discs, solid backgrounds, side-view platform
107
+ * rects, hand-authored vector art) are all this atom with different
108
+ * `shape`/`anchor`/geometry — composed in `.lolo`, not here. The React component renders `null`; it exists so the pattern pipeline
109
109
  * registers a `draw-shape` pattern and standalone pages stay inspectable.
110
110
  */
111
111
 
112
- type ShapeKind = 'cell' | 'rect' | 'ellipse' | 'poly';
112
+ type ShapeKind = 'cell' | 'rect' | 'ellipse' | 'poly' | 'path';
113
113
  interface DrawShapeProps extends DrawableBase {
114
114
  type: 'draw-shape';
115
115
  shape: ShapeKind;
@@ -130,6 +130,8 @@ interface DrawShapeProps extends DrawableBase {
130
130
  offsetY?: number;
131
131
  /** Poly vertices as world-unit offsets relative to the cell's projected top-left. */
132
132
  points?: PainterPoint[];
133
+ /** SVG path data in world units relative to the cell's projected top-left — same coordinate convention as `points`. */
134
+ d?: string;
133
135
  fill?: string;
134
136
  stroke?: string;
135
137
  strokeWidth?: number;
@@ -162,6 +164,33 @@ interface DrawTextProps extends DrawableBase {
162
164
  opacity?: number;
163
165
  }
164
166
 
167
+ /**
168
+ * `draw-group` — the drawable CONTAINER atom (dimension-agnostic).
169
+ *
170
+ * Multi-shape art (a hero token = cloak + head + sword shapes) travels as ONE
171
+ * node: the host paints the group by translating to its projected position,
172
+ * applying `scale`/`rotate`/`opacity`, then painting each `items` descriptor
173
+ * through the normal dispatch. `items` is a plain data prop (NOT `children`,
174
+ * which UISlotRenderer special-cases) — same convention as the `draw-*-layer`
175
+ * molecules. The React component renders `null`; it exists so the pattern
176
+ * pipeline registers a `draw-group` pattern and standalone pages stay
177
+ * inspectable. 2D-canvas only — the 3D backend skips it with a warn.
178
+ */
179
+
180
+ interface DrawGroupProps extends DrawableBase {
181
+ type: 'draw-group';
182
+ /** Logical scene position; the projector maps it to pixels / world. */
183
+ position: ScenePos;
184
+ /** Uniform scale applied to the whole group. */
185
+ scale?: number;
186
+ /** Rotation in radians (painter units). */
187
+ rotate?: number;
188
+ /** 0..1 opacity. */
189
+ opacity?: number;
190
+ /** The grouped drawables, painted through the normal dispatch. */
191
+ items: DrawableNode[];
192
+ }
193
+
165
194
  /**
166
195
  * `draw-sprite-layer` — batch multiple sprites in one descriptor for O(layers) rendering.
167
196
  *
@@ -218,6 +247,6 @@ interface DrawTextLayerProps extends DrawableBase {
218
247
  */
219
248
 
220
249
  /** Every drawable descriptor. The host's `children` are a `DrawableNode[]`. */
221
- type DrawableNode = DrawSpriteProps | DrawShapeProps | DrawTextProps | DrawSpriteLayerProps | DrawShapeLayerProps | DrawTextLayerProps;
250
+ type DrawableNode = DrawSpriteProps | DrawShapeProps | DrawTextProps | DrawGroupProps | DrawSpriteLayerProps | DrawShapeLayerProps | DrawTextLayerProps;
222
251
 
223
252
  export type { DrawableNode as D };
@@ -76,9 +76,9 @@ interface DrawSpriteProps extends DrawableBase {
76
76
  asset: Asset;
77
77
  /** How the sprite aligns to its projected position. Default `'top-left'`. */
78
78
  anchor?: DrawableAnchor;
79
- /** Draw width in world units (fractions of `projector.tileWidth`); omittedresolved source width in px. */
79
+ /** Draw width in world units (fractions of `projector.tileWidth`). Omittedone cell on tile grids (`flat`/`iso`/`hex`); native source px on `free`/`side`. */
80
80
  width?: number;
81
- /** Draw height in world units (fractions of `projector.tileWidth`); omittedresolved source height in px. */
81
+ /** Draw height in world units (fractions of `projector.tileWidth`). Omittedone cell on tile grids (`flat`/`iso`/`hex`); native source px on `free`/`side`. */
82
82
  height?: number;
83
83
  /** Explicit atlas sub-rect override (px); omitted → resolved from `asset.atlas`/`asset.sprite`. */
84
84
  frame?: BlitSrc;
@@ -100,16 +100,16 @@ interface DrawSpriteProps extends DrawableBase {
100
100
  * ONE descriptor (`DrawShapeProps`, grounded in core `ScenePos`) with TWO
101
101
  * backends: `paintShape` (2D, here) and an R3F ground-plane mesh (`Shape3D` in
102
102
  * `lib/drawable/mesh3d`, kept OUT of this file so the 2D path never pulls R3F).
103
- * Paints a cell footprint, an axis-aligned rect, an ellipse, or a poly at a scene
104
- * position, fill and/or stroke. Genre uses (tile fallback, iso/hex diamond
105
- * fallback, cell highlight, feature disc, unit selection ring, unit fallback
106
- * circle, ground/ghost discs, solid backgrounds, side-view platform rects) are
107
- * all this atom with different `shape`/`anchor`/geometry — composed in `.lolo`,
108
- * not here. The React component renders `null`; it exists so the pattern pipeline
103
+ * Paints a cell footprint, an axis-aligned rect, an ellipse, a poly, or an SVG
104
+ * path at a scene position, fill and/or stroke. Genre uses (tile fallback, iso/hex
105
+ * diamond fallback, cell highlight, feature disc, unit selection ring, unit
106
+ * fallback circle, ground/ghost discs, solid backgrounds, side-view platform
107
+ * rects, hand-authored vector art) are all this atom with different
108
+ * `shape`/`anchor`/geometry — composed in `.lolo`, not here. The React component renders `null`; it exists so the pattern pipeline
109
109
  * registers a `draw-shape` pattern and standalone pages stay inspectable.
110
110
  */
111
111
 
112
- type ShapeKind = 'cell' | 'rect' | 'ellipse' | 'poly';
112
+ type ShapeKind = 'cell' | 'rect' | 'ellipse' | 'poly' | 'path';
113
113
  interface DrawShapeProps extends DrawableBase {
114
114
  type: 'draw-shape';
115
115
  shape: ShapeKind;
@@ -130,6 +130,8 @@ interface DrawShapeProps extends DrawableBase {
130
130
  offsetY?: number;
131
131
  /** Poly vertices as world-unit offsets relative to the cell's projected top-left. */
132
132
  points?: PainterPoint[];
133
+ /** SVG path data in world units relative to the cell's projected top-left — same coordinate convention as `points`. */
134
+ d?: string;
133
135
  fill?: string;
134
136
  stroke?: string;
135
137
  strokeWidth?: number;
@@ -162,6 +164,33 @@ interface DrawTextProps extends DrawableBase {
162
164
  opacity?: number;
163
165
  }
164
166
 
167
+ /**
168
+ * `draw-group` — the drawable CONTAINER atom (dimension-agnostic).
169
+ *
170
+ * Multi-shape art (a hero token = cloak + head + sword shapes) travels as ONE
171
+ * node: the host paints the group by translating to its projected position,
172
+ * applying `scale`/`rotate`/`opacity`, then painting each `items` descriptor
173
+ * through the normal dispatch. `items` is a plain data prop (NOT `children`,
174
+ * which UISlotRenderer special-cases) — same convention as the `draw-*-layer`
175
+ * molecules. The React component renders `null`; it exists so the pattern
176
+ * pipeline registers a `draw-group` pattern and standalone pages stay
177
+ * inspectable. 2D-canvas only — the 3D backend skips it with a warn.
178
+ */
179
+
180
+ interface DrawGroupProps extends DrawableBase {
181
+ type: 'draw-group';
182
+ /** Logical scene position; the projector maps it to pixels / world. */
183
+ position: ScenePos;
184
+ /** Uniform scale applied to the whole group. */
185
+ scale?: number;
186
+ /** Rotation in radians (painter units). */
187
+ rotate?: number;
188
+ /** 0..1 opacity. */
189
+ opacity?: number;
190
+ /** The grouped drawables, painted through the normal dispatch. */
191
+ items: DrawableNode[];
192
+ }
193
+
165
194
  /**
166
195
  * `draw-sprite-layer` — batch multiple sprites in one descriptor for O(layers) rendering.
167
196
  *
@@ -218,6 +247,6 @@ interface DrawTextLayerProps extends DrawableBase {
218
247
  */
219
248
 
220
249
  /** Every drawable descriptor. The host's `children` are a `DrawableNode[]`. */
221
- type DrawableNode = DrawSpriteProps | DrawShapeProps | DrawTextProps | DrawSpriteLayerProps | DrawShapeLayerProps | DrawTextLayerProps;
250
+ type DrawableNode = DrawSpriteProps | DrawShapeProps | DrawTextProps | DrawGroupProps | DrawSpriteLayerProps | DrawShapeLayerProps | DrawTextLayerProps;
222
251
 
223
252
  export type { DrawableNode as D };