@almadar/ui 5.112.0 → 5.114.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.
@@ -12,6 +12,8 @@ import { createPortal } from 'react-dom';
12
12
  import { useTranslate } from '@almadar/ui/hooks';
13
13
  import { useUISlots, UISlotProvider, useTheme } from '@almadar/ui/context';
14
14
  import { evaluateGuard, evaluate, createMinimalContext, executeEffects } from '@almadar/evaluator';
15
+ import { wrapCallbackForEvent, prepareSchemaForPreview, perfStore, pushPerfEntry, collectTraitRefsFromResolvedTrait, buildOrbitalsByTrait, collectEmbeddedTraits } from '@almadar/runtime/ui';
16
+ export { PERF_NAMESPACE, adjustSchemaForMockData, buildMockData, clearPerf, perfEnd, perfStart, perfTime, prepareSchemaForPreview, wrapCallbackForEvent } from '@almadar/runtime/ui';
15
17
  import { Link, Outlet, useLocation } from 'react-router-dom';
16
18
  import ELK from 'elkjs/lib/elk.bundled.js';
17
19
  import SyntaxHighlighter from 'react-syntax-highlighter/dist/esm/prism-light.js';
@@ -37,13 +39,14 @@ import ReactMarkdown from 'react-markdown';
37
39
  import remarkGfm from 'remark-gfm';
38
40
  import remarkMath from 'remark-math';
39
41
  import rehypeKatex from 'rehype-katex';
40
- import { isCircuitEvent, schemaToIR, getPage, clearSchemaCache as clearSchemaCache$1, isEntityCall, walkSExpr, mergeEntityFrame, isInlineTrait } from '@almadar/core';
42
+ import { isCircuitEvent, schemaToIR, getPage, clearSchemaCache as clearSchemaCache$1, walkSExpr, buildResolvedTraitConfigs, mergeEntityFrame, isInlineTrait, isSExpr, isEventPayloadValue } from '@almadar/core';
41
43
  import { DndContext, pointerWithin, rectIntersection, closestCorners, useSensors, useSensor, PointerSensor, KeyboardSensor, useDroppable } from '@dnd-kit/core';
42
44
  import { useSortable, arrayMove, sortableKeyboardCoordinates, SortableContext, rectSortingStrategy, verticalListSortingStrategy } from '@dnd-kit/sortable';
43
45
  import { CSS } from '@dnd-kit/utilities';
44
46
  import { useNodeId, ReactFlowProvider, Handle, Position } from '@xyflow/react';
45
47
  import { isDrawHostPattern, getPatternDefinition, getComponentForPattern as getComponentForPattern$1 } from '@almadar/core/patterns';
46
- import { StateMachineManager, collectDeclaredConfigDefaults, createServerEffectHandlers, EffectExecutor, createContextFromBindings, createTickScheduler, isValidCronExpression, parseDurationString, InMemoryPersistence, normalizeCallSiteConfigToValues } from '@almadar/runtime';
48
+ import { StateMachineManager, collectDeclaredConfigDefaults, resolveCallSitePayloadCaptures, createServerEffectHandlers, EffectExecutor, createContextFromBindings, createTickScheduler, isValidCronExpression, parseDurationString, InMemoryPersistence, normalizeCallSiteConfigToValues } from '@almadar/runtime';
49
+ import { isKnownStdOperator } from '@almadar/std/registry';
47
50
  import { OrbitalServerRuntime } from '@almadar/runtime/OrbitalServerRuntime';
48
51
 
49
52
  var __defProp = Object.defineProperty;
@@ -1017,41 +1020,6 @@ function kebabToPascal(name) {
1017
1020
  return part.charAt(0).toUpperCase() + part.slice(1);
1018
1021
  }).join("");
1019
1022
  }
1020
- function loadLib(key, importer) {
1021
- let p = libPromises.get(key);
1022
- if (!p) {
1023
- p = importer();
1024
- libPromises.set(key, p);
1025
- }
1026
- return p;
1027
- }
1028
- function lazyFamilyIcon(libKey, importer, pick, fallbackName, family) {
1029
- const Lazy = React81__default.lazy(async () => {
1030
- const lib = await loadLib(libKey, importer);
1031
- const Comp = pick(lib);
1032
- if (!Comp) {
1033
- warnFallback(fallbackName, family);
1034
- return { default: makeLucideAdapter(fallbackName, true) };
1035
- }
1036
- return { default: Comp };
1037
- });
1038
- const Wrapped = (props) => /* @__PURE__ */ jsx(
1039
- React81__default.Suspense,
1040
- {
1041
- fallback: /* @__PURE__ */ jsx(
1042
- "span",
1043
- {
1044
- "aria-hidden": true,
1045
- className: props.className,
1046
- style: { display: "inline-block", ...props.style }
1047
- }
1048
- ),
1049
- children: /* @__PURE__ */ jsx(Lazy, { ...props })
1050
- }
1051
- );
1052
- Wrapped.displayName = `Lazy.${libKey}.${fallbackName}`;
1053
- return Wrapped;
1054
- }
1055
1023
  function isComponentLike(v) {
1056
1024
  return v != null && (typeof v === "function" || typeof v === "object");
1057
1025
  }
@@ -1065,146 +1033,32 @@ function resolveLucide(name) {
1065
1033
  if (isComponentLike(asIs)) return asIs;
1066
1034
  return LucideIcons2.HelpCircle;
1067
1035
  }
1068
- function resolvePhosphor(name, weight, family) {
1069
- const target = phosphorAliases[name] ?? kebabToPascal(name);
1070
- return lazyFamilyIcon(
1071
- "phosphor",
1072
- () => import('@phosphor-icons/react'),
1073
- (lib) => {
1074
- const PhosphorComp = lib[target];
1075
- if (!PhosphorComp) return null;
1076
- const Component = PhosphorComp;
1077
- const Adapter = (props) => /* @__PURE__ */ jsx(
1078
- Component,
1079
- {
1080
- weight,
1081
- className: props.className,
1082
- style: props.style,
1083
- size: props.size ?? "1em"
1084
- }
1085
- );
1086
- Adapter.displayName = `Phosphor.${target}.${weight}`;
1087
- return Adapter;
1088
- },
1089
- name,
1090
- family
1091
- );
1092
- }
1093
- function resolveTabler(name, family) {
1094
- const suffix = tablerAliases[name] ?? kebabToPascal(name);
1095
- const target = `Icon${suffix}`;
1096
- return lazyFamilyIcon(
1097
- "tabler",
1098
- () => import('@tabler/icons-react'),
1099
- (lib) => {
1100
- const TablerComp = lib[target];
1101
- if (!TablerComp) return null;
1102
- const Component = TablerComp;
1103
- const Adapter = (props) => /* @__PURE__ */ jsx(
1104
- Component,
1105
- {
1106
- stroke: props.strokeWidth ?? 1.5,
1107
- className: props.className,
1108
- style: props.style,
1109
- size: props.size ?? 24
1110
- }
1111
- );
1112
- Adapter.displayName = `Tabler.${target}`;
1113
- return Adapter;
1114
- },
1115
- name,
1116
- family
1117
- );
1118
- }
1119
- function resolveFa(name, family) {
1120
- const suffix = faAliases[name] ?? kebabToPascal(name);
1121
- const target = `Fa${suffix}`;
1122
- return lazyFamilyIcon(
1123
- "fa",
1124
- () => import('react-icons/fa'),
1125
- (lib) => {
1126
- const FaComp = lib[target];
1127
- if (!FaComp) return null;
1128
- const Component = FaComp;
1129
- const Adapter = (props) => /* @__PURE__ */ jsx(
1130
- Component,
1131
- {
1132
- className: props.className,
1133
- style: props.style,
1134
- size: props.size ?? "1em"
1135
- }
1136
- );
1137
- Adapter.displayName = `Fa.${target}`;
1138
- return Adapter;
1139
- },
1140
- name,
1141
- family
1142
- );
1143
- }
1144
- function warnFallback(name, family) {
1145
- const key = `${family}::${name}`;
1146
- if (warned.has(key)) return;
1147
- warned.add(key);
1148
- if (typeof console !== "undefined") {
1149
- console.warn(
1150
- `[iconFamily] No '${name}' mapping in family '${family}'; falling back to lucide. Add an alias in lib/iconFamily.ts.`
1151
- );
1152
- }
1153
- }
1154
- function makeLucideAdapter(name, isFallback = false) {
1036
+ function makeLucideAdapter(name) {
1155
1037
  const LucideComp = resolveLucide(name);
1156
- const Adapter = (props) => {
1157
- const stroke = props.strokeWidth ?? (isFallback ? 2 : void 0);
1158
- const style = isFallback ? { ...props.style ?? {}, strokeWidth: stroke ?? 2 } : props.style;
1159
- return /* @__PURE__ */ jsx(
1160
- LucideComp,
1161
- {
1162
- className: props.className,
1163
- strokeWidth: stroke,
1164
- style,
1165
- size: props.size
1166
- }
1167
- );
1168
- };
1169
- Adapter.displayName = `Lucide.${name}${isFallback ? ".fallback" : ""}`;
1038
+ const Adapter = (props) => /* @__PURE__ */ jsx(
1039
+ LucideComp,
1040
+ {
1041
+ className: props.className,
1042
+ strokeWidth: props.strokeWidth,
1043
+ style: props.style,
1044
+ size: props.size
1045
+ }
1046
+ );
1047
+ Adapter.displayName = `Lucide.${name}`;
1170
1048
  return Adapter;
1171
1049
  }
1172
- function resolveIconForFamily(name, family) {
1173
- switch (family) {
1174
- case "lucide":
1175
- return makeLucideAdapter(name, false);
1176
- // Non-lucide families resolve to a lazy, Suspense-wrapped component that
1177
- // dynamic-imports the library on first render and falls back to lucide
1178
- // internally when the family lacks the icon (see lazyFamilyIcon).
1179
- case "phosphor-outline":
1180
- return resolvePhosphor(name, "regular", family);
1181
- case "phosphor-fill":
1182
- return resolvePhosphor(name, "fill", family);
1183
- case "phosphor-duotone":
1184
- return resolvePhosphor(name, "duotone", family);
1185
- case "tabler":
1186
- return resolveTabler(name, family);
1187
- case "fa-solid":
1188
- return resolveFa(name, family);
1189
- }
1190
- }
1191
- var DEFAULT_FAMILY, VALID_FAMILIES, cachedFamily, listeners, observer, libPromises, lucideAliases, phosphorAliases, tablerAliases, faAliases, warned;
1050
+ function resolveIconForFamily(name, _family) {
1051
+ return makeLucideAdapter(name);
1052
+ }
1053
+ var DEFAULT_FAMILY, VALID_FAMILIES, cachedFamily, listeners, observer, lucideAliases;
1192
1054
  var init_iconFamily = __esm({
1193
1055
  "lib/iconFamily.tsx"() {
1194
1056
  "use client";
1195
1057
  DEFAULT_FAMILY = "lucide";
1196
- VALID_FAMILIES = [
1197
- "lucide",
1198
- "phosphor-outline",
1199
- "phosphor-fill",
1200
- "phosphor-duotone",
1201
- "tabler",
1202
- "fa-solid"
1203
- ];
1058
+ VALID_FAMILIES = [DEFAULT_FAMILY];
1204
1059
  cachedFamily = null;
1205
1060
  listeners = /* @__PURE__ */ new Set();
1206
1061
  observer = null;
1207
- libPromises = /* @__PURE__ */ new Map();
1208
1062
  lucideAliases = {
1209
1063
  close: LucideIcons2.X,
1210
1064
  trash: LucideIcons2.Trash2,
@@ -1217,478 +1071,6 @@ var init_iconFamily = __esm({
1217
1071
  "sort-asc": LucideIcons2.ArrowUpNarrowWide,
1218
1072
  "sort-desc": LucideIcons2.ArrowDownNarrowWide
1219
1073
  };
1220
- phosphorAliases = {
1221
- // lucide name → phosphor PascalCase name
1222
- // Actions
1223
- plus: "Plus",
1224
- minus: "Minus",
1225
- x: "X",
1226
- check: "Check",
1227
- close: "X",
1228
- edit: "PencilSimple",
1229
- pencil: "PencilSimple",
1230
- trash: "Trash",
1231
- save: "FloppyDisk",
1232
- copy: "Copy",
1233
- share: "Share",
1234
- send: "PaperPlaneRight",
1235
- download: "DownloadSimple",
1236
- upload: "UploadSimple",
1237
- archive: "Archive",
1238
- refresh: "ArrowsClockwise",
1239
- loader: "CircleNotch",
1240
- link: "Link",
1241
- paperclip: "Paperclip",
1242
- // Navigation
1243
- "chevron-down": "CaretDown",
1244
- "chevron-up": "CaretUp",
1245
- "chevron-left": "CaretLeft",
1246
- "chevron-right": "CaretRight",
1247
- "arrow-up": "ArrowUp",
1248
- "arrow-down": "ArrowDown",
1249
- "arrow-left": "ArrowLeft",
1250
- "arrow-right": "ArrowRight",
1251
- menu: "List",
1252
- more: "DotsThree",
1253
- "more-vertical": "DotsThreeVertical",
1254
- "more-horizontal": "DotsThree",
1255
- external: "ArrowSquareOut",
1256
- "external-link": "ArrowSquareOut",
1257
- // Files
1258
- file: "File",
1259
- "file-text": "FileText",
1260
- "file-plus": "FilePlus",
1261
- "file-minus": "FileMinus",
1262
- folder: "Folder",
1263
- "folder-open": "FolderOpen",
1264
- document: "FileText",
1265
- // Charts
1266
- "bar-chart": "ChartBar",
1267
- "bar-chart-2": "ChartBar",
1268
- "bar-chart-3": "ChartBar",
1269
- "line-chart": "ChartLine",
1270
- "pie-chart": "ChartPie",
1271
- activity: "Pulse",
1272
- "trending-up": "TrendUp",
1273
- "trending-down": "TrendDown",
1274
- // Messages
1275
- message: "ChatCircle",
1276
- "message-circle": "ChatCircle",
1277
- "message-square": "ChatText",
1278
- "messages-square": "ChatsCircle",
1279
- comment: "ChatCircle",
1280
- comments: "ChatsCircle",
1281
- inbox: "Tray",
1282
- mail: "Envelope",
1283
- envelope: "Envelope",
1284
- // Status
1285
- "alert-circle": "WarningCircle",
1286
- "alert-triangle": "Warning",
1287
- "check-circle": "CheckCircle",
1288
- "x-circle": "XCircle",
1289
- info: "Info",
1290
- "help-circle": "Question",
1291
- "life-buoy": "Lifebuoy",
1292
- lifebuoy: "Lifebuoy",
1293
- warning: "Warning",
1294
- error: "WarningCircle",
1295
- // Media
1296
- image: "Image",
1297
- video: "VideoCamera",
1298
- film: "FilmStrip",
1299
- camera: "Camera",
1300
- music: "MusicNote",
1301
- play: "Play",
1302
- pause: "Pause",
1303
- stop: "Stop",
1304
- "skip-forward": "SkipForward",
1305
- "skip-back": "SkipBack",
1306
- volume: "SpeakerHigh",
1307
- "volume-2": "SpeakerHigh",
1308
- "volume-x": "SpeakerX",
1309
- mic: "Microphone",
1310
- "mic-off": "MicrophoneSlash",
1311
- // People
1312
- user: "User",
1313
- users: "Users",
1314
- "user-plus": "UserPlus",
1315
- "user-check": "UserCheck",
1316
- // Time
1317
- calendar: "Calendar",
1318
- clock: "Clock",
1319
- timer: "Timer",
1320
- // Location
1321
- map: "MapTrifold",
1322
- "map-pin": "MapPin",
1323
- navigation: "NavigationArrow",
1324
- compass: "Compass",
1325
- globe: "Globe",
1326
- target: "Target",
1327
- // Project / layout
1328
- kanban: "Kanban",
1329
- list: "List",
1330
- table: "Table",
1331
- grid: "GridFour",
1332
- layout: "Layout",
1333
- columns: "Columns",
1334
- rows: "Rows",
1335
- // Misc
1336
- bell: "Bell",
1337
- bookmark: "Bookmark",
1338
- briefcase: "Briefcase",
1339
- flag: "Flag",
1340
- tag: "Tag",
1341
- tags: "Tag",
1342
- star: "Star",
1343
- heart: "Heart",
1344
- home: "House",
1345
- settings: "Gear",
1346
- eye: "Eye",
1347
- "eye-off": "EyeSlash",
1348
- lock: "Lock",
1349
- unlock: "LockOpen",
1350
- key: "Key",
1351
- shield: "Shield",
1352
- search: "MagnifyingGlass",
1353
- filter: "Funnel",
1354
- "sort-asc": "SortAscending",
1355
- "sort-desc": "SortDescending",
1356
- zap: "Lightning",
1357
- sparkles: "Sparkle",
1358
- // Code
1359
- code: "Code",
1360
- terminal: "Terminal",
1361
- database: "Database",
1362
- server: "HardDrives",
1363
- cloud: "Cloud",
1364
- wifi: "WifiHigh",
1365
- package: "Package",
1366
- box: "Package",
1367
- // Theme
1368
- sun: "Sun",
1369
- moon: "Moon",
1370
- // Phone
1371
- phone: "Phone",
1372
- printer: "Printer",
1373
- // Hierarchy
1374
- tree: "Tree",
1375
- network: "Network"
1376
- };
1377
- tablerAliases = {
1378
- // lucide name → tabler suffix (after the `Icon` prefix)
1379
- // Actions
1380
- plus: "Plus",
1381
- minus: "Minus",
1382
- x: "X",
1383
- check: "Check",
1384
- close: "X",
1385
- edit: "Pencil",
1386
- pencil: "Pencil",
1387
- trash: "Trash",
1388
- save: "DeviceFloppy",
1389
- copy: "Copy",
1390
- share: "Share",
1391
- send: "Send",
1392
- download: "Download",
1393
- upload: "Upload",
1394
- archive: "Archive",
1395
- refresh: "Refresh",
1396
- loader: "Loader2",
1397
- link: "Link",
1398
- paperclip: "Paperclip",
1399
- external: "ExternalLink",
1400
- "external-link": "ExternalLink",
1401
- // Navigation
1402
- "chevron-down": "ChevronDown",
1403
- "chevron-up": "ChevronUp",
1404
- "chevron-left": "ChevronLeft",
1405
- "chevron-right": "ChevronRight",
1406
- "arrow-down": "ArrowDown",
1407
- "arrow-up": "ArrowUp",
1408
- "arrow-left": "ArrowLeft",
1409
- "arrow-right": "ArrowRight",
1410
- menu: "Menu2",
1411
- more: "Dots",
1412
- "more-vertical": "DotsVertical",
1413
- // Files
1414
- file: "File",
1415
- "file-text": "FileText",
1416
- "file-plus": "FilePlus",
1417
- "file-check": "FileCheck",
1418
- "file-minus": "FileMinus",
1419
- folder: "Folder",
1420
- "folder-open": "FolderOpen",
1421
- document: "FileText",
1422
- // Charts
1423
- "bar-chart": "ChartBar",
1424
- "bar-chart-2": "ChartBar",
1425
- "bar-chart-3": "ChartBar",
1426
- "line-chart": "ChartLine",
1427
- "pie-chart": "ChartPie",
1428
- activity: "Activity",
1429
- "trending-up": "TrendingUp",
1430
- "trending-down": "TrendingDown",
1431
- // Messages
1432
- message: "Message",
1433
- "message-circle": "MessageCircle",
1434
- "message-square": "Message2",
1435
- "messages-square": "Messages",
1436
- comment: "Message",
1437
- comments: "Messages",
1438
- inbox: "Inbox",
1439
- mail: "Mail",
1440
- envelope: "Mail",
1441
- // Status
1442
- "alert-circle": "AlertCircle",
1443
- "alert-triangle": "AlertTriangle",
1444
- "check-circle": "CircleCheck",
1445
- "x-circle": "CircleX",
1446
- info: "InfoCircle",
1447
- "help-circle": "HelpCircle",
1448
- "life-buoy": "Lifebuoy",
1449
- warning: "AlertTriangle",
1450
- error: "AlertOctagon",
1451
- // Media
1452
- image: "Photo",
1453
- video: "Video",
1454
- camera: "Camera",
1455
- music: "Music",
1456
- play: "PlayerPlay",
1457
- pause: "PlayerPause",
1458
- stop: "PlayerStop",
1459
- "skip-forward": "PlayerSkipForward",
1460
- "skip-back": "PlayerSkipBack",
1461
- volume: "Volume",
1462
- "volume-2": "Volume",
1463
- "volume-x": "VolumeOff",
1464
- mic: "Microphone",
1465
- "mic-off": "MicrophoneOff",
1466
- // People
1467
- user: "User",
1468
- users: "Users",
1469
- "user-plus": "UserPlus",
1470
- "user-check": "UserCheck",
1471
- // Time
1472
- calendar: "Calendar",
1473
- clock: "Clock",
1474
- timer: "Hourglass",
1475
- // Location
1476
- map: "Map",
1477
- "map-pin": "MapPin",
1478
- navigation: "Navigation",
1479
- compass: "Compass",
1480
- globe: "World",
1481
- target: "Target",
1482
- // Project / layout
1483
- kanban: "LayoutKanban",
1484
- list: "List",
1485
- table: "Table",
1486
- grid: "LayoutGrid",
1487
- layout: "Layout",
1488
- columns: "LayoutColumns",
1489
- rows: "LayoutRows",
1490
- // Misc
1491
- bell: "Bell",
1492
- bookmark: "Bookmark",
1493
- briefcase: "Briefcase",
1494
- flag: "Flag",
1495
- tag: "Tag",
1496
- tags: "Tags",
1497
- star: "Star",
1498
- heart: "Heart",
1499
- home: "Home",
1500
- settings: "Settings",
1501
- eye: "Eye",
1502
- "eye-off": "EyeOff",
1503
- lock: "Lock",
1504
- unlock: "LockOpen",
1505
- key: "Key",
1506
- shield: "Shield",
1507
- search: "Search",
1508
- filter: "Filter",
1509
- "sort-asc": "SortAscending",
1510
- "sort-desc": "SortDescending",
1511
- zap: "Bolt",
1512
- sparkles: "Sparkles",
1513
- // Code / data
1514
- code: "Code",
1515
- terminal: "Terminal",
1516
- database: "Database",
1517
- server: "Server",
1518
- cloud: "Cloud",
1519
- wifi: "Wifi",
1520
- package: "Package",
1521
- box: "Box",
1522
- // Theme
1523
- sun: "Sun",
1524
- moon: "Moon",
1525
- // Phone
1526
- phone: "Phone",
1527
- printer: "Printer",
1528
- // Hierarchy
1529
- tree: "Hierarchy",
1530
- network: "Network"
1531
- };
1532
- faAliases = {
1533
- // lucide name → fa-solid suffix (after the `Fa` prefix).
1534
- // react-icons/fa ships FontAwesome 5 — names like `FaFileText` don't exist
1535
- // (FA renamed to `FaFileAlt`). When you see a console.warn from
1536
- // [iconFamily] about an unmapped lucide name in this family, add the
1537
- // closest FA5 sibling here so the fallback stays in-family.
1538
- search: "Search",
1539
- close: "Times",
1540
- x: "Times",
1541
- loader: "Spinner",
1542
- refresh: "Sync",
1543
- "sort-asc": "SortAmountUp",
1544
- "sort-desc": "SortAmountDown",
1545
- "chevron-down": "ChevronDown",
1546
- "chevron-up": "ChevronUp",
1547
- "chevron-left": "ChevronLeft",
1548
- "chevron-right": "ChevronRight",
1549
- "help-circle": "QuestionCircle",
1550
- "alert-triangle": "ExclamationTriangle",
1551
- "alert-circle": "ExclamationCircle",
1552
- "check-circle": "CheckCircle",
1553
- "x-circle": "TimesCircle",
1554
- edit: "Edit",
1555
- pencil: "PencilAlt",
1556
- trash: "Trash",
1557
- send: "PaperPlane",
1558
- share: "ShareAlt",
1559
- external: "ExternalLinkAlt",
1560
- plus: "Plus",
1561
- minus: "Minus",
1562
- check: "Check",
1563
- star: "Star",
1564
- heart: "Heart",
1565
- home: "Home",
1566
- user: "User",
1567
- users: "Users",
1568
- "user-plus": "UserPlus",
1569
- "user-check": "UserCheck",
1570
- settings: "Cog",
1571
- menu: "Bars",
1572
- "arrow-up": "ArrowUp",
1573
- "arrow-down": "ArrowDown",
1574
- "arrow-left": "ArrowLeft",
1575
- "arrow-right": "ArrowRight",
1576
- copy: "Copy",
1577
- download: "Download",
1578
- upload: "Upload",
1579
- filter: "Filter",
1580
- calendar: "Calendar",
1581
- clock: "Clock",
1582
- bell: "Bell",
1583
- mail: "Envelope",
1584
- envelope: "Envelope",
1585
- lock: "Lock",
1586
- unlock: "LockOpen",
1587
- eye: "Eye",
1588
- "eye-off": "EyeSlash",
1589
- more: "EllipsisH",
1590
- "more-vertical": "EllipsisV",
1591
- info: "InfoCircle",
1592
- warning: "ExclamationTriangle",
1593
- error: "ExclamationCircle",
1594
- // Time
1595
- timer: "Hourglass",
1596
- // Files (FA renamed FileText → FileAlt)
1597
- file: "File",
1598
- "file-text": "FileAlt",
1599
- "file-plus": "FileMedical",
1600
- "file-minus": "FileExcel",
1601
- "file-check": "FileSignature",
1602
- document: "FileAlt",
1603
- // Charts (lucide BarChart2 / BarChart3 → FA ChartBar)
1604
- "bar-chart": "ChartBar",
1605
- "bar-chart-2": "ChartBar",
1606
- "bar-chart-3": "ChartBar",
1607
- "line-chart": "ChartLine",
1608
- "pie-chart": "ChartPie",
1609
- activity: "ChartLine",
1610
- "trending-up": "ChartLine",
1611
- "trending-down": "ChartLine",
1612
- // Messages (lucide MessageCircle/MessageSquare → FA CommentDots/CommentAlt)
1613
- message: "Comment",
1614
- "message-circle": "CommentDots",
1615
- "message-square": "CommentAlt",
1616
- "messages-square": "Comments",
1617
- comment: "Comment",
1618
- comments: "Comments",
1619
- inbox: "Inbox",
1620
- // Support / help
1621
- "life-buoy": "LifeRing",
1622
- lifebuoy: "LifeRing",
1623
- // Project / kanban (FA has no kanban; closest semantic is Tasks/Columns)
1624
- kanban: "Tasks",
1625
- columns: "Columns",
1626
- rows: "Bars",
1627
- layout: "ThLarge",
1628
- grid: "Th",
1629
- list: "List",
1630
- table: "Table",
1631
- // Storage / folders
1632
- folder: "Folder",
1633
- "folder-open": "FolderOpen",
1634
- archive: "Archive",
1635
- bookmark: "Bookmark",
1636
- briefcase: "Briefcase",
1637
- package: "Box",
1638
- box: "Box",
1639
- // Map / location
1640
- map: "Map",
1641
- "map-pin": "MapMarkerAlt",
1642
- navigation: "LocationArrow",
1643
- compass: "Compass",
1644
- globe: "Globe",
1645
- target: "Bullseye",
1646
- // Media
1647
- image: "Image",
1648
- video: "Video",
1649
- film: "Film",
1650
- camera: "Camera",
1651
- music: "Music",
1652
- play: "Play",
1653
- pause: "Pause",
1654
- stop: "Stop",
1655
- "skip-forward": "Forward",
1656
- "skip-back": "Backward",
1657
- volume: "VolumeUp",
1658
- "volume-2": "VolumeUp",
1659
- "volume-x": "VolumeMute",
1660
- mic: "Microphone",
1661
- "mic-off": "MicrophoneSlash",
1662
- phone: "Phone",
1663
- // Code / data
1664
- code: "Code",
1665
- terminal: "Terminal",
1666
- database: "Database",
1667
- server: "Server",
1668
- cloud: "Cloud",
1669
- wifi: "Wifi",
1670
- // Security
1671
- shield: "ShieldAlt",
1672
- key: "Key",
1673
- // Misc actions
1674
- printer: "Print",
1675
- save: "Save",
1676
- link: "Link",
1677
- unlink: "Unlink",
1678
- paperclip: "Paperclip",
1679
- flag: "Flag",
1680
- tag: "Tag",
1681
- tags: "Tags",
1682
- zap: "Bolt",
1683
- sparkles: "Magic",
1684
- // Theme
1685
- sun: "Sun",
1686
- moon: "Moon",
1687
- // Hierarchy (FA has no Tree icon for hierarchies; Sitemap is the org-chart icon)
1688
- tree: "Sitemap",
1689
- network: "NetworkWired"
1690
- };
1691
- warned = /* @__PURE__ */ new Set();
1692
1074
  }
1693
1075
  });
1694
1076
  function kebabToPascal2(name) {
@@ -1769,7 +1151,7 @@ var init_Icon = __esm({
1769
1151
  const family = useIconFamily();
1770
1152
  const RenderedComponent = React81__default.useMemo(() => {
1771
1153
  if (directIcon) return null;
1772
- return effectiveName ? resolveIconForFamily(effectiveName, family) : null;
1154
+ return effectiveName ? resolveIconForFamily(effectiveName) : null;
1773
1155
  }, [directIcon, effectiveName, family]);
1774
1156
  const effectiveStrokeWidth = strokeWidth ?? void 0;
1775
1157
  const inlineStyle = {
@@ -2148,7 +1530,7 @@ var init_Button = __esm({
2148
1530
  ref,
2149
1531
  disabled: disabled || isLoading,
2150
1532
  className: cn(
2151
- "inline-flex items-center justify-center gap-2",
1533
+ "relative inline-flex items-center justify-center gap-2",
2152
1534
  "font-medium",
2153
1535
  "rounded-sm",
2154
1536
  "cursor-pointer",
@@ -3916,6 +3298,7 @@ var init_Input = __esm({
3916
3298
  icon: iconProp,
3917
3299
  clearable,
3918
3300
  onClear,
3301
+ action,
3919
3302
  value,
3920
3303
  options,
3921
3304
  rows = 3,
@@ -3965,6 +3348,11 @@ var init_Input = __esm({
3965
3348
  onClear?.();
3966
3349
  }
3967
3350
  };
3351
+ const handleKeyDown = (e) => {
3352
+ if (action && e.key === "Enter") {
3353
+ eventBus.emit(`UI:${action}`, { value: e.currentTarget.value });
3354
+ }
3355
+ };
3968
3356
  const wrapField = (field) => /* @__PURE__ */ jsxs("div", { className: "w-full", children: [
3969
3357
  label && /* @__PURE__ */ jsx("label", { className: "block text-sm font-medium text-foreground mb-1", children: label }),
3970
3358
  field,
@@ -4038,6 +3426,7 @@ var init_Input = __esm({
4038
3426
  type,
4039
3427
  value,
4040
3428
  onChange: handleChange,
3429
+ onKeyDown: handleKeyDown,
4041
3430
  className: baseClassName,
4042
3431
  ...props
4043
3432
  }
@@ -4570,7 +3959,7 @@ var init_Card = __esm({
4570
3959
  });
4571
3960
  function GameIcon({ assetUrl, icon, size = "md", alt, className }) {
4572
3961
  const px = typeof size === "number" ? size : sizeMap[size];
4573
- const family = useIconFamily();
3962
+ useIconFamily();
4574
3963
  if (assetUrl?.url) {
4575
3964
  return /* @__PURE__ */ jsx(
4576
3965
  AtlasImage,
@@ -4582,7 +3971,7 @@ function GameIcon({ assetUrl, icon, size = "md", alt, className }) {
4582
3971
  }
4583
3972
  );
4584
3973
  }
4585
- const I = typeof icon === "string" ? resolveIconForFamily(icon, family) : icon;
3974
+ const I = typeof icon === "string" ? resolveIconForFamily(icon) : icon;
4586
3975
  return /* @__PURE__ */ jsx(I, { width: px, height: px, className: cn("flex-shrink-0", className) });
4587
3976
  }
4588
3977
  var sizeMap;
@@ -6979,8 +6368,8 @@ function Seigaiha({ size, color, strokeWidth }) {
6979
6368
  [s, s * 0.1]
6980
6369
  ];
6981
6370
  for (const [cx, cy] of centers) {
6982
- for (let ring2 = 1; ring2 <= 3; ring2++) {
6983
- const cr = r * (ring2 / 3);
6371
+ for (let ring = 1; ring <= 3; ring++) {
6372
+ const cr = r * (ring / 3);
6984
6373
  paths.push(
6985
6374
  `M ${f(cx - cr)},${f(cy)} A ${f(cr)} ${f(cr)} 0 0 1 ${f(cx + cr)},${f(cy)}`
6986
6375
  );
@@ -7077,8 +6466,8 @@ function Arch({ size, color, strokeWidth }) {
7077
6466
  const h = size * 1.5;
7078
6467
  const cx = w / 2;
7079
6468
  const paths = [];
7080
- for (let ring2 = 0; ring2 < 4; ring2++) {
7081
- const scale = 1 - ring2 * 0.2;
6469
+ for (let ring = 0; ring < 4; ring++) {
6470
+ const scale = 1 - ring * 0.2;
7082
6471
  const archW = w * 0.48 * scale;
7083
6472
  const archH = h * 0.7 * scale;
7084
6473
  const baseY = h * 0.85;
@@ -7093,7 +6482,7 @@ function Arch({ size, color, strokeWidth }) {
7093
6482
  paths.push(
7094
6483
  `M ${f(lx)},${f(baseY)} A ${f(radius)} ${f(radius)} 0 0 1 ${f(cx)},${f(tipY)} A ${f(radius)} ${f(radius)} 0 0 1 ${f(rx)},${f(baseY)}`
7095
6484
  );
7096
- if (ring2 === 0) {
6485
+ if (ring === 0) {
7097
6486
  paths.push(`M ${f(lx)},${f(baseY)} L ${f(rx)},${f(baseY)}`);
7098
6487
  }
7099
6488
  }
@@ -9501,9 +8890,9 @@ var init_webPainter2d = __esm({
9501
8890
  // lib/drawable/projector.ts
9502
8891
  function create2DProjector(opts) {
9503
8892
  const { scale, baseOffsetX, layout } = opts;
9504
- const tileWidth = TILE_WIDTH * scale;
9505
- const floorHeight = FLOOR_HEIGHT * scale;
9506
- const diamondTopY = (opts.diamondTopY ?? DIAMOND_TOP_Y) * scale;
8893
+ const tileWidth = layout === "free" ? 1 : TILE_WIDTH * scale;
8894
+ const floorHeight = layout === "free" ? 1 : FLOOR_HEIGHT * scale;
8895
+ const diamondTopY = layout === "free" ? 0 : (opts.diamondTopY ?? DIAMOND_TOP_Y) * scale;
9507
8896
  const squareGrid = layout === "flat" || layout === "free";
9508
8897
  const project = (pos) => layout === "free" ? { x: pos.x, y: pos.y } : isoToScreen(pos.x, pos.y, scale, baseOffsetX, layout);
9509
8898
  const anchorPoint = (pos, anchor) => {
@@ -9544,6 +8933,15 @@ var init_projector = __esm({
9544
8933
  }
9545
8934
  });
9546
8935
 
8936
+ // lib/drawable/contract.ts
8937
+ function isValidScenePos(pos) {
8938
+ return Number.isFinite(pos?.x) && Number.isFinite(pos?.y);
8939
+ }
8940
+ var init_contract = __esm({
8941
+ "lib/drawable/contract.ts"() {
8942
+ }
8943
+ });
8944
+
9547
8945
  // components/game/atoms/DrawSprite.tsx
9548
8946
  function DrawSprite(_props) {
9549
8947
  return null;
@@ -9553,10 +8951,12 @@ var init_DrawSprite = __esm({
9553
8951
  "components/game/atoms/DrawSprite.tsx"() {
9554
8952
  "use client";
9555
8953
  init_atlasSlice();
8954
+ init_contract();
9556
8955
  paintSprite = (painter, node, dctx) => {
8956
+ if (!node.asset?.url || !isValidScenePos(node.position)) return;
9557
8957
  const tex = painter.resolveTexture(node.asset.url);
9558
8958
  if (!tex) return;
9559
- let src = node.frame;
8959
+ let src = typeof node.frame === "object" ? node.frame : void 0;
9560
8960
  if (!src && isAtlasAsset(node.asset)) {
9561
8961
  const atlas = getAtlas(node.asset.atlas, dctx.invalidate);
9562
8962
  if (!atlas) return;
@@ -9601,7 +9001,9 @@ var paintShape;
9601
9001
  var init_DrawShape = __esm({
9602
9002
  "components/game/atoms/DrawShape.tsx"() {
9603
9003
  "use client";
9004
+ init_contract();
9604
9005
  paintShape = (painter, node, dctx) => {
9006
+ if (!isValidScenePos(node.position)) return;
9605
9007
  painter.save();
9606
9008
  if (node.opacity !== void 0 && node.opacity !== 1) painter.setAlpha(node.opacity);
9607
9009
  switch (node.shape) {
@@ -9655,7 +9057,9 @@ var paintText;
9655
9057
  var init_DrawText = __esm({
9656
9058
  "components/game/atoms/DrawText.tsx"() {
9657
9059
  "use client";
9060
+ init_contract();
9658
9061
  paintText = (painter, node, dctx) => {
9062
+ if (!isValidScenePos(node.position)) return;
9659
9063
  const p = dctx.projector.anchorPoint(node.position, node.anchor ?? "center");
9660
9064
  const x = p.x + (node.offsetX ?? 0);
9661
9065
  const y = p.y + (node.offsetY ?? 0);
@@ -9760,12 +9164,14 @@ function collectDrawnItems(nodes) {
9760
9164
  case "draw-sprite":
9761
9165
  case "draw-shape":
9762
9166
  case "draw-text":
9763
- out.push({ pos: n.position, id: n.id });
9167
+ if (isValidScenePos(n.position)) out.push({ pos: n.position, id: n.id });
9764
9168
  break;
9765
9169
  case "draw-sprite-layer":
9766
9170
  case "draw-shape-layer":
9767
9171
  case "draw-text-layer":
9768
- for (const it of n.items) out.push({ pos: it.position, id: it.id });
9172
+ for (const it of n.items) {
9173
+ if (isValidScenePos(it.position)) out.push({ pos: it.position, id: it.id });
9174
+ }
9769
9175
  break;
9770
9176
  }
9771
9177
  }
@@ -9780,6 +9186,7 @@ function buildHitIndex(items) {
9780
9186
  }
9781
9187
  var init_hitTest = __esm({
9782
9188
  "lib/drawable/hitTest.ts"() {
9189
+ init_contract();
9783
9190
  }
9784
9191
  });
9785
9192
  function normalizeBackdrop(bg) {
@@ -9805,14 +9212,16 @@ function Canvas2D({
9805
9212
  cameraPos,
9806
9213
  bgColor
9807
9214
  }) {
9215
+ const instanceId = useMemo(() => Math.random().toString(36).slice(2, 8), []);
9216
+ function isDrawableLayer(node) {
9217
+ return node.type === "draw-sprite-layer" || node.type === "draw-shape-layer" || node.type === "draw-text-layer";
9218
+ }
9808
9219
  const layerSummaries = drawables?.map((d) => {
9809
- if (!d || typeof d !== "object") return d;
9810
- const rec = d;
9811
- return { type: rec.type, itemsLen: Array.isArray(rec.items) ? rec.items.length : void 0, firstItem: Array.isArray(rec.items) ? rec.items[0] : void 0 };
9220
+ if (!isDrawableLayer(d)) return { type: d.type };
9221
+ return { type: d.type, itemsLen: d.items.length, firstItem: d.items[0] };
9812
9222
  });
9813
- console.error("[debug:Canvas2D] " + JSON.stringify({ projection, scale, cameraMode: camera, cameraPos, drawablesCount: drawables?.length, layerSummaries }));
9223
+ canvas2DLog.debug("Canvas2D render", { instanceId, projection, scale, cameraMode: camera, cameraPos: cameraPos ? JSON.stringify(cameraPos) : void 0, drawablesCount: drawables?.length, layerSummaries: layerSummaries ? JSON.stringify(layerSummaries) : void 0 });
9814
9224
  const backgroundImage = normalizeBackdrop(backgroundImageRaw);
9815
- const instanceId = useMemo(() => Math.random().toString(36).slice(2, 8), []);
9816
9225
  const isFree = projection === "free";
9817
9226
  const squareGrid = projection === "flat" || isFree || projection === "side";
9818
9227
  const layout = projection === "side" ? "free" : projection;
@@ -9947,7 +9356,7 @@ function Canvas2D({
9947
9356
  }
9948
9357
  const containerRect = containerRef.current?.getBoundingClientRect();
9949
9358
  const canvasRect = canvas.getBoundingClientRect();
9950
- console.error("[debug:Canvas2D:draw:" + instanceId + "] " + JSON.stringify({ viewportSize, baseOffsetX, cam: { x: cam.x, y: cam.y, zoom: cam.zoom }, cameraPos, containerRect: containerRect ? { width: containerRect.width, height: containerRect.height } : null, canvasRect: canvasRect ? { width: canvasRect.width, height: canvasRect.height } : null }));
9359
+ canvas2DLog.debug("Canvas2D draw", { instanceId, viewportSize, baseOffsetX, cam: { x: cam.x, y: cam.y, zoom: cam.zoom }, cameraPos: cameraPos ? JSON.stringify(cameraPos) : void 0, containerRect: containerRect ? { width: containerRect.width, height: containerRect.height } : null, canvasRect: canvasRect ? { width: canvasRect.width, height: canvasRect.height } : null });
9951
9360
  const painter = createWebPainter(ctx, bumpAtlas);
9952
9361
  painter.save();
9953
9362
  painter.translate(viewportSize.width / 2, viewportSize.height / 2);
@@ -10159,6 +9568,7 @@ function Canvas2D({
10159
9568
  }
10160
9569
  );
10161
9570
  }
9571
+ var canvas2DLog;
10162
9572
  var init_Canvas2D = __esm({
10163
9573
  "components/game/molecules/Canvas2D.tsx"() {
10164
9574
  "use client";
@@ -10180,6 +9590,7 @@ var init_Canvas2D = __esm({
10180
9590
  init_paintDispatch();
10181
9591
  init_hitTest();
10182
9592
  init_isometric();
9593
+ canvas2DLog = createLogger("almadar:ui:game-canvas");
10183
9594
  Canvas2D.displayName = "Canvas2D";
10184
9595
  }
10185
9596
  });
@@ -10218,7 +9629,7 @@ function Canvas({
10218
9629
  keyMap,
10219
9630
  keyUpMap
10220
9631
  }) {
10221
- console.error("[debug:Canvas] " + JSON.stringify({ mode, drawablesCount: drawables?.length, projection, camera }));
9632
+ canvasLog.debug("Canvas render", { mode, drawablesCount: drawables?.length, projection, camera: camera ? JSON.stringify(camera) : void 0 });
10222
9633
  const zoom = camera?.zoom;
10223
9634
  if (mode === "3d") {
10224
9635
  const props3d = {
@@ -10271,7 +9682,7 @@ function Canvas({
10271
9682
  }
10272
9683
  );
10273
9684
  }
10274
- var Canvas3DHost;
9685
+ var Canvas3DHost, canvasLog;
10275
9686
  var init_Canvas = __esm({
10276
9687
  "components/game/molecules/Canvas.tsx"() {
10277
9688
  "use client";
@@ -10279,6 +9690,7 @@ var init_Canvas = __esm({
10279
9690
  Canvas3DHost = lazy(
10280
9691
  () => import('@almadar/ui/components/molecules/game/three').then((m) => ({ default: m.Canvas3DHost }))
10281
9692
  );
9693
+ canvasLog = createLogger("almadar:ui:game-canvas");
10282
9694
  Canvas.displayName = "Canvas";
10283
9695
  }
10284
9696
  });
@@ -11814,21 +11226,6 @@ var init_renderer = __esm({
11814
11226
  init_slot_definitions();
11815
11227
  }
11816
11228
  });
11817
-
11818
- // lib/wrapCallbackForEvent.ts
11819
- function wrapCallbackForEvent(qualifiedEvent, callbackArgs, emit) {
11820
- const argNames = (callbackArgs ?? []).map((a) => a.name);
11821
- if (argNames.length === 0) {
11822
- return () => emit(qualifiedEvent);
11823
- }
11824
- return (...args) => {
11825
- const payload = {};
11826
- for (let i = 0; i < argNames.length; i += 1) {
11827
- payload[argNames[i]] = args[i];
11828
- }
11829
- emit(qualifiedEvent, payload);
11830
- };
11831
- }
11832
11229
  var init_wrapCallbackForEvent = __esm({
11833
11230
  "lib/wrapCallbackForEvent.ts"() {
11834
11231
  }
@@ -22719,7 +22116,8 @@ function DataGrid({
22719
22116
  const { t } = useTranslate();
22720
22117
  const [selectedIds, setSelectedIds] = useState(/* @__PURE__ */ new Set());
22721
22118
  const [visibleCount, setVisibleCount] = useState(pageSize || Infinity);
22722
- const fieldDefs = fields ?? columns ?? [];
22119
+ const fieldDefs = (Array.isArray(fields) ? fields : void 0) ?? (Array.isArray(columns) ? columns : void 0) ?? [];
22120
+ const actionDefs = Array.isArray(itemActions) ? itemActions : [];
22723
22121
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
22724
22122
  const dnd = useDataDnd({
22725
22123
  items: allDataRaw,
@@ -22763,8 +22161,8 @@ function DataGrid({
22763
22161
  const titleField = fieldDefs.find((f3) => f3.variant === "h3" || f3.variant === "h4") ?? fieldDefs[0];
22764
22162
  const badgeFields = fieldDefs.filter((f3) => f3.variant === "badge" && f3 !== titleField);
22765
22163
  const bodyFields = fieldDefs.filter((f3) => f3 !== titleField && !badgeFields.includes(f3));
22766
- const primaryActions = itemActions?.filter((a) => a.variant !== "danger") ?? [];
22767
- const dangerActions = itemActions?.filter((a) => a.variant === "danger") ?? [];
22164
+ const primaryActions = actionDefs.filter((a) => a.variant !== "danger");
22165
+ const dangerActions = actionDefs.filter((a) => a.variant === "danger");
22768
22166
  const handleActionClick = (action, itemData) => (e) => {
22769
22167
  e.stopPropagation();
22770
22168
  const payload = {
@@ -35294,7 +34692,7 @@ function measureLabelWidth(text) {
35294
34692
  if (typeof document === "undefined") return text.length * 6;
35295
34693
  if (!labelMeasureCtx) labelMeasureCtx = document.createElement("canvas").getContext("2d");
35296
34694
  if (!labelMeasureCtx) return text.length * 6;
35297
- labelMeasureCtx.font = "10px system-ui";
34695
+ labelMeasureCtx.font = "12px system-ui";
35298
34696
  return labelMeasureCtx.measureText(text).width;
35299
34697
  }
35300
34698
  function getGroupColor(group, groups) {
@@ -35340,6 +34738,7 @@ var init_GraphCanvas = __esm({
35340
34738
  actions,
35341
34739
  onNodeClick,
35342
34740
  onNodeDoubleClick,
34741
+ onBadgeClick,
35343
34742
  nodeClickEvent,
35344
34743
  selectedNodeId,
35345
34744
  repulsion = 800,
@@ -35487,7 +34886,9 @@ var init_GraphCanvas = __esm({
35487
34886
  const dx = target.x - source.x;
35488
34887
  const dy = target.y - source.y;
35489
34888
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
35490
- const force = (dist - linkDistance) * 0.05;
34889
+ const w2 = edge.weight ?? 1;
34890
+ const linkTarget = linkDistance * (1 + (1 - Math.min(1, Math.max(0, w2))) * 1.5);
34891
+ const force = (dist - linkTarget) * 0.05;
35491
34892
  const fx = dx / dist * force;
35492
34893
  const fy = dy / dist * force;
35493
34894
  source.fx += fx;
@@ -35509,7 +34910,7 @@ var init_GraphCanvas = __esm({
35509
34910
  node.y = Math.max(30, Math.min(h - 30, node.y));
35510
34911
  }
35511
34912
  const LABEL_GAP = 12;
35512
- const LABEL_H = 12;
34913
+ const LABEL_H = 16;
35513
34914
  const pad = nodeSpacing / 2;
35514
34915
  for (let i = 0; i < nodes.length; i++) {
35515
34916
  for (let j = i + 1; j < nodes.length; j++) {
@@ -35530,13 +34931,13 @@ var init_GraphCanvas = __esm({
35530
34931
  const overlapY = Math.min(aBot, bBot) - Math.max(aTop, bTop);
35531
34932
  if (overlapX > 0 && overlapY > 0) {
35532
34933
  if (overlapX <= overlapY) {
35533
- const push2 = overlapX / 2 * (b.x >= a.x ? 1 : -1);
35534
- a.x = Math.max(30, Math.min(w - 30, a.x - push2));
35535
- b.x = Math.max(30, Math.min(w - 30, b.x + push2));
34934
+ const push = overlapX / 2 * (b.x >= a.x ? 1 : -1);
34935
+ a.x = Math.max(30, Math.min(w - 30, a.x - push));
34936
+ b.x = Math.max(30, Math.min(w - 30, b.x + push));
35536
34937
  } else {
35537
- const push2 = overlapY / 2 * (bTop + bBot >= aTop + aBot ? 1 : -1);
35538
- a.y = Math.max(30, Math.min(h - 30, a.y - push2));
35539
- b.y = Math.max(30, Math.min(h - 30, b.y + push2));
34938
+ const push = overlapY / 2 * (bTop + bBot >= aTop + aBot ? 1 : -1);
34939
+ a.y = Math.max(30, Math.min(h - 30, a.y - push));
34940
+ b.y = Math.max(30, Math.min(h - 30, b.y + push));
35540
34941
  }
35541
34942
  }
35542
34943
  }
@@ -35564,6 +34965,11 @@ var init_GraphCanvas = __esm({
35564
34965
  const h = height;
35565
34966
  const nodes = nodesRef.current;
35566
34967
  const accentColor = resolveColor3("var(--color-accent)", canvas);
34968
+ const fontFamily = resolveColor3("var(--font-family)", canvas) || "system-ui";
34969
+ const fgColor = resolveColor3("var(--color-foreground)", canvas);
34970
+ const mutedColor = resolveColor3("var(--color-muted-foreground)", canvas) || fgColor;
34971
+ const bgColor = resolveColor3("var(--color-background)", canvas) || "#ffffff";
34972
+ const accentFg = resolveColor3("var(--color-accent-foreground)", canvas) || "#ffffff";
35567
34973
  const dpr = typeof window !== "undefined" && window.devicePixelRatio || 1;
35568
34974
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
35569
34975
  ctx.clearRect(0, 0, w, h);
@@ -35583,19 +34989,21 @@ var init_GraphCanvas = __esm({
35583
34989
  const target = nodes.find((n) => n.id === edge.target);
35584
34990
  if (!source || !target) continue;
35585
34991
  const incident = !!hoveredNode && (edge.source === hoveredNode || edge.target === hoveredNode);
35586
- ctx.globalAlpha = hoveredNode ? incident ? 1 : 0.05 : linkOpacity;
34992
+ const w2 = edge.weight ?? 1;
34993
+ ctx.globalAlpha = hoveredNode ? incident ? 1 : 0.05 : linkOpacity * w2;
35587
34994
  ctx.beginPath();
35588
34995
  ctx.moveTo(source.x, source.y);
35589
34996
  ctx.lineTo(target.x, target.y);
35590
34997
  ctx.strokeStyle = incident ? accentColor : edge.color || "#888888";
35591
- ctx.lineWidth = incident ? 2 : edge.weight ? Math.max(1, edge.weight) : 1;
34998
+ ctx.lineWidth = incident ? 2 : Math.max(0.75, w2);
35592
34999
  ctx.stroke();
35593
35000
  if (edge.label && showLabels) {
35594
35001
  const mx = (source.x + target.x) / 2;
35595
35002
  const my = (source.y + target.y) / 2;
35596
- ctx.fillStyle = "#888888";
35597
- ctx.font = "9px system-ui";
35003
+ ctx.fillStyle = mutedColor;
35004
+ ctx.font = `9px ${fontFamily}`;
35598
35005
  ctx.textAlign = "center";
35006
+ ctx.textBaseline = "alphabetic";
35599
35007
  ctx.fillText(edge.label, mx, my - 4);
35600
35008
  }
35601
35009
  }
@@ -35620,10 +35028,33 @@ var init_GraphCanvas = __esm({
35620
35028
  }
35621
35029
  ctx.stroke();
35622
35030
  if (showLabels && node.label) {
35623
- ctx.fillStyle = "#666666";
35624
- ctx.font = `${isSelected || isHovered ? "bold " : ""}10px system-ui`;
35031
+ ctx.font = `${isSelected || isHovered ? "600" : "500"} 12px ${fontFamily}`;
35625
35032
  ctx.textAlign = "center";
35626
- ctx.fillText(node.label, node.x, node.y + radius + 12);
35033
+ ctx.textBaseline = "middle";
35034
+ const ly = node.y + radius + 14;
35035
+ ctx.lineWidth = 3;
35036
+ ctx.lineJoin = "round";
35037
+ ctx.strokeStyle = bgColor;
35038
+ ctx.strokeText(node.label, node.x, ly);
35039
+ ctx.fillStyle = isSelected || isHovered ? fgColor : mutedColor;
35040
+ ctx.fillText(node.label, node.x, ly);
35041
+ }
35042
+ if (node.badge && node.badge > 1) {
35043
+ const bx = node.x + radius * 0.7;
35044
+ const by = node.y - radius * 0.7;
35045
+ const br = Math.max(7, Math.min(11, radius * 0.45));
35046
+ ctx.beginPath();
35047
+ ctx.arc(bx, by, br, 0, Math.PI * 2);
35048
+ ctx.fillStyle = accentColor;
35049
+ ctx.fill();
35050
+ ctx.strokeStyle = bgColor;
35051
+ ctx.lineWidth = 2;
35052
+ ctx.stroke();
35053
+ ctx.fillStyle = accentFg;
35054
+ ctx.font = `600 9px ${fontFamily}`;
35055
+ ctx.textAlign = "center";
35056
+ ctx.textBaseline = "middle";
35057
+ ctx.fillText(String(node.badge), bx, by + 0.5);
35627
35058
  }
35628
35059
  }
35629
35060
  ctx.restore();
@@ -35716,11 +35147,21 @@ var init_GraphCanvas = __esm({
35716
35147
  if (!coords) return;
35717
35148
  const node = nodeAt(coords.graphX, coords.graphY);
35718
35149
  if (node) {
35150
+ if (node.badge && node.badge > 1 && onBadgeClick) {
35151
+ const r = (node.size || 8) + (selectedNodeId === node.id ? 4 : 0);
35152
+ const bx = node.x + r * 0.7;
35153
+ const by = node.y - r * 0.7;
35154
+ const br = Math.max(7, Math.min(11, r * 0.45)) + 3;
35155
+ if (Math.hypot(coords.graphX - bx, coords.graphY - by) <= br) {
35156
+ onBadgeClick(node);
35157
+ return;
35158
+ }
35159
+ }
35719
35160
  handleNodeClick(node);
35720
35161
  }
35721
35162
  }
35722
35163
  },
35723
- [toCoords, nodeAt, handleNodeClick]
35164
+ [toCoords, nodeAt, handleNodeClick, onBadgeClick, selectedNodeId]
35724
35165
  );
35725
35166
  const handlePointerLeave = useCallback(() => {
35726
35167
  setHoveredNode(null);
@@ -40241,7 +39682,7 @@ function getAllEvents(traits2) {
40241
39682
  function EventDispatcherTab({ traits: traits2, schema }) {
40242
39683
  const eventBus = useEventBus();
40243
39684
  const { t } = useTranslate();
40244
- const [log10, setLog] = React81.useState([]);
39685
+ const [log9, setLog] = React81.useState([]);
40245
39686
  const prevStatesRef = React81.useRef(/* @__PURE__ */ new Map());
40246
39687
  React81.useEffect(() => {
40247
39688
  for (const trait of traits2) {
@@ -40305,9 +39746,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
40305
39746
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.otherEvents") }),
40306
39747
  /* @__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)) })
40307
39748
  ] }),
40308
- log10.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
39749
+ log9.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
40309
39750
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.recentTransitions") }),
40310
- /* @__PURE__ */ jsx(Stack, { gap: "xs", children: log10.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
39751
+ /* @__PURE__ */ jsx(Stack, { gap: "xs", children: log9.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
40311
39752
  /* @__PURE__ */ jsx("span", { className: "text-purple-400", children: entry.traitName }),
40312
39753
  " ",
40313
39754
  /* @__PURE__ */ jsx("span", { className: "text-gray-500", children: entry.from }),
@@ -43944,27 +43385,27 @@ var log2 = createLogger("almadar:ui:shared-entity-store");
43944
43385
  var EMPTY_ENTITY_STATE = {};
43945
43386
  function createSharedEntityStore() {
43946
43387
  const states = /* @__PURE__ */ new Map();
43947
- const subscribers2 = /* @__PURE__ */ new Map();
43948
- const getSnapshot3 = (entityId) => states.get(entityId) ?? EMPTY_ENTITY_STATE;
43949
- const subscribe2 = (entityId, callback) => {
43950
- let set = subscribers2.get(entityId);
43388
+ const subscribers = /* @__PURE__ */ new Map();
43389
+ const getSnapshot2 = (entityId) => states.get(entityId) ?? EMPTY_ENTITY_STATE;
43390
+ const subscribe = (entityId, callback) => {
43391
+ let set = subscribers.get(entityId);
43951
43392
  if (!set) {
43952
43393
  set = /* @__PURE__ */ new Set();
43953
- subscribers2.set(entityId, set);
43394
+ subscribers.set(entityId, set);
43954
43395
  }
43955
43396
  set.add(callback);
43956
43397
  return () => {
43957
- const current = subscribers2.get(entityId);
43398
+ const current = subscribers.get(entityId);
43958
43399
  if (!current) return;
43959
43400
  current.delete(callback);
43960
43401
  if (current.size === 0) {
43961
- subscribers2.delete(entityId);
43402
+ subscribers.delete(entityId);
43962
43403
  }
43963
43404
  };
43964
43405
  };
43965
43406
  const commit = (entityId, nextState) => {
43966
43407
  states.set(entityId, nextState);
43967
- const set = subscribers2.get(entityId);
43408
+ const set = subscribers.get(entityId);
43968
43409
  if (!set) return;
43969
43410
  set.forEach((callback) => {
43970
43411
  try {
@@ -43982,7 +43423,7 @@ function createSharedEntityStore() {
43982
43423
  states.set(entityId, initialState);
43983
43424
  }
43984
43425
  };
43985
- return { getSnapshot: getSnapshot3, subscribe: subscribe2, commit, seed };
43426
+ return { getSnapshot: getSnapshot2, subscribe, commit, seed };
43986
43427
  }
43987
43428
  function useSharedEntityStore() {
43988
43429
  const storeRef = useRef(null);
@@ -44058,6 +43499,11 @@ function createClientEffectHandlers(options) {
44058
43499
  };
44059
43500
  }
44060
43501
  var lambdaLog = createLogger("almadar:ui:fn-form-lambda");
43502
+ function isOperatorCall(value) {
43503
+ const first = value[0];
43504
+ if (typeof first !== "string") return false;
43505
+ return isKnownStdOperator(first) || first.includes("/") || first === "lambda" || first === "let";
43506
+ }
44061
43507
  function isFnFormLambda(value) {
44062
43508
  if (!Array.isArray(value)) return false;
44063
43509
  const arr = value;
@@ -44097,7 +43543,14 @@ function resolveLambdaBindings(body, params, item, index) {
44097
43543
  return body;
44098
43544
  }
44099
43545
  if (Array.isArray(body)) {
44100
- return body.map((b) => recur(b));
43546
+ if (isFnFormLambda(body)) return body;
43547
+ const arr = body;
43548
+ const substituted = arr.map((b) => recur(b));
43549
+ if (isOperatorCall(substituted) && isSExpr(substituted)) {
43550
+ const evaluated = evaluate(substituted, createMinimalContext());
43551
+ return isEventPayloadValue(evaluated) ? evaluated : String(evaluated);
43552
+ }
43553
+ return substituted;
44101
43554
  }
44102
43555
  if (body !== null && typeof body === "object" && !React81__default.isValidElement(body) && !(body instanceof Date) && typeof body !== "function") {
44103
43556
  const out = {};
@@ -44192,6 +43645,8 @@ var flushLog = createLogger("almadar:ui:slot-flush");
44192
43645
  var stateLog = createLogger("almadar:ui:state-transitions");
44193
43646
  var tickLog = createLogger("almadar:ui:tick-effects");
44194
43647
  setNamespaceLevel("almadar:ui:tick-effects", "WARN");
43648
+ var sharedEntityLog = createLogger("almadar:ui:shared-entity");
43649
+ setNamespaceLevel("almadar:ui:shared-entity", "WARN");
44195
43650
  var SYNC_TICK_OPERATORS = /* @__PURE__ */ new Set([
44196
43651
  "set",
44197
43652
  "emit",
@@ -44286,14 +43741,14 @@ function createSharedEntityWriter(binding, tick, traitStatesRef, emit) {
44286
43741
  function getBindingConfig(binding) {
44287
43742
  const raw = binding.config;
44288
43743
  const normalized = normalizeCallSiteConfigToValues(raw);
44289
- console.log("[debug:getBindingConfig]", binding.trait.name, "raw keys=", raw ? Object.keys(raw) : "undefined", "has tiles=", raw ? "tiles" in raw : false);
43744
+ sharedEntityLog.debug("getBindingConfig", { traitName: binding.trait.name, rawKeys: raw ? Object.keys(raw) : void 0, hasTiles: raw ? "tiles" in raw : false });
44290
43745
  return normalized;
44291
43746
  }
44292
43747
  function evalFieldDefault(value) {
44293
43748
  if (!Array.isArray(value) || value.length === 0) return value;
44294
43749
  const head = value[0];
44295
- const isSExpr = typeof head === "string" && (head.includes("/") || head === "let" || head === "if" || head === "lambda");
44296
- if (!isSExpr) return value;
43750
+ const isSExpr2 = typeof head === "string" && (head.includes("/") || head === "let" || head === "if" || head === "lambda");
43751
+ if (!isSExpr2) return value;
44297
43752
  try {
44298
43753
  return evaluate(value, createMinimalContext({}, {}, ""));
44299
43754
  } catch {
@@ -44301,7 +43756,7 @@ function evalFieldDefault(value) {
44301
43756
  }
44302
43757
  }
44303
43758
  function useTraitStateMachine(traitBindings, uiSlots, options) {
44304
- console.log("[debug:useTraitStateMachine] start, traitBindings count=", traitBindings.length, "names=", traitBindings.map((b) => b.trait.name).join(","));
43759
+ sharedEntityLog.debug("useTraitStateMachine start", { traitBindingsCount: traitBindings.length, traitNames: traitBindings.map((b) => b.trait.name) });
44305
43760
  const eventBus = useEventBus();
44306
43761
  const { entities } = useEntitySchema();
44307
43762
  const traitConfigsByName = options?.traitConfigsByName;
@@ -44320,10 +43775,15 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
44320
43775
  if (!group) {
44321
43776
  let defaults;
44322
43777
  for (const field of entityDef.fields) {
44323
- if (field.default !== void 0) {
43778
+ if (field.default !== void 0 && field.default !== null) {
44324
43779
  const evaluated = evalFieldDefault(field.default);
44325
43780
  if (field.name === "tiles") {
44326
- console.log(`[debug:seed] ${linkedEntityName}.tiles seed type=`, typeof evaluated, Array.isArray(evaluated) ? "len=" + evaluated?.length : "", "head=", Array.isArray(evaluated) && evaluated.length > 0 ? JSON.stringify(evaluated[0]).slice(0, 80) : "n/a");
43781
+ sharedEntityLog.debug("seed tiles", {
43782
+ linkedEntityName,
43783
+ type: typeof evaluated,
43784
+ length: Array.isArray(evaluated) ? evaluated?.length : void 0,
43785
+ head: Array.isArray(evaluated) && evaluated.length > 0 ? JSON.stringify(evaluated[0]).slice(0, 80) : void 0
43786
+ });
44327
43787
  }
44328
43788
  (defaults ?? (defaults = {}))[field.name] = evaluated;
44329
43789
  }
@@ -44340,7 +43800,12 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
44340
43800
  for (const group of sharedGroups.values()) {
44341
43801
  if (group.defaults) {
44342
43802
  sharedEntityStore.seed(group.storeKey, group.defaults);
44343
- console.log("[debug:shared-seed]", group.storeKey, "writers=", group.writerBindings.map((b) => b.trait.name).join(","), "renderers=", group.renderBindings.map((b) => b.trait.name).join(","), "defaults.tiles=", Array.isArray(group.defaults.tiles) ? group.defaults.tiles.length : group.defaults.tiles);
43803
+ sharedEntityLog.debug("shared-seed", {
43804
+ storeKey: group.storeKey,
43805
+ writers: group.writerBindings.map((b) => b.trait.name),
43806
+ renderers: group.renderBindings.map((b) => b.trait.name),
43807
+ tilesLength: Array.isArray(group.defaults.tiles) ? group.defaults.tiles.length : group.defaults.tiles
43808
+ });
44344
43809
  }
44345
43810
  }
44346
43811
  const sharedKeyByTraitNameRef = useRef(/* @__PURE__ */ new Map());
@@ -44351,13 +43816,15 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
44351
43816
  for (const binding of group.renderBindings) map.set(binding.trait.name, group.storeKey);
44352
43817
  }
44353
43818
  sharedKeyByTraitNameRef.current = map;
44354
- console.log("[debug:shared-map]", Array.from(map.entries()).map(([k, v]) => `${k}->${v}`).join(","));
43819
+ sharedEntityLog.debug("shared-map", { map: Array.from(map.entries()).map(([k, v]) => `${k}->${v}`) });
44355
43820
  }, [sharedGroups]);
44356
43821
  const manager = useMemo(() => {
44357
43822
  const traitDefs = traitBindings.map(toTraitDefinition);
44358
43823
  const m = new StateMachineManager(traitDefs);
44359
43824
  for (const binding of traitBindings) {
44360
- const cfg = getBindingConfig(binding) ?? traitConfigsByName?.[binding.trait.name];
43825
+ const rawCfg = getBindingConfig(binding);
43826
+ const resolvedCfg = traitConfigsByName?.[binding.trait.name];
43827
+ const cfg = rawCfg || resolvedCfg ? { ...rawCfg ?? {}, ...resolvedCfg ?? {} } : void 0;
44361
43828
  if (cfg !== void 0) {
44362
43829
  m.setTraitConfig(binding.trait.name, cfg);
44363
43830
  }
@@ -44535,13 +44002,13 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
44535
44002
  };
44536
44003
  }, [traitBindings]);
44537
44004
  const executeTransitionEffects = useCallback(async (params) => {
44538
- const { binding, previousState, newState, payload, flushEvent, syncOnly, log: log10 } = params;
44005
+ const { binding, previousState, newState, payload, flushEvent, syncOnly, log: log9 } = params;
44539
44006
  const traitName = binding.trait.name;
44540
44007
  const linkedEntity = binding.linkedEntity || "";
44541
44008
  const entityId = payload?.entityId;
44542
44009
  const sharedKey = sharedKeyByTraitNameRef.current.get(traitName);
44543
44010
  if (traitName === "Hero" || traitName === "Authority") {
44544
- console.log(`[debug:executeTransitionEffects] ${traitName} sharedKey=`, sharedKey, "store tiles=", sharedKey ? sharedEntityStore.getSnapshot(sharedKey).tiles?.length : "n/a");
44011
+ sharedEntityLog.debug("executeTransitionEffects sharedKey", { traitName, sharedKey, storeTilesLength: sharedKey ? sharedEntityStore.getSnapshot(sharedKey).tiles?.length : void 0 });
44545
44012
  }
44546
44013
  let liveEntity;
44547
44014
  if (sharedKey !== void 0) {
@@ -44568,10 +44035,15 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
44568
44035
  addPattern: (slot, pattern, props) => {
44569
44036
  if (traitName === "Hero" && slot === "main" && props && typeof props === "object") {
44570
44037
  const canvasChild = Array.isArray(props.children) ? props.children[0] : null;
44571
- const grandChildren = canvasChild && typeof canvasChild === "object" ? canvasChild.children : null;
44038
+ const grandChildren = canvasChild && typeof canvasChild === "object" && !Array.isArray(canvasChild) ? canvasChild.children : null;
44572
44039
  const firstLayer = Array.isArray(grandChildren) && grandChildren.length > 0 ? grandChildren[0] : null;
44573
- const firstLayerItems = firstLayer && typeof firstLayer === "object" ? firstLayer.items : null;
44574
- console.log(`[debug:render-ui] ${traitName} slot=${slot} canvasChild=`, canvasChild ? canvasChild.type : "none", "firstLayerItems=", Array.isArray(firstLayerItems) ? firstLayerItems.length : firstLayerItems);
44040
+ const firstLayerItems = firstLayer && typeof firstLayer === "object" && !Array.isArray(firstLayer) ? firstLayer.items : null;
44041
+ sharedEntityLog.debug("render-ui main slot", {
44042
+ traitName,
44043
+ slot,
44044
+ canvasChildType: canvasChild && typeof canvasChild === "object" && !Array.isArray(canvasChild) ? canvasChild.type : "none",
44045
+ firstLayerItemsLength: Array.isArray(firstLayerItems) ? firstLayerItems.length : firstLayerItems
44046
+ });
44575
44047
  }
44576
44048
  const existing = pendingSlots.get(slot) || [];
44577
44049
  existing.push({ pattern, props: props || {} });
@@ -44604,10 +44076,20 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
44604
44076
  state: previousState
44605
44077
  };
44606
44078
  const sharedDeclared = collectDeclaredConfigDefaults(binding.trait);
44607
- const sharedCallSite = getBindingConfig(binding);
44608
- if (sharedDeclared || sharedCallSite) {
44079
+ const sharedResolved = traitConfigsByName?.[traitName];
44080
+ const sharedCallSiteRaw = getBindingConfig(binding);
44081
+ const sharedCallSite = sharedCallSiteRaw ? resolveCallSitePayloadCaptures(
44082
+ Object.fromEntries(
44083
+ Object.entries(sharedCallSiteRaw).filter(
44084
+ ([, v]) => !(typeof v === "string" && v.startsWith("@config."))
44085
+ )
44086
+ ),
44087
+ payload || {}
44088
+ ) : void 0;
44089
+ if (sharedDeclared || sharedResolved || sharedCallSite) {
44609
44090
  sharedBindings.config = {
44610
44091
  ...sharedDeclared ?? {},
44092
+ ...sharedResolved ?? {},
44611
44093
  ...sharedCallSite ?? {}
44612
44094
  };
44613
44095
  }
@@ -44641,7 +44123,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
44641
44123
  ...handlers,
44642
44124
  set: async (targetId, field, value) => {
44643
44125
  if (baseSet) await baseSet(targetId, field, value);
44644
- log10.debug("set:write", {
44126
+ log9.debug("set:write", {
44645
44127
  traitName,
44646
44128
  field,
44647
44129
  value: JSON.stringify(value),
@@ -44655,15 +44137,30 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
44655
44137
  state: previousState
44656
44138
  };
44657
44139
  const declaredDefaults = collectDeclaredConfigDefaults(binding.trait);
44140
+ const resolvedDefaults = traitConfigsByName?.[traitName];
44658
44141
  const callSiteConfig = getBindingConfig(binding);
44659
- if (declaredDefaults || callSiteConfig) {
44142
+ const callSiteOverrides = callSiteConfig ? resolveCallSitePayloadCaptures(
44143
+ Object.fromEntries(
44144
+ Object.entries(callSiteConfig).filter(
44145
+ ([, v]) => !(typeof v === "string" && v.startsWith("@config."))
44146
+ )
44147
+ ),
44148
+ payload || {}
44149
+ ) : void 0;
44150
+ if (declaredDefaults || resolvedDefaults || callSiteOverrides) {
44660
44151
  bindingCtx.config = {
44661
44152
  ...declaredDefaults ?? {},
44662
- ...callSiteConfig ?? {}
44153
+ ...resolvedDefaults ?? {},
44154
+ ...callSiteOverrides ?? {}
44663
44155
  };
44664
44156
  }
44665
44157
  if (traitName === "Authority" || traitName === "Hero") {
44666
- console.log(`[debug:executeTransitionEffects] ${traitName} config tiles type=`, typeof bindingCtx.config?.tiles, Array.isArray(bindingCtx.config?.tiles) ? "len=" + bindingCtx.config?.tiles?.length : "", "keys=", bindingCtx.config ? Object.keys(bindingCtx.config) : "none");
44158
+ sharedEntityLog.debug("executeTransitionEffects config tiles", {
44159
+ traitName,
44160
+ tilesType: typeof bindingCtx.config?.tiles,
44161
+ tilesLength: Array.isArray(bindingCtx.config?.tiles) ? bindingCtx.config?.tiles?.length : void 0,
44162
+ configKeys: bindingCtx.config ? Object.keys(bindingCtx.config) : void 0
44163
+ });
44667
44164
  }
44668
44165
  const effectContext = {
44669
44166
  traitName,
@@ -44682,18 +44179,28 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
44682
44179
  }
44683
44180
  };
44684
44181
  if (traitName === "Hero") {
44685
- console.log(`[debug:executeTransitionEffects] ${traitName} effects count=${effects.length} hasRenderUI=${typeof handlers.renderUI === "function"} effect heads=${effects.map((e) => Array.isArray(e) ? String(e[0]) : "??").join(",")}`);
44182
+ sharedEntityLog.debug("executeTransitionEffects effects summary", {
44183
+ traitName,
44184
+ effectsCount: effects.length,
44185
+ hasRenderUI: typeof handlers.renderUI === "function",
44186
+ effectHeads: effects.map((e) => Array.isArray(e) ? String(e[0]) : "??")
44187
+ });
44686
44188
  }
44687
44189
  const executor = new EffectExecutor({ handlers: trackingHandlers, bindings: bindingCtx, context: effectContext });
44688
44190
  try {
44689
44191
  await executor.executeAll(effects);
44690
44192
  if (traitName === "Authority" || traitName === "Hero") {
44691
- console.log(`[debug:executeTransitionEffects] ${traitName} after executeAll liveEntity.tiles type=`, typeof liveEntity.tiles, Array.isArray(liveEntity.tiles) ? "len=" + liveEntity.tiles?.length : "", "firstTilePos=", Array.isArray(liveEntity.tiles) && liveEntity.tiles.length > 0 ? JSON.stringify(liveEntity.tiles[0]).slice(0, 120) : "n/a");
44193
+ sharedEntityLog.debug("executeTransitionEffects after executeAll", {
44194
+ traitName,
44195
+ tilesType: typeof liveEntity.tiles,
44196
+ tilesLength: Array.isArray(liveEntity.tiles) ? liveEntity.tiles?.length : void 0,
44197
+ firstTilePos: Array.isArray(liveEntity.tiles) && liveEntity.tiles.length > 0 ? JSON.stringify(liveEntity.tiles[0]).slice(0, 120) : void 0
44198
+ });
44692
44199
  }
44693
44200
  if (sharedKey !== void 0) {
44694
44201
  sharedEntityStore.commit(sharedKey, liveEntity);
44695
44202
  }
44696
- log10.debug("effects:executed", () => ({
44203
+ log9.debug("effects:executed", () => ({
44697
44204
  traitName,
44698
44205
  transition: `${previousState}->${newState}`,
44699
44206
  event: flushEvent,
@@ -44703,7 +44210,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
44703
44210
  slotsTouched: Array.from(pendingSlots.keys()).join(",")
44704
44211
  }));
44705
44212
  for (const [slot, patterns] of pendingSlots) {
44706
- log10.debug("flush:slot", {
44213
+ log9.debug("flush:slot", {
44707
44214
  traitName,
44708
44215
  slot,
44709
44216
  patternCount: patterns.length,
@@ -44718,7 +44225,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
44718
44225
  });
44719
44226
  }
44720
44227
  } catch (error) {
44721
- log10.error("effects:error", {
44228
+ log9.error("effects:error", {
44722
44229
  traitName,
44723
44230
  transition: `${previousState}->${newState}`,
44724
44231
  event: flushEvent,
@@ -44740,7 +44247,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
44740
44247
  payload: {},
44741
44248
  state: currentState
44742
44249
  };
44743
- const bindingCfg = getBindingConfig(binding);
44250
+ const bindingCfg = getBindingConfig(binding) ?? traitConfigsByName?.[traitName];
44744
44251
  if (bindingCfg) {
44745
44252
  guardCtx.config = bindingCfg;
44746
44253
  }
@@ -45103,17 +44610,19 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
45103
44610
  }, [traitBindings, eventBus, enqueueAndDrain]);
45104
44611
  useEffect(() => {
45105
44612
  const mgr = managerRef.current;
45106
- const inited = initedTraitsRef.current;
44613
+ const eventsToFire = /* @__PURE__ */ new Set();
45107
44614
  for (const binding of traitBindings) {
45108
44615
  const traitName = binding.trait.name;
45109
- if (inited.has(traitName)) continue;
45110
44616
  const lifecycleEvent = LIFECYCLE_EVENTS.find(
45111
44617
  (evt) => mgr.canHandleEvent(traitName, evt)
45112
44618
  );
45113
- if (lifecycleEvent === void 0) continue;
45114
- inited.add(traitName);
45115
- stateLog.debug("mount:fire-lifecycle", { traitName, event: lifecycleEvent });
45116
- enqueueAndDrain(lifecycleEvent, {});
44619
+ if (lifecycleEvent !== void 0) {
44620
+ eventsToFire.add(lifecycleEvent);
44621
+ }
44622
+ }
44623
+ for (const event of eventsToFire) {
44624
+ stateLog.debug("mount:fire-lifecycle", { event, traitCount: traitBindings.length });
44625
+ enqueueAndDrain(event, {});
45117
44626
  }
45118
44627
  return () => {
45119
44628
  initedTraitsRef.current = /* @__PURE__ */ new Set();
@@ -45228,343 +44737,8 @@ init_Typography();
45228
44737
  init_UISlotRenderer();
45229
44738
  init_useEventBus();
45230
44739
 
45231
- // lib/embedded-traits.ts
45232
- var TRAIT_BINDING_PREFIX = "@trait.";
45233
- function collectTraitRefsFromValue(value, into) {
45234
- if (value === null || value === void 0) return;
45235
- if (typeof value === "string") {
45236
- if (value.startsWith(TRAIT_BINDING_PREFIX)) {
45237
- const rest = value.slice(TRAIT_BINDING_PREFIX.length);
45238
- const dot = rest.indexOf(".");
45239
- const traitName = dot === -1 ? rest : rest.slice(0, dot);
45240
- if (traitName.length > 0) into.add(traitName);
45241
- }
45242
- return;
45243
- }
45244
- if (Array.isArray(value)) {
45245
- for (const item of value) collectTraitRefsFromValue(item, into);
45246
- return;
45247
- }
45248
- if (typeof value === "object") {
45249
- for (const v of Object.values(value)) {
45250
- collectTraitRefsFromValue(v, into);
45251
- }
45252
- }
45253
- }
45254
- function collectTraitRefsFromEffects(effects, into) {
45255
- if (!effects) return;
45256
- for (const effect of effects) {
45257
- if (!Array.isArray(effect)) continue;
45258
- if (effect[0] === "render-ui" && effect.length >= 3) {
45259
- collectTraitRefsFromValue(effect[2], into);
45260
- continue;
45261
- }
45262
- for (let i = 1; i < effect.length; i++) {
45263
- const arg = effect[i];
45264
- if (Array.isArray(arg)) collectTraitRefsFromEffects([arg], into);
45265
- else collectTraitRefsFromValue(arg, into);
45266
- }
45267
- }
45268
- }
45269
- function collectTraitRefsFromResolvedTrait(trait) {
45270
- const out = /* @__PURE__ */ new Set();
45271
- for (const transition of trait.transitions ?? []) {
45272
- collectTraitRefsFromEffects(transition.effects, out);
45273
- }
45274
- for (const tick of trait.ticks ?? []) {
45275
- collectTraitRefsFromEffects(tick.effects, out);
45276
- }
45277
- return out;
45278
- }
45279
- function collectEmbeddedTraits(schema) {
45280
- const out = /* @__PURE__ */ new Set();
45281
- if (!schema?.orbitals) return out;
45282
- for (const orbital of schema.orbitals) {
45283
- const traits2 = orbital.traits;
45284
- if (!Array.isArray(traits2)) continue;
45285
- for (const traitRef of traits2) {
45286
- if (!traitRef || typeof traitRef !== "object") continue;
45287
- const resolved = traitRef._resolved;
45288
- const target = resolved && typeof resolved === "object" ? resolved : traitRef;
45289
- if (target.config) {
45290
- collectTraitRefsFromValue(target.config, out);
45291
- }
45292
- const transitions = target.stateMachine?.transitions;
45293
- if (!Array.isArray(transitions)) continue;
45294
- for (const t of transitions) {
45295
- collectTraitRefsFromEffects(t.effects, out);
45296
- }
45297
- collectTraitRefsFromEffects(target.initialEffects, out);
45298
- const ticks2 = target.ticks;
45299
- if (Array.isArray(ticks2)) {
45300
- for (const tick of ticks2) {
45301
- collectTraitRefsFromEffects(tick.effects, out);
45302
- }
45303
- }
45304
- }
45305
- }
45306
- return out;
45307
- }
45308
-
45309
- // lib/orbitalsByTrait.ts
45310
- function buildOrbitalsByTrait(schema, resolvedPages = []) {
45311
- const map = {};
45312
- if (!schema?.orbitals) return map;
45313
- const pagePathToOrbital = {};
45314
- for (const orb of schema.orbitals) {
45315
- for (const traitRef of orb.traits ?? []) {
45316
- let traitName;
45317
- if (typeof traitRef === "string") {
45318
- const parts = traitRef.split(".");
45319
- traitName = parts[parts.length - 1];
45320
- } else if (typeof traitRef.ref === "string") {
45321
- const parts = traitRef.ref.split(".");
45322
- traitName = traitRef.name ?? parts[parts.length - 1];
45323
- } else if (typeof traitRef.name === "string") {
45324
- traitName = traitRef.name;
45325
- }
45326
- if (traitName) map[traitName] = orb.name;
45327
- }
45328
- for (const pg of orb.pages ?? []) {
45329
- const path = typeof pg === "string" ? pg : pg?.path;
45330
- if (path) pagePathToOrbital[path] = orb.name;
45331
- }
45332
- }
45333
- for (const page of resolvedPages) {
45334
- const orbital = page.path ? pagePathToOrbital[page.path] : void 0;
45335
- if (!orbital) continue;
45336
- for (const traitName of page.traitNames) {
45337
- if (traitName && !(traitName in map)) map[traitName] = orbital;
45338
- }
45339
- }
45340
- return map;
45341
- }
45342
-
45343
44740
  // runtime/OrbPreview.tsx
45344
44741
  init_verificationRegistry();
45345
- var PERF_NAMESPACE = "almadar:perf:canvas";
45346
- var log9 = createLogger(PERF_NAMESPACE);
45347
- var RING_SIZE = 50;
45348
- var ring = [];
45349
- var writeIdx = 0;
45350
- var subscribers = /* @__PURE__ */ new Set();
45351
- var notifyScheduled = false;
45352
- var revision = 0;
45353
- var cachedSnapshot = [];
45354
- var cachedRevision = -1;
45355
- function scheduleNotify() {
45356
- if (notifyScheduled) return;
45357
- notifyScheduled = true;
45358
- queueMicrotask(() => {
45359
- notifyScheduled = false;
45360
- revision++;
45361
- for (const fn of subscribers) fn();
45362
- });
45363
- }
45364
- function push(entry) {
45365
- if (ring.length < RING_SIZE) {
45366
- ring.push(entry);
45367
- } else {
45368
- ring[writeIdx] = entry;
45369
- }
45370
- writeIdx = (writeIdx + 1) % RING_SIZE;
45371
- scheduleNotify();
45372
- }
45373
- function isEnabled() {
45374
- return isLogLevelEnabled("DEBUG", PERF_NAMESPACE);
45375
- }
45376
- function now() {
45377
- return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
45378
- }
45379
- function perfStart(name) {
45380
- if (!isEnabled()) return -1;
45381
- if (typeof performance !== "undefined" && typeof performance.mark === "function") {
45382
- try {
45383
- performance.mark(`${name}-start`);
45384
- } catch {
45385
- }
45386
- }
45387
- return now();
45388
- }
45389
- function perfEnd(name, startToken, detail) {
45390
- if (startToken < 0 || !isEnabled()) return;
45391
- const endTs = now();
45392
- const durationMs = endTs - startToken;
45393
- if (typeof performance !== "undefined" && typeof performance.measure === "function") {
45394
- try {
45395
- performance.mark(`${name}-end`);
45396
- performance.measure(name, `${name}-start`, `${name}-end`);
45397
- } catch {
45398
- }
45399
- }
45400
- push({ name, durationMs, ts: endTs, detail });
45401
- log9.debug(name, () => ({ durationMs, ...detail ?? {} }));
45402
- }
45403
- function perfTime(name, fn, detail) {
45404
- const t = perfStart(name);
45405
- try {
45406
- return fn();
45407
- } finally {
45408
- perfEnd(name, t, detail);
45409
- }
45410
- }
45411
- var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
45412
- if (!isEnabled()) return;
45413
- push({
45414
- name: `profiler:${id}:${phase}`,
45415
- durationMs: actualDuration,
45416
- ts: commitTime,
45417
- detail: { baseDuration }
45418
- });
45419
- log9.debug(`profiler:${id}:${phase}`, () => ({ actualDuration, baseDuration }));
45420
- };
45421
- function getPerfSnapshot() {
45422
- if (ring.length < RING_SIZE) return ring.slice();
45423
- return [...ring.slice(writeIdx), ...ring.slice(0, writeIdx)];
45424
- }
45425
- function getSnapshot2() {
45426
- if (cachedRevision !== revision) {
45427
- cachedSnapshot = getPerfSnapshot();
45428
- cachedRevision = revision;
45429
- }
45430
- return cachedSnapshot;
45431
- }
45432
- function subscribe(fn) {
45433
- subscribers.add(fn);
45434
- return () => {
45435
- subscribers.delete(fn);
45436
- };
45437
- }
45438
- function usePerfBuffer() {
45439
- return useSyncExternalStore(subscribe, getSnapshot2, getSnapshot2);
45440
- }
45441
- function clearPerf() {
45442
- ring.length = 0;
45443
- writeIdx = 0;
45444
- scheduleNotify();
45445
- }
45446
-
45447
- // lib/prepareSchemaForPreview.ts
45448
- function generateEntityRow(entity, idx) {
45449
- const row = { id: String(idx) };
45450
- for (const f3 of entity.fields) {
45451
- if (f3.name === void 0 || f3.name === "id") continue;
45452
- row[f3.name] = generateFieldValue(entity.name, f3, idx);
45453
- }
45454
- return row;
45455
- }
45456
- function generateFieldValue(entityName, field, idx) {
45457
- if ("values" in field && field.values && field.values.length > 0) {
45458
- return field.values[(idx - 1) % field.values.length];
45459
- }
45460
- const fieldName = field.name ?? "";
45461
- switch (field.type) {
45462
- case "string":
45463
- return `${entityName} ${fieldName.charAt(0).toUpperCase() + fieldName.slice(1)} ${idx}`;
45464
- case "number":
45465
- return idx * 10;
45466
- case "boolean":
45467
- return idx % 2 === 0;
45468
- default:
45469
- return field.default ?? null;
45470
- }
45471
- }
45472
- function buildMockData(schema) {
45473
- const t = perfStart("build-mock-data");
45474
- const result = {};
45475
- for (const orbital of schema.orbitals) {
45476
- const entity = orbital.entity;
45477
- if (!entity || typeof entity === "string") continue;
45478
- if (isEntityCall(entity)) continue;
45479
- const entityName = entity.name;
45480
- if (!entityName) continue;
45481
- if (entity.instances && entity.instances.length > 0) {
45482
- result[entityName] = entity.instances;
45483
- continue;
45484
- }
45485
- const rows = Array.from(
45486
- { length: 10 },
45487
- (_, i) => generateEntityRow(entity, i + 1)
45488
- );
45489
- result[entityName] = rows;
45490
- }
45491
- for (const orbital of schema.orbitals) {
45492
- for (const traitRef of orbital.traits ?? []) {
45493
- if (!isInlineTrait3(traitRef)) continue;
45494
- const trait = traitRef;
45495
- const sourceEntity = trait.sourceEntityDefinition;
45496
- if (!sourceEntity || isEntityCall(sourceEntity)) continue;
45497
- const sourceName = sourceEntity.name;
45498
- if (!sourceName) continue;
45499
- if (!result[sourceName]) {
45500
- result[sourceName] = sourceEntity.instances && sourceEntity.instances.length > 0 ? sourceEntity.instances : Array.from(
45501
- { length: 10 },
45502
- (_, i) => generateEntityRow(sourceEntity, i + 1)
45503
- );
45504
- }
45505
- const reboundName = trait.linkedEntity;
45506
- if (!reboundName || reboundName === sourceName) continue;
45507
- const reboundRows = result[reboundName];
45508
- if (!reboundRows || reboundRows.length === 0) continue;
45509
- reboundRows.forEach((row, i) => {
45510
- for (const f3 of sourceEntity.fields) {
45511
- if (f3.name === void 0 || f3.name === "id") continue;
45512
- if (row[f3.name] !== void 0) continue;
45513
- row[f3.name] = generateFieldValue(sourceName, f3, i + 1);
45514
- }
45515
- });
45516
- }
45517
- }
45518
- perfEnd("build-mock-data", t, { orbitalCount: schema.orbitals.length, entityCount: Object.keys(result).length });
45519
- return result;
45520
- }
45521
- function isInlineTrait3(traitRef) {
45522
- return typeof traitRef === "object" && traitRef !== null && "stateMachine" in traitRef;
45523
- }
45524
- function findDataState(sm, initialStateName) {
45525
- return sm.states.find((s) => {
45526
- if (s.name === initialStateName) return false;
45527
- return sm.transitions.some(
45528
- (t) => t.event === "INIT" && (t.from === s.name || Array.isArray(t.from) && t.from.includes(s.name))
45529
- );
45530
- });
45531
- }
45532
- function rewriteTraitInitialState(trait, mockData) {
45533
- const sm = trait.stateMachine;
45534
- if (!sm) return trait;
45535
- const linkedEntity = trait.linkedEntity;
45536
- if (!linkedEntity || !mockData[linkedEntity]?.length) return trait;
45537
- const initialStateName = sm.states.find((s) => s.isInitial)?.name ?? sm.states[0]?.name;
45538
- if (!initialStateName) return trait;
45539
- const dataState = findDataState(sm, initialStateName);
45540
- if (!dataState) return trait;
45541
- const updatedStates = sm.states.map((s) => {
45542
- if (s.name === initialStateName) return { ...s, isInitial: false };
45543
- if (s.name === dataState.name) return { ...s, isInitial: true };
45544
- return s;
45545
- });
45546
- return { ...trait, stateMachine: { ...sm, states: updatedStates } };
45547
- }
45548
- function adjustSchemaForMockData(schema, mockData) {
45549
- let changed = false;
45550
- const updatedOrbitals = schema.orbitals.map((orbital) => {
45551
- const traits2 = orbital.traits ?? [];
45552
- const updatedTraits = traits2.map((traitRef) => {
45553
- if (!isInlineTrait3(traitRef)) return traitRef;
45554
- const updated = rewriteTraitInitialState(traitRef, mockData);
45555
- if (updated !== traitRef) changed = true;
45556
- return updated;
45557
- });
45558
- return changed ? { ...orbital, traits: updatedTraits } : orbital;
45559
- });
45560
- return changed ? { ...schema, orbitals: updatedOrbitals } : schema;
45561
- }
45562
- function prepareSchemaForPreview(input) {
45563
- const parsed = typeof input === "string" ? JSON.parse(input) : input;
45564
- const mockData = buildMockData(parsed);
45565
- const schema = adjustSchemaForMockData(parsed, mockData);
45566
- return { schema, mockData };
45567
- }
45568
44742
  var xOrbitalLog = createLogger("almadar:runtime:cross-orbital");
45569
44743
  var navLog = createLogger("almadar:runtime:navigation");
45570
44744
  function normalizeChild(child) {
@@ -45652,6 +44826,7 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
45652
44826
  hadPrev: prevTraitsRef.current !== void 0
45653
44827
  }));
45654
44828
  if (refChanged) {
44829
+ navLog.info("page:traits-reset", { traitsCount: Array.isArray(traits2) ? traits2.length : -1 });
45655
44830
  uiSlots.clearAll();
45656
44831
  initSentRef.current = false;
45657
44832
  }
@@ -45797,24 +44972,10 @@ function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, onNavi
45797
44972
  pageOrbitalNames: pageOrbitalNames.join(",")
45798
44973
  });
45799
44974
  }, [pageName, allPageTraits, orbitalsByTrait, pageOrbitalNames]);
45800
- const traitConfigsByName = useMemo(() => {
45801
- const map = {};
45802
- const orbitals = schema?.orbitals;
45803
- if (!orbitals) return map;
45804
- for (const orb of orbitals) {
45805
- const traitRefs = orb.traits;
45806
- if (!traitRefs) continue;
45807
- for (const t of traitRefs) {
45808
- if (typeof t === "string") continue;
45809
- const name = t.name ?? t.ref;
45810
- const config = t.config;
45811
- if (typeof name === "string" && config !== void 0) {
45812
- map[name] = config;
45813
- }
45814
- }
45815
- }
45816
- return map;
45817
- }, [schema]);
44975
+ const traitConfigsByName = useMemo(
44976
+ () => buildResolvedTraitConfigs(schema),
44977
+ [schema]
44978
+ );
45818
44979
  const embeddedTraits = useMemo(() => {
45819
44980
  const set = collectEmbeddedTraits(schema);
45820
44981
  xOrbitalLog.info("SchemaRunner:embeddedTraits", {
@@ -46076,5 +45237,16 @@ function BrowserPlayground({
46076
45237
  }
46077
45238
  );
46078
45239
  }
45240
+ function usePerfBuffer() {
45241
+ return useSyncExternalStore(perfStore.subscribe, perfStore.getSnapshot, perfStore.getSnapshot);
45242
+ }
45243
+ var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
45244
+ pushPerfEntry({
45245
+ name: `profiler:${id}:${phase}`,
45246
+ durationMs: actualDuration,
45247
+ ts: commitTime,
45248
+ detail: { baseDuration }
45249
+ });
45250
+ };
46079
45251
 
46080
- export { BrowserPlayground, OrbPreview, PERF_NAMESPACE, adjustSchemaForMockData, buildMockData, clearPerf, clearSchemaCache, createClientEffectHandlers, perfEnd, perfStart, perfTime, prepareSchemaForPreview, profilerOnRender, usePerfBuffer, useResolvedSchema, useTraitStateMachine, wrapCallbackForEvent };
45252
+ export { BrowserPlayground, OrbPreview, clearSchemaCache, createClientEffectHandlers, profilerOnRender, usePerfBuffer, useResolvedSchema, useTraitStateMachine };