@almadar/ui 5.97.0 → 5.98.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.
@@ -10966,11 +10966,14 @@ function recordTransition(trace) {
10966
10966
  }
10967
10967
  if (entry.event === "INIT") {
10968
10968
  const hasFetch = entry.effects.some((e) => e.type === "fetch");
10969
+ const hasEntitySeed = entry.effects.some(
10970
+ (e) => e.type === "set" && typeof e.args[0] === "string" && e.args[0].startsWith("@entity.")
10971
+ );
10969
10972
  const checkId = `init-fetch-${entry.traitName}`;
10970
- if (hasFetch) {
10973
+ if (hasFetch || hasEntitySeed) {
10971
10974
  registerCheck(
10972
10975
  checkId,
10973
- `INIT transition for "${entry.traitName}" has fetch effect`,
10976
+ `INIT transition for "${entry.traitName}" has fetch or entity-seed effect`,
10974
10977
  "pass"
10975
10978
  );
10976
10979
  } else {
@@ -11625,7 +11628,7 @@ var init_ScoreDisplay = __esm({
11625
11628
  }
11626
11629
  });
11627
11630
  function ControlButton({
11628
- assetUrl = DEFAULT_ASSET_URL,
11631
+ assetUrl,
11629
11632
  label,
11630
11633
  icon,
11631
11634
  size = "md",
@@ -11703,7 +11706,7 @@ function ControlButton({
11703
11706
  }
11704
11707
  );
11705
11708
  }
11706
- var sizeMap4, shapeMap, variantMap, DEFAULT_ASSET_URL;
11709
+ var sizeMap4, shapeMap, variantMap;
11707
11710
  var init_ControlButton = __esm({
11708
11711
  "components/game/2d/atoms/ControlButton.tsx"() {
11709
11712
  "use client";
@@ -11730,11 +11733,6 @@ var init_ControlButton = __esm({
11730
11733
  secondary: "bg-secondary text-secondary-foreground border-border hover:bg-secondary-hover",
11731
11734
  ghost: "bg-transparent text-foreground border-border hover:bg-muted"
11732
11735
  };
11733
- DEFAULT_ASSET_URL = {
11734
- url: "https://almadar-kflow-assets.web.app/shared/effects/particles/circle_01.png",
11735
- role: "ui",
11736
- category: "control"
11737
- };
11738
11736
  ControlButton.displayName = "ControlButton";
11739
11737
  }
11740
11738
  });
@@ -11823,7 +11821,7 @@ function isKnownState(s) {
11823
11821
  return s in DEFAULT_STATE_STYLES;
11824
11822
  }
11825
11823
  function StateIndicator({
11826
- assetUrl = DEFAULT_ASSET_URL2,
11824
+ assetUrl = DEFAULT_ASSET_URL,
11827
11825
  state = "idle",
11828
11826
  label,
11829
11827
  size = "md",
@@ -11853,14 +11851,14 @@ function StateIndicator({
11853
11851
  }
11854
11852
  );
11855
11853
  }
11856
- var DEFAULT_ASSET_URL2, DEFAULT_STATE_STYLES, DEFAULT_STYLE, STATIC_STATES, SIZE_CLASSES;
11854
+ var DEFAULT_ASSET_URL, DEFAULT_STATE_STYLES, DEFAULT_STYLE, STATIC_STATES, SIZE_CLASSES;
11857
11855
  var init_StateIndicator = __esm({
11858
11856
  "components/game/2d/atoms/StateIndicator.tsx"() {
11859
11857
  init_Box();
11860
11858
  init_Icon();
11861
11859
  init_cn();
11862
11860
  init_GameIcon();
11863
- DEFAULT_ASSET_URL2 = {
11861
+ DEFAULT_ASSET_URL = {
11864
11862
  url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
11865
11863
  role: "ui",
11866
11864
  category: "state"
@@ -11946,7 +11944,7 @@ var init_TimerDisplay = __esm({
11946
11944
  }
11947
11945
  });
11948
11946
  function ResourceCounter({
11949
- assetUrl = DEFAULT_ASSET_URL3,
11947
+ assetUrl = DEFAULT_ASSET_URL2,
11950
11948
  icon,
11951
11949
  label = "Gold",
11952
11950
  value = 250,
@@ -11979,7 +11977,7 @@ function ResourceCounter({
11979
11977
  }
11980
11978
  );
11981
11979
  }
11982
- var colorTokenClasses2, DEFAULT_ASSET_URL3, sizeMap6;
11980
+ var colorTokenClasses2, DEFAULT_ASSET_URL2, sizeMap6;
11983
11981
  var init_ResourceCounter = __esm({
11984
11982
  "components/game/2d/atoms/ResourceCounter.tsx"() {
11985
11983
  init_cn();
@@ -11995,7 +11993,7 @@ var init_ResourceCounter = __esm({
11995
11993
  error: "text-error",
11996
11994
  muted: "text-muted-foreground"
11997
11995
  };
11998
- DEFAULT_ASSET_URL3 = {
11996
+ DEFAULT_ASSET_URL2 = {
11999
11997
  url: "https://almadar-kflow-assets.web.app/shared/world-map/gold_mine.png",
12000
11998
  role: "ui",
12001
11999
  category: "coin"
@@ -12009,7 +12007,7 @@ var init_ResourceCounter = __esm({
12009
12007
  }
12010
12008
  });
12011
12009
  function ItemSlot({
12012
- assetUrl = DEFAULT_ASSET_URL4,
12010
+ assetUrl = DEFAULT_ASSET_URL3,
12013
12011
  icon = "sword",
12014
12012
  label = "Iron Sword",
12015
12013
  quantity,
@@ -12064,7 +12062,7 @@ function ItemSlot({
12064
12062
  }
12065
12063
  );
12066
12064
  }
12067
- var sizeMap7, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL4, assetSizeMap;
12065
+ var sizeMap7, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL3, assetSizeMap;
12068
12066
  var init_ItemSlot = __esm({
12069
12067
  "components/game/2d/atoms/ItemSlot.tsx"() {
12070
12068
  "use client";
@@ -12094,7 +12092,7 @@ var init_ItemSlot = __esm({
12094
12092
  epic: "shadow-lg",
12095
12093
  legendary: "shadow-lg"
12096
12094
  };
12097
- DEFAULT_ASSET_URL4 = {
12095
+ DEFAULT_ASSET_URL3 = {
12098
12096
  url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
12099
12097
  role: "item",
12100
12098
  category: "item"
@@ -12108,7 +12106,7 @@ var init_ItemSlot = __esm({
12108
12106
  }
12109
12107
  });
12110
12108
  function TurnIndicator({
12111
- assetUrl = DEFAULT_ASSET_URL5,
12109
+ assetUrl = DEFAULT_ASSET_URL4,
12112
12110
  currentTurn = 1,
12113
12111
  maxTurns,
12114
12112
  activeTeam,
@@ -12148,7 +12146,7 @@ function TurnIndicator({
12148
12146
  }
12149
12147
  );
12150
12148
  }
12151
- var sizeMap8, DEFAULT_ASSET_URL5;
12149
+ var sizeMap8, DEFAULT_ASSET_URL4;
12152
12150
  var init_TurnIndicator = __esm({
12153
12151
  "components/game/2d/atoms/TurnIndicator.tsx"() {
12154
12152
  init_cn();
@@ -12160,7 +12158,7 @@ var init_TurnIndicator = __esm({
12160
12158
  md: { wrapper: "text-sm gap-2 px-3 py-1", dot: "w-2 h-2" },
12161
12159
  lg: { wrapper: "text-base gap-2.5 px-4 py-1.5", dot: "w-2.5 h-2.5" }
12162
12160
  };
12163
- DEFAULT_ASSET_URL5 = {
12161
+ DEFAULT_ASSET_URL4 = {
12164
12162
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/symbol_01.png",
12165
12163
  role: "ui",
12166
12164
  category: "turn"
@@ -12180,7 +12178,7 @@ function getComboScale(combo) {
12180
12178
  return "";
12181
12179
  }
12182
12180
  function ComboCounter({
12183
- assetUrl = DEFAULT_ASSET_URL6,
12181
+ assetUrl = DEFAULT_ASSET_URL5,
12184
12182
  combo = 5,
12185
12183
  multiplier,
12186
12184
  streak,
@@ -12215,14 +12213,14 @@ function ComboCounter({
12215
12213
  }
12216
12214
  );
12217
12215
  }
12218
- var DEFAULT_ASSET_URL6, sizeMap9;
12216
+ var DEFAULT_ASSET_URL5, sizeMap9;
12219
12217
  var init_ComboCounter = __esm({
12220
12218
  "components/game/2d/atoms/ComboCounter.tsx"() {
12221
12219
  init_cn();
12222
12220
  init_Box();
12223
12221
  init_Typography();
12224
12222
  init_GameIcon();
12225
- DEFAULT_ASSET_URL6 = {
12223
+ DEFAULT_ASSET_URL5 = {
12226
12224
  url: "https://almadar-kflow-assets.web.app/shared/effects/flash/flash00.png",
12227
12225
  role: "effect",
12228
12226
  category: "effect"
@@ -12236,7 +12234,7 @@ var init_ComboCounter = __esm({
12236
12234
  }
12237
12235
  });
12238
12236
  function WaypointMarker({
12239
- assetUrl = DEFAULT_ASSET_URL7,
12237
+ assetUrl = DEFAULT_ASSET_URL6,
12240
12238
  label,
12241
12239
  icon,
12242
12240
  active = true,
@@ -12296,7 +12294,7 @@ function WaypointMarker({
12296
12294
  )
12297
12295
  ] });
12298
12296
  }
12299
- var DEFAULT_ASSET_URL7, sizeMap10, checkIcon;
12297
+ var DEFAULT_ASSET_URL6, sizeMap10, checkIcon;
12300
12298
  var init_WaypointMarker = __esm({
12301
12299
  "components/game/2d/atoms/WaypointMarker.tsx"() {
12302
12300
  init_cn();
@@ -12304,7 +12302,7 @@ var init_WaypointMarker = __esm({
12304
12302
  init_Box();
12305
12303
  init_Typography();
12306
12304
  init_GameIcon();
12307
- DEFAULT_ASSET_URL7 = {
12305
+ DEFAULT_ASSET_URL6 = {
12308
12306
  url: "https://almadar-kflow-assets.web.app/shared/world-map/battle_marker.png",
12309
12307
  role: "ui",
12310
12308
  category: "waypoint"
@@ -12325,7 +12323,7 @@ function formatDuration(seconds) {
12325
12323
  return `${Math.round(seconds)}s`;
12326
12324
  }
12327
12325
  function StatusEffect({
12328
- assetUrl = DEFAULT_ASSET_URL8,
12326
+ assetUrl = DEFAULT_ASSET_URL7,
12329
12327
  icon,
12330
12328
  label = "Shield",
12331
12329
  duration = 30,
@@ -12376,7 +12374,7 @@ function StatusEffect({
12376
12374
  label && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-xs text-muted-foreground mt-0.5 text-center whitespace-nowrap", children: label })
12377
12375
  ] });
12378
12376
  }
12379
- var DEFAULT_ASSET_URL8, sizeMap11, variantStyles7;
12377
+ var DEFAULT_ASSET_URL7, sizeMap11, variantStyles7;
12380
12378
  var init_StatusEffect = __esm({
12381
12379
  "components/game/2d/atoms/StatusEffect.tsx"() {
12382
12380
  init_cn();
@@ -12384,7 +12382,7 @@ var init_StatusEffect = __esm({
12384
12382
  init_Box();
12385
12383
  init_Typography();
12386
12384
  init_GameIcon();
12387
- DEFAULT_ASSET_URL8 = {
12385
+ DEFAULT_ASSET_URL7 = {
12388
12386
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png",
12389
12387
  role: "ui",
12390
12388
  category: "effect"
@@ -12403,7 +12401,7 @@ var init_StatusEffect = __esm({
12403
12401
  }
12404
12402
  });
12405
12403
  function DamageNumber({
12406
- assetUrl = DEFAULT_ASSET_URL9,
12404
+ assetUrl = DEFAULT_ASSET_URL8,
12407
12405
  value = 42,
12408
12406
  type = "damage",
12409
12407
  size = "md",
@@ -12431,7 +12429,7 @@ function DamageNumber({
12431
12429
  )
12432
12430
  ] });
12433
12431
  }
12434
- var sizeMap12, typeStyles, floatKeyframes, DEFAULT_ASSET_URL9;
12432
+ var sizeMap12, typeStyles, floatKeyframes, DEFAULT_ASSET_URL8;
12435
12433
  var init_DamageNumber = __esm({
12436
12434
  "components/game/2d/atoms/DamageNumber.tsx"() {
12437
12435
  init_cn();
@@ -12455,7 +12453,7 @@ var init_DamageNumber = __esm({
12455
12453
  100% { opacity: 0; transform: translateY(-32px) scale(0.8); }
12456
12454
  }
12457
12455
  `;
12458
- DEFAULT_ASSET_URL9 = {
12456
+ DEFAULT_ASSET_URL8 = {
12459
12457
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/spark_01.png",
12460
12458
  role: "effect",
12461
12459
  category: "effect"
@@ -12581,7 +12579,7 @@ var init_ChoiceButton = __esm({
12581
12579
  }
12582
12580
  });
12583
12581
  function ActionButton({
12584
- assetUrl = DEFAULT_ASSET_URL10,
12582
+ assetUrl = DEFAULT_ASSET_URL9,
12585
12583
  label = "Attack",
12586
12584
  icon,
12587
12585
  cooldown = 0,
@@ -12650,7 +12648,7 @@ function ActionButton({
12650
12648
  }
12651
12649
  );
12652
12650
  }
12653
- var sizeMap13, variantStyles8, DEFAULT_ASSET_URL10;
12651
+ var sizeMap13, variantStyles8, DEFAULT_ASSET_URL9;
12654
12652
  var init_ActionButton = __esm({
12655
12653
  "components/game/2d/atoms/ActionButton.tsx"() {
12656
12654
  init_cn();
@@ -12670,7 +12668,7 @@ var init_ActionButton = __esm({
12670
12668
  secondary: "bg-secondary text-secondary-foreground hover:bg-secondary-hover border-border",
12671
12669
  danger: "bg-error text-error-foreground hover:bg-error/90 border-error"
12672
12670
  };
12673
- DEFAULT_ASSET_URL10 = {
12671
+ DEFAULT_ASSET_URL9 = {
12674
12672
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/slash_01.png",
12675
12673
  role: "ui",
12676
12674
  category: "action"
@@ -12890,15 +12888,17 @@ function ControlGrid({
12890
12888
  },
12891
12889
  d
12892
12890
  );
12891
+ const usesSemantic = !!directionEvents;
12892
+ const cell = (d) => !usesSemantic || directionEvents?.[d] ? dir(d) : /* @__PURE__ */ jsxRuntime.jsx(Box, {}, d);
12893
12893
  return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("inline-grid grid-cols-3", ds.gap, ds.container, className), children: [
12894
12894
  /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
12895
- dir("up"),
12895
+ cell("up"),
12896
12896
  /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
12897
- dir("left"),
12897
+ cell("left"),
12898
12898
  /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-6 h-6 rounded-interactive bg-muted border-2 border-muted-foreground" }) }),
12899
- dir("right"),
12899
+ cell("right"),
12900
12900
  /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
12901
- dir("down"),
12901
+ cell("down"),
12902
12902
  /* @__PURE__ */ jsxRuntime.jsx(Box, {})
12903
12903
  ] });
12904
12904
  }
@@ -53703,6 +53703,7 @@ var crossTraitLog = logger.createLogger("almadar:ui:cross-trait");
53703
53703
  var flushLog = logger.createLogger("almadar:ui:slot-flush");
53704
53704
  var stateLog = logger.createLogger("almadar:ui:state-transitions");
53705
53705
  var tickLog = logger.createLogger("almadar:ui:tick-effects");
53706
+ logger.setNamespaceLevel("almadar:ui:tick-effects", "WARN");
53706
53707
  var SYNC_TICK_OPERATORS = /* @__PURE__ */ new Set([
53707
53708
  "set",
53708
53709
  "emit",
@@ -54122,8 +54123,15 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
54122
54123
  const scheduler = runtime.createTickScheduler();
54123
54124
  for (const binding of traitBindings) {
54124
54125
  for (const tick of binding.trait.ticks ?? []) {
54125
- const intervalMs = tick.interval === "frame" ? 0 : tick.interval;
54126
- scheduler.add(intervalMs, () => runTickEffects(tick, binding));
54126
+ if (tick.interval === "frame") {
54127
+ scheduler.add(0, () => runTickEffects(tick, binding));
54128
+ } else if (typeof tick.interval === "number") {
54129
+ scheduler.add(tick.interval, () => runTickEffects(tick, binding));
54130
+ } else if (runtime.isValidCronExpression(tick.interval)) {
54131
+ scheduler.addCron(tick.interval, () => runTickEffects(tick, binding));
54132
+ } else {
54133
+ scheduler.add(runtime.parseDurationString(tick.interval), () => runTickEffects(tick, binding));
54134
+ }
54127
54135
  }
54128
54136
  }
54129
54137
  return () => scheduler.stopAll();
package/dist/avl/index.js CHANGED
@@ -2,7 +2,7 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import * as React105 from 'react';
3
3
  import React105__default, { createContext, useState, useMemo, useRef, useEffect, useContext, useCallback, Suspense, useLayoutEffect, Profiler, useReducer, useSyncExternalStore, lazy, useId } from 'react';
4
4
  import { getAllPages, OrbitalProvider, EventBusContext, useTraitScope, ServerBridgeProvider, VerificationProvider, EntitySchemaProvider, OrbitalThemeProvider, useServerBridge, useEntitySchema, useEntitySchemaOptional, TraitScopeProvider, useCurrentPagePath } from '@almadar/ui/providers';
5
- import { createLogger, isLogLevelEnabled } from '@almadar/logger';
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';
8
8
  import { useTranslate } from '@almadar/ui/hooks';
@@ -41,7 +41,7 @@ import { sortableKeyboardCoordinates, useSortable, arrayMove, SortableContext, r
41
41
  import { CSS } from '@dnd-kit/utilities';
42
42
  import { getPatternDefinition, getComponentForPattern as getComponentForPattern$1, isEntityAwarePattern } from '@almadar/patterns';
43
43
  import { OrbitalServerRuntime } from '@almadar/runtime/OrbitalServerRuntime';
44
- import { InMemoryPersistence, StateMachineManager, collectDeclaredConfigDefaults, createServerEffectHandlers, EffectExecutor, createContextFromBindings, createTickScheduler } from '@almadar/runtime';
44
+ import { InMemoryPersistence, StateMachineManager, collectDeclaredConfigDefaults, createServerEffectHandlers, EffectExecutor, createContextFromBindings, createTickScheduler, isValidCronExpression, parseDurationString } from '@almadar/runtime';
45
45
 
46
46
  var __defProp = Object.defineProperty;
47
47
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -10920,11 +10920,14 @@ function recordTransition(trace) {
10920
10920
  }
10921
10921
  if (entry.event === "INIT") {
10922
10922
  const hasFetch = entry.effects.some((e) => e.type === "fetch");
10923
+ const hasEntitySeed = entry.effects.some(
10924
+ (e) => e.type === "set" && typeof e.args[0] === "string" && e.args[0].startsWith("@entity.")
10925
+ );
10923
10926
  const checkId = `init-fetch-${entry.traitName}`;
10924
- if (hasFetch) {
10927
+ if (hasFetch || hasEntitySeed) {
10925
10928
  registerCheck(
10926
10929
  checkId,
10927
- `INIT transition for "${entry.traitName}" has fetch effect`,
10930
+ `INIT transition for "${entry.traitName}" has fetch or entity-seed effect`,
10928
10931
  "pass"
10929
10932
  );
10930
10933
  } else {
@@ -11579,7 +11582,7 @@ var init_ScoreDisplay = __esm({
11579
11582
  }
11580
11583
  });
11581
11584
  function ControlButton({
11582
- assetUrl = DEFAULT_ASSET_URL,
11585
+ assetUrl,
11583
11586
  label,
11584
11587
  icon,
11585
11588
  size = "md",
@@ -11657,7 +11660,7 @@ function ControlButton({
11657
11660
  }
11658
11661
  );
11659
11662
  }
11660
- var sizeMap4, shapeMap, variantMap, DEFAULT_ASSET_URL;
11663
+ var sizeMap4, shapeMap, variantMap;
11661
11664
  var init_ControlButton = __esm({
11662
11665
  "components/game/2d/atoms/ControlButton.tsx"() {
11663
11666
  "use client";
@@ -11684,11 +11687,6 @@ var init_ControlButton = __esm({
11684
11687
  secondary: "bg-secondary text-secondary-foreground border-border hover:bg-secondary-hover",
11685
11688
  ghost: "bg-transparent text-foreground border-border hover:bg-muted"
11686
11689
  };
11687
- DEFAULT_ASSET_URL = {
11688
- url: "https://almadar-kflow-assets.web.app/shared/effects/particles/circle_01.png",
11689
- role: "ui",
11690
- category: "control"
11691
- };
11692
11690
  ControlButton.displayName = "ControlButton";
11693
11691
  }
11694
11692
  });
@@ -11777,7 +11775,7 @@ function isKnownState(s) {
11777
11775
  return s in DEFAULT_STATE_STYLES;
11778
11776
  }
11779
11777
  function StateIndicator({
11780
- assetUrl = DEFAULT_ASSET_URL2,
11778
+ assetUrl = DEFAULT_ASSET_URL,
11781
11779
  state = "idle",
11782
11780
  label,
11783
11781
  size = "md",
@@ -11807,14 +11805,14 @@ function StateIndicator({
11807
11805
  }
11808
11806
  );
11809
11807
  }
11810
- var DEFAULT_ASSET_URL2, DEFAULT_STATE_STYLES, DEFAULT_STYLE, STATIC_STATES, SIZE_CLASSES;
11808
+ var DEFAULT_ASSET_URL, DEFAULT_STATE_STYLES, DEFAULT_STYLE, STATIC_STATES, SIZE_CLASSES;
11811
11809
  var init_StateIndicator = __esm({
11812
11810
  "components/game/2d/atoms/StateIndicator.tsx"() {
11813
11811
  init_Box();
11814
11812
  init_Icon();
11815
11813
  init_cn();
11816
11814
  init_GameIcon();
11817
- DEFAULT_ASSET_URL2 = {
11815
+ DEFAULT_ASSET_URL = {
11818
11816
  url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
11819
11817
  role: "ui",
11820
11818
  category: "state"
@@ -11900,7 +11898,7 @@ var init_TimerDisplay = __esm({
11900
11898
  }
11901
11899
  });
11902
11900
  function ResourceCounter({
11903
- assetUrl = DEFAULT_ASSET_URL3,
11901
+ assetUrl = DEFAULT_ASSET_URL2,
11904
11902
  icon,
11905
11903
  label = "Gold",
11906
11904
  value = 250,
@@ -11933,7 +11931,7 @@ function ResourceCounter({
11933
11931
  }
11934
11932
  );
11935
11933
  }
11936
- var colorTokenClasses2, DEFAULT_ASSET_URL3, sizeMap6;
11934
+ var colorTokenClasses2, DEFAULT_ASSET_URL2, sizeMap6;
11937
11935
  var init_ResourceCounter = __esm({
11938
11936
  "components/game/2d/atoms/ResourceCounter.tsx"() {
11939
11937
  init_cn();
@@ -11949,7 +11947,7 @@ var init_ResourceCounter = __esm({
11949
11947
  error: "text-error",
11950
11948
  muted: "text-muted-foreground"
11951
11949
  };
11952
- DEFAULT_ASSET_URL3 = {
11950
+ DEFAULT_ASSET_URL2 = {
11953
11951
  url: "https://almadar-kflow-assets.web.app/shared/world-map/gold_mine.png",
11954
11952
  role: "ui",
11955
11953
  category: "coin"
@@ -11963,7 +11961,7 @@ var init_ResourceCounter = __esm({
11963
11961
  }
11964
11962
  });
11965
11963
  function ItemSlot({
11966
- assetUrl = DEFAULT_ASSET_URL4,
11964
+ assetUrl = DEFAULT_ASSET_URL3,
11967
11965
  icon = "sword",
11968
11966
  label = "Iron Sword",
11969
11967
  quantity,
@@ -12018,7 +12016,7 @@ function ItemSlot({
12018
12016
  }
12019
12017
  );
12020
12018
  }
12021
- var sizeMap7, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL4, assetSizeMap;
12019
+ var sizeMap7, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL3, assetSizeMap;
12022
12020
  var init_ItemSlot = __esm({
12023
12021
  "components/game/2d/atoms/ItemSlot.tsx"() {
12024
12022
  "use client";
@@ -12048,7 +12046,7 @@ var init_ItemSlot = __esm({
12048
12046
  epic: "shadow-lg",
12049
12047
  legendary: "shadow-lg"
12050
12048
  };
12051
- DEFAULT_ASSET_URL4 = {
12049
+ DEFAULT_ASSET_URL3 = {
12052
12050
  url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
12053
12051
  role: "item",
12054
12052
  category: "item"
@@ -12062,7 +12060,7 @@ var init_ItemSlot = __esm({
12062
12060
  }
12063
12061
  });
12064
12062
  function TurnIndicator({
12065
- assetUrl = DEFAULT_ASSET_URL5,
12063
+ assetUrl = DEFAULT_ASSET_URL4,
12066
12064
  currentTurn = 1,
12067
12065
  maxTurns,
12068
12066
  activeTeam,
@@ -12102,7 +12100,7 @@ function TurnIndicator({
12102
12100
  }
12103
12101
  );
12104
12102
  }
12105
- var sizeMap8, DEFAULT_ASSET_URL5;
12103
+ var sizeMap8, DEFAULT_ASSET_URL4;
12106
12104
  var init_TurnIndicator = __esm({
12107
12105
  "components/game/2d/atoms/TurnIndicator.tsx"() {
12108
12106
  init_cn();
@@ -12114,7 +12112,7 @@ var init_TurnIndicator = __esm({
12114
12112
  md: { wrapper: "text-sm gap-2 px-3 py-1", dot: "w-2 h-2" },
12115
12113
  lg: { wrapper: "text-base gap-2.5 px-4 py-1.5", dot: "w-2.5 h-2.5" }
12116
12114
  };
12117
- DEFAULT_ASSET_URL5 = {
12115
+ DEFAULT_ASSET_URL4 = {
12118
12116
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/symbol_01.png",
12119
12117
  role: "ui",
12120
12118
  category: "turn"
@@ -12134,7 +12132,7 @@ function getComboScale(combo) {
12134
12132
  return "";
12135
12133
  }
12136
12134
  function ComboCounter({
12137
- assetUrl = DEFAULT_ASSET_URL6,
12135
+ assetUrl = DEFAULT_ASSET_URL5,
12138
12136
  combo = 5,
12139
12137
  multiplier,
12140
12138
  streak,
@@ -12169,14 +12167,14 @@ function ComboCounter({
12169
12167
  }
12170
12168
  );
12171
12169
  }
12172
- var DEFAULT_ASSET_URL6, sizeMap9;
12170
+ var DEFAULT_ASSET_URL5, sizeMap9;
12173
12171
  var init_ComboCounter = __esm({
12174
12172
  "components/game/2d/atoms/ComboCounter.tsx"() {
12175
12173
  init_cn();
12176
12174
  init_Box();
12177
12175
  init_Typography();
12178
12176
  init_GameIcon();
12179
- DEFAULT_ASSET_URL6 = {
12177
+ DEFAULT_ASSET_URL5 = {
12180
12178
  url: "https://almadar-kflow-assets.web.app/shared/effects/flash/flash00.png",
12181
12179
  role: "effect",
12182
12180
  category: "effect"
@@ -12190,7 +12188,7 @@ var init_ComboCounter = __esm({
12190
12188
  }
12191
12189
  });
12192
12190
  function WaypointMarker({
12193
- assetUrl = DEFAULT_ASSET_URL7,
12191
+ assetUrl = DEFAULT_ASSET_URL6,
12194
12192
  label,
12195
12193
  icon,
12196
12194
  active = true,
@@ -12250,7 +12248,7 @@ function WaypointMarker({
12250
12248
  )
12251
12249
  ] });
12252
12250
  }
12253
- var DEFAULT_ASSET_URL7, sizeMap10, checkIcon;
12251
+ var DEFAULT_ASSET_URL6, sizeMap10, checkIcon;
12254
12252
  var init_WaypointMarker = __esm({
12255
12253
  "components/game/2d/atoms/WaypointMarker.tsx"() {
12256
12254
  init_cn();
@@ -12258,7 +12256,7 @@ var init_WaypointMarker = __esm({
12258
12256
  init_Box();
12259
12257
  init_Typography();
12260
12258
  init_GameIcon();
12261
- DEFAULT_ASSET_URL7 = {
12259
+ DEFAULT_ASSET_URL6 = {
12262
12260
  url: "https://almadar-kflow-assets.web.app/shared/world-map/battle_marker.png",
12263
12261
  role: "ui",
12264
12262
  category: "waypoint"
@@ -12279,7 +12277,7 @@ function formatDuration(seconds) {
12279
12277
  return `${Math.round(seconds)}s`;
12280
12278
  }
12281
12279
  function StatusEffect({
12282
- assetUrl = DEFAULT_ASSET_URL8,
12280
+ assetUrl = DEFAULT_ASSET_URL7,
12283
12281
  icon,
12284
12282
  label = "Shield",
12285
12283
  duration = 30,
@@ -12330,7 +12328,7 @@ function StatusEffect({
12330
12328
  label && /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-xs text-muted-foreground mt-0.5 text-center whitespace-nowrap", children: label })
12331
12329
  ] });
12332
12330
  }
12333
- var DEFAULT_ASSET_URL8, sizeMap11, variantStyles7;
12331
+ var DEFAULT_ASSET_URL7, sizeMap11, variantStyles7;
12334
12332
  var init_StatusEffect = __esm({
12335
12333
  "components/game/2d/atoms/StatusEffect.tsx"() {
12336
12334
  init_cn();
@@ -12338,7 +12336,7 @@ var init_StatusEffect = __esm({
12338
12336
  init_Box();
12339
12337
  init_Typography();
12340
12338
  init_GameIcon();
12341
- DEFAULT_ASSET_URL8 = {
12339
+ DEFAULT_ASSET_URL7 = {
12342
12340
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png",
12343
12341
  role: "ui",
12344
12342
  category: "effect"
@@ -12357,7 +12355,7 @@ var init_StatusEffect = __esm({
12357
12355
  }
12358
12356
  });
12359
12357
  function DamageNumber({
12360
- assetUrl = DEFAULT_ASSET_URL9,
12358
+ assetUrl = DEFAULT_ASSET_URL8,
12361
12359
  value = 42,
12362
12360
  type = "damage",
12363
12361
  size = "md",
@@ -12385,7 +12383,7 @@ function DamageNumber({
12385
12383
  )
12386
12384
  ] });
12387
12385
  }
12388
- var sizeMap12, typeStyles, floatKeyframes, DEFAULT_ASSET_URL9;
12386
+ var sizeMap12, typeStyles, floatKeyframes, DEFAULT_ASSET_URL8;
12389
12387
  var init_DamageNumber = __esm({
12390
12388
  "components/game/2d/atoms/DamageNumber.tsx"() {
12391
12389
  init_cn();
@@ -12409,7 +12407,7 @@ var init_DamageNumber = __esm({
12409
12407
  100% { opacity: 0; transform: translateY(-32px) scale(0.8); }
12410
12408
  }
12411
12409
  `;
12412
- DEFAULT_ASSET_URL9 = {
12410
+ DEFAULT_ASSET_URL8 = {
12413
12411
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/spark_01.png",
12414
12412
  role: "effect",
12415
12413
  category: "effect"
@@ -12535,7 +12533,7 @@ var init_ChoiceButton = __esm({
12535
12533
  }
12536
12534
  });
12537
12535
  function ActionButton({
12538
- assetUrl = DEFAULT_ASSET_URL10,
12536
+ assetUrl = DEFAULT_ASSET_URL9,
12539
12537
  label = "Attack",
12540
12538
  icon,
12541
12539
  cooldown = 0,
@@ -12604,7 +12602,7 @@ function ActionButton({
12604
12602
  }
12605
12603
  );
12606
12604
  }
12607
- var sizeMap13, variantStyles8, DEFAULT_ASSET_URL10;
12605
+ var sizeMap13, variantStyles8, DEFAULT_ASSET_URL9;
12608
12606
  var init_ActionButton = __esm({
12609
12607
  "components/game/2d/atoms/ActionButton.tsx"() {
12610
12608
  init_cn();
@@ -12624,7 +12622,7 @@ var init_ActionButton = __esm({
12624
12622
  secondary: "bg-secondary text-secondary-foreground hover:bg-secondary-hover border-border",
12625
12623
  danger: "bg-error text-error-foreground hover:bg-error/90 border-error"
12626
12624
  };
12627
- DEFAULT_ASSET_URL10 = {
12625
+ DEFAULT_ASSET_URL9 = {
12628
12626
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/slash_01.png",
12629
12627
  role: "ui",
12630
12628
  category: "action"
@@ -12844,15 +12842,17 @@ function ControlGrid({
12844
12842
  },
12845
12843
  d
12846
12844
  );
12845
+ const usesSemantic = !!directionEvents;
12846
+ const cell = (d) => !usesSemantic || directionEvents?.[d] ? dir(d) : /* @__PURE__ */ jsx(Box, {}, d);
12847
12847
  return /* @__PURE__ */ jsxs(Box, { className: cn("inline-grid grid-cols-3", ds.gap, ds.container, className), children: [
12848
12848
  /* @__PURE__ */ jsx(Box, {}),
12849
- dir("up"),
12849
+ cell("up"),
12850
12850
  /* @__PURE__ */ jsx(Box, {}),
12851
- dir("left"),
12851
+ cell("left"),
12852
12852
  /* @__PURE__ */ jsx(Box, { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx(Box, { className: "w-6 h-6 rounded-interactive bg-muted border-2 border-muted-foreground" }) }),
12853
- dir("right"),
12853
+ cell("right"),
12854
12854
  /* @__PURE__ */ jsx(Box, {}),
12855
- dir("down"),
12855
+ cell("down"),
12856
12856
  /* @__PURE__ */ jsx(Box, {})
12857
12857
  ] });
12858
12858
  }
@@ -53657,6 +53657,7 @@ var crossTraitLog = createLogger("almadar:ui:cross-trait");
53657
53657
  var flushLog = createLogger("almadar:ui:slot-flush");
53658
53658
  var stateLog = createLogger("almadar:ui:state-transitions");
53659
53659
  var tickLog = createLogger("almadar:ui:tick-effects");
53660
+ setNamespaceLevel("almadar:ui:tick-effects", "WARN");
53660
53661
  var SYNC_TICK_OPERATORS = /* @__PURE__ */ new Set([
53661
53662
  "set",
53662
53663
  "emit",
@@ -54076,8 +54077,15 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
54076
54077
  const scheduler = createTickScheduler();
54077
54078
  for (const binding of traitBindings) {
54078
54079
  for (const tick of binding.trait.ticks ?? []) {
54079
- const intervalMs = tick.interval === "frame" ? 0 : tick.interval;
54080
- scheduler.add(intervalMs, () => runTickEffects(tick, binding));
54080
+ if (tick.interval === "frame") {
54081
+ scheduler.add(0, () => runTickEffects(tick, binding));
54082
+ } else if (typeof tick.interval === "number") {
54083
+ scheduler.add(tick.interval, () => runTickEffects(tick, binding));
54084
+ } else if (isValidCronExpression(tick.interval)) {
54085
+ scheduler.addCron(tick.interval, () => runTickEffects(tick, binding));
54086
+ } else {
54087
+ scheduler.add(parseDurationString(tick.interval), () => runTickEffects(tick, binding));
54088
+ }
54081
54089
  }
54082
54090
  }
54083
54091
  return () => scheduler.stopAll();