@almadar/ui 5.53.0 → 5.55.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.
package/dist/avl/index.js CHANGED
@@ -12160,6 +12160,16 @@ var init_Skeleton = __esm({
12160
12160
  Skeleton.displayName = "Skeleton";
12161
12161
  }
12162
12162
  });
12163
+ function isKnownPattern(type) {
12164
+ return type in componentMapping;
12165
+ }
12166
+ var componentMapping;
12167
+ var init_pattern_resolver = __esm({
12168
+ "renderer/pattern-resolver.ts"() {
12169
+ createLogger("almadar:ui:pattern-resolver");
12170
+ componentMapping = {};
12171
+ }
12172
+ });
12163
12173
 
12164
12174
  // renderer/slot-definitions.ts
12165
12175
  function isPortalSlot(slot) {
@@ -12268,6 +12278,7 @@ var init_navigation = __esm({
12268
12278
  // renderer/index.ts
12269
12279
  var init_renderer = __esm({
12270
12280
  "renderer/index.ts"() {
12281
+ init_pattern_resolver();
12271
12282
  init_slot_definitions();
12272
12283
  }
12273
12284
  });
@@ -13971,7 +13982,7 @@ function recordTransition(trace) {
13971
13982
  ...trace,
13972
13983
  id: `t-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
13973
13984
  };
13974
- log4.debug("transition:recorded", { trait: trace.traitName, from: trace.from, to: trace.to, event: trace.event, effectCount: trace.effects.length });
13985
+ log5.debug("transition:recorded", { trait: trace.traitName, from: trace.from, to: trace.to, event: trace.event, effectCount: trace.effects.length });
13975
13986
  getState().transitions.push(entry);
13976
13987
  if (getState().transitions.length > MAX_TRANSITIONS) {
13977
13988
  getState().transitions.shift();
@@ -14070,7 +14081,7 @@ function getTraitSnapshots() {
14070
14081
  try {
14071
14082
  snapshots.push(getter());
14072
14083
  } catch (err) {
14073
- log4.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
14084
+ log5.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
14074
14085
  }
14075
14086
  }
14076
14087
  return snapshots;
@@ -14169,10 +14180,10 @@ function updateAssetStatus(url, status) {
14169
14180
  window.__orbitalVerification.assetStatus[url] = status;
14170
14181
  }
14171
14182
  }
14172
- var log4, MAX_TRANSITIONS;
14183
+ var log5, MAX_TRANSITIONS;
14173
14184
  var init_verificationRegistry = __esm({
14174
14185
  "lib/verificationRegistry.ts"() {
14175
- log4 = createLogger("almadar:bridge");
14186
+ log5 = createLogger("almadar:bridge");
14176
14187
  MAX_TRANSITIONS = 500;
14177
14188
  exposeOnWindow();
14178
14189
  }
@@ -16068,7 +16079,7 @@ function generateDiff(oldVal, newVal) {
16068
16079
  }
16069
16080
  return diff;
16070
16081
  }
16071
- var orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log5, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, CodeBlock;
16082
+ var orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log6, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, CodeBlock;
16072
16083
  var init_CodeBlock = __esm({
16073
16084
  "components/core/molecules/markdown/CodeBlock.tsx"() {
16074
16085
  init_cn();
@@ -16151,7 +16162,7 @@ var init_CodeBlock = __esm({
16151
16162
  "lolo-op-async": { color: ORB_COLORS.dark.async }
16152
16163
  };
16153
16164
  loloStyle = { ...dark, ...loloStyleOverrides };
16154
- log5 = createLogger("almadar:ui:markdown-code");
16165
+ log6 = createLogger("almadar:ui:markdown-code");
16155
16166
  CODE_LANGUAGES = [
16156
16167
  "text",
16157
16168
  "json",
@@ -16415,7 +16426,7 @@ var init_CodeBlock = __esm({
16415
16426
  eventBus.emit("UI:COPY_CODE", { language: activeLanguage, success: true });
16416
16427
  setTimeout(() => setCopied(false), 2e3);
16417
16428
  } catch (err) {
16418
- log5.error("Failed to copy code", { error: err instanceof Error ? err : String(err) });
16429
+ log6.error("Failed to copy code", { error: err instanceof Error ? err : String(err) });
16419
16430
  eventBus.emit("UI:COPY_CODE", { language: activeLanguage, success: false });
16420
16431
  }
16421
16432
  };
@@ -20296,14 +20307,14 @@ function useSafeEventBus2() {
20296
20307
  } };
20297
20308
  }
20298
20309
  }
20299
- var log6, lookStyles4, ButtonGroup;
20310
+ var log7, lookStyles4, ButtonGroup;
20300
20311
  var init_ButtonGroup = __esm({
20301
20312
  "components/core/molecules/ButtonGroup.tsx"() {
20302
20313
  "use client";
20303
20314
  init_cn();
20304
20315
  init_atoms2();
20305
20316
  init_useEventBus();
20306
- log6 = createLogger("almadar:ui:button-group");
20317
+ log7 = createLogger("almadar:ui:button-group");
20307
20318
  lookStyles4 = {
20308
20319
  "right-aligned-buttons": "",
20309
20320
  "floating-bar": "fixed bottom-section left-1/2 -translate-x-1/2 shadow-elevation-toast bg-card p-card-sm rounded-container",
@@ -20384,7 +20395,7 @@ var init_ButtonGroup = __esm({
20384
20395
  {
20385
20396
  variant: "ghost",
20386
20397
  onClick: () => {
20387
- log6.debug("Filter clicked", { field: filter.field });
20398
+ log7.debug("Filter clicked", { field: filter.field });
20388
20399
  },
20389
20400
  children: filter.label
20390
20401
  },
@@ -28046,9 +28057,9 @@ function debug(...args) {
28046
28057
  const [first, ...rest] = args;
28047
28058
  const message = typeof first === "string" ? first : "<debug>";
28048
28059
  if (rest.length === 0 && typeof first === "string") {
28049
- log7.debug(message);
28060
+ log8.debug(message);
28050
28061
  } else {
28051
- log7.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
28062
+ log8.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
28052
28063
  }
28053
28064
  }
28054
28065
  function debugGroup(label) {
@@ -28076,11 +28087,11 @@ function toLogMetaValue(v) {
28076
28087
  }
28077
28088
  return String(v);
28078
28089
  }
28079
- var NAMESPACE, log7;
28090
+ var NAMESPACE, log8;
28080
28091
  var init_debug = __esm({
28081
28092
  "lib/debug.ts"() {
28082
28093
  NAMESPACE = "almadar:ui:debug";
28083
- log7 = createLogger(NAMESPACE);
28094
+ log8 = createLogger(NAMESPACE);
28084
28095
  createLogger("almadar:ui:debug:input");
28085
28096
  createLogger("almadar:ui:debug:collision");
28086
28097
  createLogger("almadar:ui:debug:physics");
@@ -31491,12 +31502,18 @@ function PlatformerCanvas({
31491
31502
  camX = Math.max(0, Math.min(px - cw / 2, ww - cw));
31492
31503
  camY = Math.max(0, Math.min(py - ch / 2 - 50, wh - ch));
31493
31504
  }
31494
- if (plats.length !== lastPlatCountRef.current) {
31505
+ const shouldDiag = plats.length !== lastPlatCountRef.current;
31506
+ if (shouldDiag) {
31495
31507
  lastPlatCountRef.current = plats.length;
31496
31508
  canvasLog.debug("draw:platforms", {
31497
31509
  platformCount: plats.length,
31498
31510
  camX,
31499
31511
  camY,
31512
+ plat0: JSON.stringify(plats[0]),
31513
+ plat2: JSON.stringify(plats[2]),
31514
+ tSpritesType: tSprites ? tSprites instanceof Map ? "Map" : typeof tSprites : "none",
31515
+ canvasW: canvas.width,
31516
+ canvasH: canvas.height,
31500
31517
  player: { x: px, y: py },
31501
31518
  worldWidth: ww,
31502
31519
  canvasWidth: cw,
@@ -31537,6 +31554,19 @@ function PlatformerCanvas({
31537
31554
  const platType = plat.type ?? "ground";
31538
31555
  const spriteUrl = tSprites?.[platType];
31539
31556
  const tileImg = spriteUrl ? loadImage(spriteUrl) : null;
31557
+ if (shouldDiag) {
31558
+ canvasLog.debug("plat:draw", {
31559
+ platType,
31560
+ platX,
31561
+ platY,
31562
+ w: plat.width,
31563
+ h: plat.height,
31564
+ branch: tileImg ? "tile" : "color",
31565
+ natW: tileImg?.naturalWidth,
31566
+ natH: tileImg?.naturalHeight,
31567
+ spriteUrl: spriteUrl ?? null
31568
+ });
31569
+ }
31540
31570
  if (tileImg) {
31541
31571
  const tileW = tileImg.naturalWidth;
31542
31572
  const tileH = tileImg.naturalHeight;
@@ -43943,11 +43973,11 @@ var init_Canvas3DErrorBoundary = __esm({
43943
43973
  "components/game/molecules/three/components/Canvas3DErrorBoundary.css"() {
43944
43974
  }
43945
43975
  });
43946
- var log8, Canvas3DErrorBoundary;
43976
+ var log9, Canvas3DErrorBoundary;
43947
43977
  var init_Canvas3DErrorBoundary2 = __esm({
43948
43978
  "components/game/molecules/three/components/Canvas3DErrorBoundary.tsx"() {
43949
43979
  init_Canvas3DErrorBoundary();
43950
- log8 = createLogger("almadar:ui:game:canvas3d:error-boundary");
43980
+ log9 = createLogger("almadar:ui:game:canvas3d:error-boundary");
43951
43981
  Canvas3DErrorBoundary = class extends Component {
43952
43982
  constructor(props) {
43953
43983
  super(props);
@@ -43975,8 +44005,8 @@ var init_Canvas3DErrorBoundary2 = __esm({
43975
44005
  componentDidCatch(error, errorInfo) {
43976
44006
  this.setState({ errorInfo });
43977
44007
  this.props.onError?.(error, errorInfo);
43978
- log8.error("Error caught", { error });
43979
- log8.error("Component stack", { componentStack: errorInfo.componentStack ?? "<none>" });
44008
+ log9.error("Error caught", { error });
44009
+ log9.error("Component stack", { componentStack: errorInfo.componentStack ?? "<none>" });
43980
44010
  }
43981
44011
  render() {
43982
44012
  if (this.state.hasError) {
@@ -44039,7 +44069,7 @@ function useGLTFModel(url, resourceBasePath) {
44039
44069
  setState({ model: null, isLoading: false, error: null });
44040
44070
  return;
44041
44071
  }
44042
- log9.debug("Loading", { url });
44072
+ log10.debug("Loading", { url });
44043
44073
  setState((prev) => ({ ...prev, isLoading: true, error: null }));
44044
44074
  const assetRoot = resourceBasePath || detectAssetRoot2(url);
44045
44075
  const loader = new GLTFLoader$1();
@@ -44047,7 +44077,7 @@ function useGLTFModel(url, resourceBasePath) {
44047
44077
  loader.load(
44048
44078
  url,
44049
44079
  (gltf) => {
44050
- log9.debug("Loaded", { url });
44080
+ log10.debug("Loaded", { url });
44051
44081
  setState({
44052
44082
  model: gltf.scene,
44053
44083
  isLoading: false,
@@ -44056,7 +44086,7 @@ function useGLTFModel(url, resourceBasePath) {
44056
44086
  },
44057
44087
  void 0,
44058
44088
  (err) => {
44059
- log9.warn("Failed", { url, error: err instanceof Error ? err : String(err) });
44089
+ log10.warn("Failed", { url, error: err instanceof Error ? err : String(err) });
44060
44090
  setState({
44061
44091
  model: null,
44062
44092
  isLoading: false,
@@ -44172,11 +44202,11 @@ function ModelLoader({
44172
44202
  }
44173
44203
  );
44174
44204
  }
44175
- var log9;
44205
+ var log10;
44176
44206
  var init_ModelLoader = __esm({
44177
44207
  "components/game/molecules/three/components/ModelLoader.tsx"() {
44178
44208
  "use client";
44179
- log9 = createLogger("almadar:ui:game:model-loader");
44209
+ log10 = createLogger("almadar:ui:game:model-loader");
44180
44210
  }
44181
44211
  });
44182
44212
 
@@ -48481,7 +48511,7 @@ function getAllEvents(traits2) {
48481
48511
  function EventDispatcherTab({ traits: traits2, schema }) {
48482
48512
  const eventBus = useEventBus();
48483
48513
  const { t } = useTranslate();
48484
- const [log15, setLog] = React90.useState([]);
48514
+ const [log16, setLog] = React90.useState([]);
48485
48515
  const prevStatesRef = React90.useRef(/* @__PURE__ */ new Map());
48486
48516
  React90.useEffect(() => {
48487
48517
  for (const trait of traits2) {
@@ -48545,9 +48575,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
48545
48575
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.otherEvents") }),
48546
48576
  /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: unavailableEvents.map((event) => /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", className: "opacity-50", children: event }, event)) })
48547
48577
  ] }),
48548
- log15.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
48578
+ log16.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
48549
48579
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.recentTransitions") }),
48550
- /* @__PURE__ */ jsx(Stack, { gap: "xs", children: log15.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
48580
+ /* @__PURE__ */ jsx(Stack, { gap: "xs", children: log16.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
48551
48581
  /* @__PURE__ */ jsx("span", { className: "text-purple-400", children: entry.traitName }),
48552
48582
  " ",
48553
48583
  /* @__PURE__ */ jsx("span", { className: "text-gray-500", children: entry.from }),
@@ -53412,7 +53442,7 @@ function isPatternConfig(value) {
53412
53442
  if (value instanceof Date) return false;
53413
53443
  if (typeof value === "function") return false;
53414
53444
  const record = value;
53415
- return "type" in record && typeof record.type === "string";
53445
+ return "type" in record && typeof record.type === "string" && isKnownPattern(record.type);
53416
53446
  }
53417
53447
  function isPlainConfigObject(value) {
53418
53448
  if (React90__default.isValidElement(value)) return false;
@@ -57324,7 +57354,7 @@ function convertObjectProps(props) {
57324
57354
  function convertFnFormLambdasInProps(props) {
57325
57355
  return convertObjectProps(props);
57326
57356
  }
57327
- var log10 = createLogger("almadar:ui:effects:client-handlers");
57357
+ var log11 = createLogger("almadar:ui:effects:client-handlers");
57328
57358
  function createClientEffectHandlers(options) {
57329
57359
  const { eventBus, slotSetter, navigate, notify, callService, liveEntity } = options;
57330
57360
  return {
@@ -57333,11 +57363,11 @@ function createClientEffectHandlers(options) {
57333
57363
  eventBus.emit(prefixedEvent, payload);
57334
57364
  },
57335
57365
  persist: async () => {
57336
- log10.warn("persist is server-side only, ignored on client");
57366
+ log11.warn("persist is server-side only, ignored on client");
57337
57367
  },
57338
57368
  set: (_entityId, field, value) => {
57339
57369
  if (!liveEntity) {
57340
- log10.warn("set is server-side only, ignored on client (no live entity)");
57370
+ log11.warn("set is server-side only, ignored on client (no live entity)");
57341
57371
  return;
57342
57372
  }
57343
57373
  liveEntity[field] = value;
@@ -57369,10 +57399,10 @@ function createClientEffectHandlers(options) {
57369
57399
  slotSetter.addPattern(slot, pattern, props);
57370
57400
  },
57371
57401
  navigate: navigate ?? ((path) => {
57372
- log10.warn("No navigate handler, ignoring", { path });
57402
+ log11.warn("No navigate handler, ignoring", { path });
57373
57403
  }),
57374
57404
  notify: notify ?? ((msg, type) => {
57375
- log10.debug("notify", { type, message: msg });
57405
+ log11.debug("notify", { type, message: msg });
57376
57406
  })
57377
57407
  };
57378
57408
  }
@@ -57604,7 +57634,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
57604
57634
  };
57605
57635
  }, [traitBindings]);
57606
57636
  const executeTransitionEffects = useCallback(async (params) => {
57607
- const { binding, previousState, newState, payload, flushEvent, syncOnly, log: log15 } = params;
57637
+ const { binding, previousState, newState, payload, flushEvent, syncOnly, log: log16 } = params;
57608
57638
  const traitName = binding.trait.name;
57609
57639
  const linkedEntity = binding.linkedEntity || "";
57610
57640
  const entityId = payload?.entityId;
@@ -57692,7 +57722,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
57692
57722
  ...handlers,
57693
57723
  set: async (targetId, field, value) => {
57694
57724
  if (baseSet) await baseSet(targetId, field, value);
57695
- log15.debug("set:write", {
57725
+ log16.debug("set:write", {
57696
57726
  traitName,
57697
57727
  field,
57698
57728
  value: JSON.stringify(value),
@@ -57732,7 +57762,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
57732
57762
  const executor = new EffectExecutor({ handlers: trackingHandlers, bindings: bindingCtx, context: effectContext });
57733
57763
  try {
57734
57764
  await executor.executeAll(effects);
57735
- log15.debug("effects:executed", () => ({
57765
+ log16.debug("effects:executed", () => ({
57736
57766
  traitName,
57737
57767
  transition: `${previousState}->${newState}`,
57738
57768
  event: flushEvent,
@@ -57742,7 +57772,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
57742
57772
  slotsTouched: Array.from(pendingSlots.keys()).join(",")
57743
57773
  }));
57744
57774
  for (const [slot, patterns] of pendingSlots) {
57745
- log15.debug("flush:slot", {
57775
+ log16.debug("flush:slot", {
57746
57776
  traitName,
57747
57777
  slot,
57748
57778
  patternCount: patterns.length,
@@ -57757,7 +57787,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
57757
57787
  });
57758
57788
  }
57759
57789
  } catch (error) {
57760
- log15.error("effects:error", {
57790
+ log16.error("effects:error", {
57761
57791
  traitName,
57762
57792
  transition: `${previousState}->${newState}`,
57763
57793
  event: flushEvent,
@@ -58749,7 +58779,7 @@ OrbitalThemeProvider.displayName = "OrbitalThemeProvider";
58749
58779
  init_navigation();
58750
58780
  init_verificationRegistry();
58751
58781
  var PERF_NAMESPACE = "almadar:perf:canvas";
58752
- var log12 = createLogger(PERF_NAMESPACE);
58782
+ var log13 = createLogger(PERF_NAMESPACE);
58753
58783
  var RING_SIZE = 50;
58754
58784
  var ring = [];
58755
58785
  var writeIdx = 0;
@@ -58800,7 +58830,7 @@ function perfEnd(name, startToken, detail) {
58800
58830
  }
58801
58831
  }
58802
58832
  push({ name, durationMs, ts: endTs, detail });
58803
- log12.debug(name, () => ({ durationMs, ...detail ?? {} }));
58833
+ log13.debug(name, () => ({ durationMs, ...detail ?? {} }));
58804
58834
  }
58805
58835
  var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
58806
58836
  if (!isEnabled()) return;
@@ -58810,7 +58840,7 @@ var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, com
58810
58840
  ts: commitTime,
58811
58841
  detail: { baseDuration }
58812
58842
  });
58813
- log12.debug(`profiler:${id}:${phase}`, () => ({ actualDuration, baseDuration }));
58843
+ log13.debug(`profiler:${id}:${phase}`, () => ({ actualDuration, baseDuration }));
58814
58844
  };
58815
58845
 
58816
58846
  // runtime/prepareSchemaForPreview.ts
@@ -59453,7 +59483,7 @@ init_useEventBus();
59453
59483
  // components/avl/molecules/useCanvasDnd.tsx
59454
59484
  init_useEventBus();
59455
59485
  init_useAlmadarDndCollision();
59456
- var log13 = createLogger("almadar:ui:canvas-dnd");
59486
+ var log14 = createLogger("almadar:ui:canvas-dnd");
59457
59487
  function useCanvasDraggable({
59458
59488
  id,
59459
59489
  payload,
@@ -59492,7 +59522,7 @@ function defaultEmit(eventBus, drop) {
59492
59522
  if (payload.kind === "pattern") {
59493
59523
  const patternType = payload.data.type;
59494
59524
  if (typeof patternType !== "string") {
59495
- log13.warn("default-emit:pattern:missing-type");
59525
+ log14.warn("default-emit:pattern:missing-type");
59496
59526
  return;
59497
59527
  }
59498
59528
  const out = { patternType, containerNode: target.containerNode };
@@ -59501,23 +59531,23 @@ function defaultEmit(eventBus, drop) {
59501
59531
  out.index = resolved.index;
59502
59532
  }
59503
59533
  eventBus.emit("UI:PATTERN_DROP", out);
59504
- log13.info("default-emit:pattern", { patternType, level: target.level });
59534
+ log14.info("default-emit:pattern", { patternType, level: target.level });
59505
59535
  return;
59506
59536
  }
59507
59537
  if (payload.kind === "behavior") {
59508
59538
  const behaviorName = payload.data.name;
59509
59539
  if (typeof behaviorName !== "string") {
59510
- log13.warn("default-emit:behavior:missing-name");
59540
+ log14.warn("default-emit:behavior:missing-name");
59511
59541
  return;
59512
59542
  }
59513
59543
  eventBus.emit("UI:BEHAVIOR_DROP", {
59514
59544
  behaviorName,
59515
59545
  containerNode: target.containerNode
59516
59546
  });
59517
- log13.info("default-emit:behavior", { behaviorName, level: target.level });
59547
+ log14.info("default-emit:behavior", { behaviorName, level: target.level });
59518
59548
  return;
59519
59549
  }
59520
- log13.debug("default-emit:unhandled-kind", { kind: payload.kind });
59550
+ log14.debug("default-emit:unhandled-kind", { kind: payload.kind });
59521
59551
  }
59522
59552
  function CanvasDndProvider({
59523
59553
  children,
@@ -59533,9 +59563,9 @@ function CanvasDndProvider({
59533
59563
  if (payload) {
59534
59564
  setActivePayload(payload);
59535
59565
  eventBus.emit("UI:DRAG_START", { kind: payload.kind, data: payload.data });
59536
- log13.info("dragStart", { id: e.active.id, kind: payload.kind });
59566
+ log14.info("dragStart", { id: e.active.id, kind: payload.kind });
59537
59567
  } else {
59538
- log13.warn("dragStart:missing-payload", { id: e.active.id });
59568
+ log14.warn("dragStart:missing-payload", { id: e.active.id });
59539
59569
  }
59540
59570
  }, [eventBus]);
59541
59571
  const handleDragEnd = React90__default.useCallback((e) => {
@@ -59545,7 +59575,7 @@ function CanvasDndProvider({
59545
59575
  const overData = e.over?.data.current;
59546
59576
  const target = overData?.target;
59547
59577
  const accepts = overData?.accepts;
59548
- log13.info("dragEnd", {
59578
+ log14.info("dragEnd", {
59549
59579
  activeId: e.active.id,
59550
59580
  overId: e.over?.id,
59551
59581
  hasPayload: !!payload,
@@ -59557,7 +59587,7 @@ function CanvasDndProvider({
59557
59587
  }
59558
59588
  if (!payload || !target) return;
59559
59589
  if (accepts && !accepts.includes(payload.kind)) {
59560
- log13.debug("dragEnd:rejected:kind", { kind: payload.kind, accepts: [...accepts] });
59590
+ log14.debug("dragEnd:rejected:kind", { kind: payload.kind, accepts: [...accepts] });
59561
59591
  return;
59562
59592
  }
59563
59593
  const activator = e.activatorEvent;
@@ -59569,7 +59599,7 @@ function CanvasDndProvider({
59569
59599
  }, [eventBus, onDrop]);
59570
59600
  const handleDragCancel = React90__default.useCallback(() => {
59571
59601
  setActivePayload(null);
59572
- log13.info("dragCancel");
59602
+ log14.info("dragCancel");
59573
59603
  }, []);
59574
59604
  return /* @__PURE__ */ jsxs(
59575
59605
  DndContext,
@@ -61384,7 +61414,7 @@ init_AvlTransitionLane();
61384
61414
  init_AvlSwimLane();
61385
61415
  init_types();
61386
61416
  init_avl_elk_layout();
61387
- var log14 = createLogger("almadar:ui:avl:trait-scene");
61417
+ var log15 = createLogger("almadar:ui:avl:trait-scene");
61388
61418
  var SWIM_GUTTER2 = 120;
61389
61419
  var CENTER_W2 = 360;
61390
61420
  var AvlTraitScene = ({
@@ -61397,7 +61427,7 @@ var AvlTraitScene = ({
61397
61427
  const dataKey = useMemo(() => JSON.stringify(data), [data]);
61398
61428
  useEffect(() => {
61399
61429
  computeTraitLayout(data).then(setLayout).catch((error) => {
61400
- log14.error("computeTraitLayout failed", { error: error instanceof Error ? error : String(error) });
61430
+ log15.error("computeTraitLayout failed", { error: error instanceof Error ? error : String(error) });
61401
61431
  });
61402
61432
  }, [dataKey]);
61403
61433
  if (!layout) {
@@ -7186,6 +7186,9 @@ var init_Skeleton = __esm({
7186
7186
  Skeleton.displayName = "Skeleton";
7187
7187
  }
7188
7188
  });
7189
+ function isKnownPattern(type) {
7190
+ return type in componentMapping;
7191
+ }
7189
7192
  function getKnownPatterns() {
7190
7193
  return Object.keys(componentMapping);
7191
7194
  }
@@ -7281,6 +7284,7 @@ var init_slot_definitions = __esm({
7281
7284
  // renderer/index.ts
7282
7285
  var init_renderer = __esm({
7283
7286
  "renderer/index.ts"() {
7287
+ init_pattern_resolver();
7284
7288
  init_slot_definitions();
7285
7289
  }
7286
7290
  });
@@ -29334,12 +29338,18 @@ function PlatformerCanvas({
29334
29338
  camX = Math.max(0, Math.min(px - cw / 2, ww - cw));
29335
29339
  camY = Math.max(0, Math.min(py - ch / 2 - 50, wh - ch));
29336
29340
  }
29337
- if (plats.length !== lastPlatCountRef.current) {
29341
+ const shouldDiag = plats.length !== lastPlatCountRef.current;
29342
+ if (shouldDiag) {
29338
29343
  lastPlatCountRef.current = plats.length;
29339
29344
  canvasLog.debug("draw:platforms", {
29340
29345
  platformCount: plats.length,
29341
29346
  camX,
29342
29347
  camY,
29348
+ plat0: JSON.stringify(plats[0]),
29349
+ plat2: JSON.stringify(plats[2]),
29350
+ tSpritesType: tSprites ? tSprites instanceof Map ? "Map" : typeof tSprites : "none",
29351
+ canvasW: canvas.width,
29352
+ canvasH: canvas.height,
29343
29353
  player: { x: px, y: py },
29344
29354
  worldWidth: ww,
29345
29355
  canvasWidth: cw,
@@ -29380,6 +29390,19 @@ function PlatformerCanvas({
29380
29390
  const platType = plat.type ?? "ground";
29381
29391
  const spriteUrl = tSprites?.[platType];
29382
29392
  const tileImg = spriteUrl ? loadImage(spriteUrl) : null;
29393
+ if (shouldDiag) {
29394
+ canvasLog.debug("plat:draw", {
29395
+ platType,
29396
+ platX,
29397
+ platY,
29398
+ w: plat.width,
29399
+ h: plat.height,
29400
+ branch: tileImg ? "tile" : "color",
29401
+ natW: tileImg?.naturalWidth,
29402
+ natH: tileImg?.naturalHeight,
29403
+ spriteUrl: spriteUrl ?? null
29404
+ });
29405
+ }
29383
29406
  if (tileImg) {
29384
29407
  const tileW = tileImg.naturalWidth;
29385
29408
  const tileH = tileImg.naturalHeight;
@@ -52493,7 +52516,7 @@ function isPatternConfig(value) {
52493
52516
  if (value instanceof Date) return false;
52494
52517
  if (typeof value === "function") return false;
52495
52518
  const record = value;
52496
- return "type" in record && typeof record.type === "string";
52519
+ return "type" in record && typeof record.type === "string" && isKnownPattern(record.type);
52497
52520
  }
52498
52521
  function isPlainConfigObject(value) {
52499
52522
  if (React76__namespace.default.isValidElement(value)) return false;
@@ -7140,6 +7140,9 @@ var init_Skeleton = __esm({
7140
7140
  Skeleton.displayName = "Skeleton";
7141
7141
  }
7142
7142
  });
7143
+ function isKnownPattern(type) {
7144
+ return type in componentMapping;
7145
+ }
7143
7146
  function getKnownPatterns() {
7144
7147
  return Object.keys(componentMapping);
7145
7148
  }
@@ -7235,6 +7238,7 @@ var init_slot_definitions = __esm({
7235
7238
  // renderer/index.ts
7236
7239
  var init_renderer = __esm({
7237
7240
  "renderer/index.ts"() {
7241
+ init_pattern_resolver();
7238
7242
  init_slot_definitions();
7239
7243
  }
7240
7244
  });
@@ -29288,12 +29292,18 @@ function PlatformerCanvas({
29288
29292
  camX = Math.max(0, Math.min(px - cw / 2, ww - cw));
29289
29293
  camY = Math.max(0, Math.min(py - ch / 2 - 50, wh - ch));
29290
29294
  }
29291
- if (plats.length !== lastPlatCountRef.current) {
29295
+ const shouldDiag = plats.length !== lastPlatCountRef.current;
29296
+ if (shouldDiag) {
29292
29297
  lastPlatCountRef.current = plats.length;
29293
29298
  canvasLog.debug("draw:platforms", {
29294
29299
  platformCount: plats.length,
29295
29300
  camX,
29296
29301
  camY,
29302
+ plat0: JSON.stringify(plats[0]),
29303
+ plat2: JSON.stringify(plats[2]),
29304
+ tSpritesType: tSprites ? tSprites instanceof Map ? "Map" : typeof tSprites : "none",
29305
+ canvasW: canvas.width,
29306
+ canvasH: canvas.height,
29297
29307
  player: { x: px, y: py },
29298
29308
  worldWidth: ww,
29299
29309
  canvasWidth: cw,
@@ -29334,6 +29344,19 @@ function PlatformerCanvas({
29334
29344
  const platType = plat.type ?? "ground";
29335
29345
  const spriteUrl = tSprites?.[platType];
29336
29346
  const tileImg = spriteUrl ? loadImage(spriteUrl) : null;
29347
+ if (shouldDiag) {
29348
+ canvasLog.debug("plat:draw", {
29349
+ platType,
29350
+ platX,
29351
+ platY,
29352
+ w: plat.width,
29353
+ h: plat.height,
29354
+ branch: tileImg ? "tile" : "color",
29355
+ natW: tileImg?.naturalWidth,
29356
+ natH: tileImg?.naturalHeight,
29357
+ spriteUrl: spriteUrl ?? null
29358
+ });
29359
+ }
29337
29360
  if (tileImg) {
29338
29361
  const tileW = tileImg.naturalWidth;
29339
29362
  const tileH = tileImg.naturalHeight;
@@ -52447,7 +52470,7 @@ function isPatternConfig(value) {
52447
52470
  if (value instanceof Date) return false;
52448
52471
  if (typeof value === "function") return false;
52449
52472
  const record = value;
52450
- return "type" in record && typeof record.type === "string";
52473
+ return "type" in record && typeof record.type === "string" && isKnownPattern(record.type);
52451
52474
  }
52452
52475
  function isPlainConfigObject(value) {
52453
52476
  if (React76__default.isValidElement(value)) return false;