@almadar/ui 5.113.0 → 5.115.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) {
@@ -11819,21 +11226,6 @@ var init_renderer = __esm({
11819
11226
  init_slot_definitions();
11820
11227
  }
11821
11228
  });
11822
-
11823
- // lib/wrapCallbackForEvent.ts
11824
- function wrapCallbackForEvent(qualifiedEvent, callbackArgs, emit) {
11825
- const argNames = (callbackArgs ?? []).map((a) => a.name);
11826
- if (argNames.length === 0) {
11827
- return () => emit(qualifiedEvent);
11828
- }
11829
- return (...args) => {
11830
- const payload = {};
11831
- for (let i = 0; i < argNames.length; i += 1) {
11832
- payload[argNames[i]] = args[i];
11833
- }
11834
- emit(qualifiedEvent, payload);
11835
- };
11836
- }
11837
11229
  var init_wrapCallbackForEvent = __esm({
11838
11230
  "lib/wrapCallbackForEvent.ts"() {
11839
11231
  }
@@ -22724,7 +22116,8 @@ function DataGrid({
22724
22116
  const { t } = useTranslate();
22725
22117
  const [selectedIds, setSelectedIds] = useState(/* @__PURE__ */ new Set());
22726
22118
  const [visibleCount, setVisibleCount] = useState(pageSize || Infinity);
22727
- 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 : [];
22728
22121
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
22729
22122
  const dnd = useDataDnd({
22730
22123
  items: allDataRaw,
@@ -22768,8 +22161,8 @@ function DataGrid({
22768
22161
  const titleField = fieldDefs.find((f3) => f3.variant === "h3" || f3.variant === "h4") ?? fieldDefs[0];
22769
22162
  const badgeFields = fieldDefs.filter((f3) => f3.variant === "badge" && f3 !== titleField);
22770
22163
  const bodyFields = fieldDefs.filter((f3) => f3 !== titleField && !badgeFields.includes(f3));
22771
- const primaryActions = itemActions?.filter((a) => a.variant !== "danger") ?? [];
22772
- 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");
22773
22166
  const handleActionClick = (action, itemData) => (e) => {
22774
22167
  e.stopPropagation();
22775
22168
  const payload = {
@@ -35299,7 +34692,7 @@ function measureLabelWidth(text) {
35299
34692
  if (typeof document === "undefined") return text.length * 6;
35300
34693
  if (!labelMeasureCtx) labelMeasureCtx = document.createElement("canvas").getContext("2d");
35301
34694
  if (!labelMeasureCtx) return text.length * 6;
35302
- labelMeasureCtx.font = "10px system-ui";
34695
+ labelMeasureCtx.font = "12px system-ui";
35303
34696
  return labelMeasureCtx.measureText(text).width;
35304
34697
  }
35305
34698
  function getGroupColor(group, groups) {
@@ -35345,6 +34738,7 @@ var init_GraphCanvas = __esm({
35345
34738
  actions,
35346
34739
  onNodeClick,
35347
34740
  onNodeDoubleClick,
34741
+ onBadgeClick,
35348
34742
  nodeClickEvent,
35349
34743
  selectedNodeId,
35350
34744
  repulsion = 800,
@@ -35462,7 +34856,7 @@ var init_GraphCanvas = __esm({
35462
34856
  nodesRef.current = simNodes;
35463
34857
  if (layout === "force") {
35464
34858
  let iterations = 0;
35465
- const maxIterations = 100;
34859
+ const maxIterations = 300;
35466
34860
  const tick = () => {
35467
34861
  const nodes = nodesRef.current;
35468
34862
  const centerX = w / 2;
@@ -35492,7 +34886,9 @@ var init_GraphCanvas = __esm({
35492
34886
  const dx = target.x - source.x;
35493
34887
  const dy = target.y - source.y;
35494
34888
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
35495
- const force = (dist - linkDistance) * 0.05;
34889
+ const w2 = Math.min(1, Math.max(0, edge.weight ?? 1));
34890
+ const linkTarget = linkDistance * (0.5 + (1 - w2) * 1.5);
34891
+ const force = (dist - linkTarget) * (0.04 + 0.1 * w2);
35496
34892
  const fx = dx / dist * force;
35497
34893
  const fy = dy / dist * force;
35498
34894
  source.fx += fx;
@@ -35500,9 +34896,27 @@ var init_GraphCanvas = __esm({
35500
34896
  target.fx -= fx;
35501
34897
  target.fy -= fy;
35502
34898
  }
34899
+ const centroids = /* @__PURE__ */ new Map();
35503
34900
  for (const node of nodes) {
35504
- node.fx += (centerX - node.x) * 0.01;
35505
- node.fy += (centerY - node.y) * 0.01;
34901
+ const g = node.group ?? "__none__";
34902
+ let c = centroids.get(g);
34903
+ if (!c) {
34904
+ c = { x: 0, y: 0, n: 0 };
34905
+ centroids.set(g, c);
34906
+ }
34907
+ c.x += node.x;
34908
+ c.y += node.y;
34909
+ c.n += 1;
34910
+ }
34911
+ for (const node of nodes) {
34912
+ const c = centroids.get(node.group ?? "__none__");
34913
+ if (c && c.n > 1) {
34914
+ node.fx += (c.x / c.n - node.x) * 0.04;
34915
+ node.fy += (c.y / c.n - node.y) * 0.04;
34916
+ } else {
34917
+ node.fx += (centerX - node.x) * 0.01;
34918
+ node.fy += (centerY - node.y) * 0.01;
34919
+ }
35506
34920
  }
35507
34921
  const damping = 0.9;
35508
34922
  for (const node of nodes) {
@@ -35514,7 +34928,7 @@ var init_GraphCanvas = __esm({
35514
34928
  node.y = Math.max(30, Math.min(h - 30, node.y));
35515
34929
  }
35516
34930
  const LABEL_GAP = 12;
35517
- const LABEL_H = 12;
34931
+ const LABEL_H = 16;
35518
34932
  const pad = nodeSpacing / 2;
35519
34933
  for (let i = 0; i < nodes.length; i++) {
35520
34934
  for (let j = i + 1; j < nodes.length; j++) {
@@ -35535,13 +34949,13 @@ var init_GraphCanvas = __esm({
35535
34949
  const overlapY = Math.min(aBot, bBot) - Math.max(aTop, bTop);
35536
34950
  if (overlapX > 0 && overlapY > 0) {
35537
34951
  if (overlapX <= overlapY) {
35538
- const push2 = overlapX / 2 * (b.x >= a.x ? 1 : -1);
35539
- a.x = Math.max(30, Math.min(w - 30, a.x - push2));
35540
- b.x = Math.max(30, Math.min(w - 30, b.x + push2));
34952
+ const push = overlapX / 2 * (b.x >= a.x ? 1 : -1);
34953
+ a.x = Math.max(30, Math.min(w - 30, a.x - push));
34954
+ b.x = Math.max(30, Math.min(w - 30, b.x + push));
35541
34955
  } else {
35542
- const push2 = overlapY / 2 * (bTop + bBot >= aTop + aBot ? 1 : -1);
35543
- a.y = Math.max(30, Math.min(h - 30, a.y - push2));
35544
- b.y = Math.max(30, Math.min(h - 30, b.y + push2));
34956
+ const push = overlapY / 2 * (bTop + bBot >= aTop + aBot ? 1 : -1);
34957
+ a.y = Math.max(30, Math.min(h - 30, a.y - push));
34958
+ b.y = Math.max(30, Math.min(h - 30, b.y + push));
35545
34959
  }
35546
34960
  }
35547
34961
  }
@@ -35569,6 +34983,11 @@ var init_GraphCanvas = __esm({
35569
34983
  const h = height;
35570
34984
  const nodes = nodesRef.current;
35571
34985
  const accentColor = resolveColor3("var(--color-accent)", canvas);
34986
+ const fontFamily = resolveColor3("var(--font-family)", canvas) || "system-ui";
34987
+ const fgColor = resolveColor3("var(--color-foreground)", canvas);
34988
+ const mutedColor = resolveColor3("var(--color-muted-foreground)", canvas) || fgColor;
34989
+ const bgColor = resolveColor3("var(--color-background)", canvas) || "#ffffff";
34990
+ const accentFg = resolveColor3("var(--color-accent-foreground)", canvas) || "#ffffff";
35572
34991
  const dpr = typeof window !== "undefined" && window.devicePixelRatio || 1;
35573
34992
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
35574
34993
  ctx.clearRect(0, 0, w, h);
@@ -35588,19 +35007,21 @@ var init_GraphCanvas = __esm({
35588
35007
  const target = nodes.find((n) => n.id === edge.target);
35589
35008
  if (!source || !target) continue;
35590
35009
  const incident = !!hoveredNode && (edge.source === hoveredNode || edge.target === hoveredNode);
35591
- ctx.globalAlpha = hoveredNode ? incident ? 1 : 0.05 : linkOpacity;
35010
+ const w2 = edge.weight ?? 1;
35011
+ ctx.globalAlpha = hoveredNode ? incident ? 1 : 0.05 : linkOpacity * w2;
35592
35012
  ctx.beginPath();
35593
35013
  ctx.moveTo(source.x, source.y);
35594
35014
  ctx.lineTo(target.x, target.y);
35595
35015
  ctx.strokeStyle = incident ? accentColor : edge.color || "#888888";
35596
- ctx.lineWidth = incident ? 2 : edge.weight ? Math.max(1, edge.weight) : 1;
35016
+ ctx.lineWidth = incident ? 2 : Math.max(0.75, w2);
35597
35017
  ctx.stroke();
35598
35018
  if (edge.label && showLabels) {
35599
35019
  const mx = (source.x + target.x) / 2;
35600
35020
  const my = (source.y + target.y) / 2;
35601
- ctx.fillStyle = "#888888";
35602
- ctx.font = "9px system-ui";
35021
+ ctx.fillStyle = mutedColor;
35022
+ ctx.font = `9px ${fontFamily}`;
35603
35023
  ctx.textAlign = "center";
35024
+ ctx.textBaseline = "alphabetic";
35604
35025
  ctx.fillText(edge.label, mx, my - 4);
35605
35026
  }
35606
35027
  }
@@ -35625,10 +35046,33 @@ var init_GraphCanvas = __esm({
35625
35046
  }
35626
35047
  ctx.stroke();
35627
35048
  if (showLabels && node.label) {
35628
- ctx.fillStyle = "#666666";
35629
- ctx.font = `${isSelected || isHovered ? "bold " : ""}10px system-ui`;
35049
+ ctx.font = `${isSelected || isHovered ? "600" : "500"} 12px ${fontFamily}`;
35630
35050
  ctx.textAlign = "center";
35631
- ctx.fillText(node.label, node.x, node.y + radius + 12);
35051
+ ctx.textBaseline = "middle";
35052
+ const ly = node.y + radius + 14;
35053
+ ctx.lineWidth = 3;
35054
+ ctx.lineJoin = "round";
35055
+ ctx.strokeStyle = bgColor;
35056
+ ctx.strokeText(node.label, node.x, ly);
35057
+ ctx.fillStyle = isSelected || isHovered ? fgColor : mutedColor;
35058
+ ctx.fillText(node.label, node.x, ly);
35059
+ }
35060
+ if (node.badge && node.badge > 1) {
35061
+ const bx = node.x + radius * 0.7;
35062
+ const by = node.y - radius * 0.7;
35063
+ const br = Math.max(7, Math.min(11, radius * 0.45));
35064
+ ctx.beginPath();
35065
+ ctx.arc(bx, by, br, 0, Math.PI * 2);
35066
+ ctx.fillStyle = accentColor;
35067
+ ctx.fill();
35068
+ ctx.strokeStyle = bgColor;
35069
+ ctx.lineWidth = 2;
35070
+ ctx.stroke();
35071
+ ctx.fillStyle = accentFg;
35072
+ ctx.font = `600 9px ${fontFamily}`;
35073
+ ctx.textAlign = "center";
35074
+ ctx.textBaseline = "middle";
35075
+ ctx.fillText(String(node.badge), bx, by + 0.5);
35632
35076
  }
35633
35077
  }
35634
35078
  ctx.restore();
@@ -35721,11 +35165,21 @@ var init_GraphCanvas = __esm({
35721
35165
  if (!coords) return;
35722
35166
  const node = nodeAt(coords.graphX, coords.graphY);
35723
35167
  if (node) {
35168
+ if (node.badge && node.badge > 1 && onBadgeClick) {
35169
+ const r = (node.size || 8) + (selectedNodeId === node.id ? 4 : 0);
35170
+ const bx = node.x + r * 0.7;
35171
+ const by = node.y - r * 0.7;
35172
+ const br = Math.max(7, Math.min(11, r * 0.45)) + 3;
35173
+ if (Math.hypot(coords.graphX - bx, coords.graphY - by) <= br) {
35174
+ onBadgeClick(node);
35175
+ return;
35176
+ }
35177
+ }
35724
35178
  handleNodeClick(node);
35725
35179
  }
35726
35180
  }
35727
35181
  },
35728
- [toCoords, nodeAt, handleNodeClick]
35182
+ [toCoords, nodeAt, handleNodeClick, onBadgeClick, selectedNodeId]
35729
35183
  );
35730
35184
  const handlePointerLeave = useCallback(() => {
35731
35185
  setHoveredNode(null);
@@ -40246,7 +39700,7 @@ function getAllEvents(traits2) {
40246
39700
  function EventDispatcherTab({ traits: traits2, schema }) {
40247
39701
  const eventBus = useEventBus();
40248
39702
  const { t } = useTranslate();
40249
- const [log10, setLog] = React81.useState([]);
39703
+ const [log9, setLog] = React81.useState([]);
40250
39704
  const prevStatesRef = React81.useRef(/* @__PURE__ */ new Map());
40251
39705
  React81.useEffect(() => {
40252
39706
  for (const trait of traits2) {
@@ -40310,9 +39764,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
40310
39764
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.otherEvents") }),
40311
39765
  /* @__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)) })
40312
39766
  ] }),
40313
- log10.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
39767
+ log9.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
40314
39768
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.recentTransitions") }),
40315
- /* @__PURE__ */ jsx(Stack, { gap: "xs", children: log10.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
39769
+ /* @__PURE__ */ jsx(Stack, { gap: "xs", children: log9.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
40316
39770
  /* @__PURE__ */ jsx("span", { className: "text-purple-400", children: entry.traitName }),
40317
39771
  " ",
40318
39772
  /* @__PURE__ */ jsx("span", { className: "text-gray-500", children: entry.from }),
@@ -43949,27 +43403,27 @@ var log2 = createLogger("almadar:ui:shared-entity-store");
43949
43403
  var EMPTY_ENTITY_STATE = {};
43950
43404
  function createSharedEntityStore() {
43951
43405
  const states = /* @__PURE__ */ new Map();
43952
- const subscribers2 = /* @__PURE__ */ new Map();
43953
- const getSnapshot3 = (entityId) => states.get(entityId) ?? EMPTY_ENTITY_STATE;
43954
- const subscribe2 = (entityId, callback) => {
43955
- let set = subscribers2.get(entityId);
43406
+ const subscribers = /* @__PURE__ */ new Map();
43407
+ const getSnapshot2 = (entityId) => states.get(entityId) ?? EMPTY_ENTITY_STATE;
43408
+ const subscribe = (entityId, callback) => {
43409
+ let set = subscribers.get(entityId);
43956
43410
  if (!set) {
43957
43411
  set = /* @__PURE__ */ new Set();
43958
- subscribers2.set(entityId, set);
43412
+ subscribers.set(entityId, set);
43959
43413
  }
43960
43414
  set.add(callback);
43961
43415
  return () => {
43962
- const current = subscribers2.get(entityId);
43416
+ const current = subscribers.get(entityId);
43963
43417
  if (!current) return;
43964
43418
  current.delete(callback);
43965
43419
  if (current.size === 0) {
43966
- subscribers2.delete(entityId);
43420
+ subscribers.delete(entityId);
43967
43421
  }
43968
43422
  };
43969
43423
  };
43970
43424
  const commit = (entityId, nextState) => {
43971
43425
  states.set(entityId, nextState);
43972
- const set = subscribers2.get(entityId);
43426
+ const set = subscribers.get(entityId);
43973
43427
  if (!set) return;
43974
43428
  set.forEach((callback) => {
43975
43429
  try {
@@ -43987,7 +43441,7 @@ function createSharedEntityStore() {
43987
43441
  states.set(entityId, initialState);
43988
43442
  }
43989
43443
  };
43990
- return { getSnapshot: getSnapshot3, subscribe: subscribe2, commit, seed };
43444
+ return { getSnapshot: getSnapshot2, subscribe, commit, seed };
43991
43445
  }
43992
43446
  function useSharedEntityStore() {
43993
43447
  const storeRef = useRef(null);
@@ -44063,6 +43517,11 @@ function createClientEffectHandlers(options) {
44063
43517
  };
44064
43518
  }
44065
43519
  var lambdaLog = createLogger("almadar:ui:fn-form-lambda");
43520
+ function isOperatorCall(value) {
43521
+ const first = value[0];
43522
+ if (typeof first !== "string") return false;
43523
+ return isKnownStdOperator(first) || first.includes("/") || first === "lambda" || first === "let";
43524
+ }
44066
43525
  function isFnFormLambda(value) {
44067
43526
  if (!Array.isArray(value)) return false;
44068
43527
  const arr = value;
@@ -44102,7 +43561,14 @@ function resolveLambdaBindings(body, params, item, index) {
44102
43561
  return body;
44103
43562
  }
44104
43563
  if (Array.isArray(body)) {
44105
- return body.map((b) => recur(b));
43564
+ if (isFnFormLambda(body)) return body;
43565
+ const arr = body;
43566
+ const substituted = arr.map((b) => recur(b));
43567
+ if (isOperatorCall(substituted) && isSExpr(substituted)) {
43568
+ const evaluated = evaluate(substituted, createMinimalContext());
43569
+ return isEventPayloadValue(evaluated) ? evaluated : String(evaluated);
43570
+ }
43571
+ return substituted;
44106
43572
  }
44107
43573
  if (body !== null && typeof body === "object" && !React81__default.isValidElement(body) && !(body instanceof Date) && typeof body !== "function") {
44108
43574
  const out = {};
@@ -44299,8 +43765,8 @@ function getBindingConfig(binding) {
44299
43765
  function evalFieldDefault(value) {
44300
43766
  if (!Array.isArray(value) || value.length === 0) return value;
44301
43767
  const head = value[0];
44302
- const isSExpr = typeof head === "string" && (head.includes("/") || head === "let" || head === "if" || head === "lambda");
44303
- if (!isSExpr) return value;
43768
+ const isSExpr2 = typeof head === "string" && (head.includes("/") || head === "let" || head === "if" || head === "lambda");
43769
+ if (!isSExpr2) return value;
44304
43770
  try {
44305
43771
  return evaluate(value, createMinimalContext({}, {}, ""));
44306
43772
  } catch {
@@ -44374,7 +43840,9 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
44374
43840
  const traitDefs = traitBindings.map(toTraitDefinition);
44375
43841
  const m = new StateMachineManager(traitDefs);
44376
43842
  for (const binding of traitBindings) {
44377
- const cfg = getBindingConfig(binding) ?? traitConfigsByName?.[binding.trait.name];
43843
+ const rawCfg = getBindingConfig(binding);
43844
+ const resolvedCfg = traitConfigsByName?.[binding.trait.name];
43845
+ const cfg = rawCfg || resolvedCfg ? { ...rawCfg ?? {}, ...resolvedCfg ?? {} } : void 0;
44378
43846
  if (cfg !== void 0) {
44379
43847
  m.setTraitConfig(binding.trait.name, cfg);
44380
43848
  }
@@ -44552,7 +44020,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
44552
44020
  };
44553
44021
  }, [traitBindings]);
44554
44022
  const executeTransitionEffects = useCallback(async (params) => {
44555
- const { binding, previousState, newState, payload, flushEvent, syncOnly, log: log10 } = params;
44023
+ const { binding, previousState, newState, payload, flushEvent, syncOnly, log: log9 } = params;
44556
44024
  const traitName = binding.trait.name;
44557
44025
  const linkedEntity = binding.linkedEntity || "";
44558
44026
  const entityId = payload?.entityId;
@@ -44626,10 +44094,20 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
44626
44094
  state: previousState
44627
44095
  };
44628
44096
  const sharedDeclared = collectDeclaredConfigDefaults(binding.trait);
44629
- const sharedCallSite = getBindingConfig(binding);
44630
- if (sharedDeclared || sharedCallSite) {
44097
+ const sharedResolved = traitConfigsByName?.[traitName];
44098
+ const sharedCallSiteRaw = getBindingConfig(binding);
44099
+ const sharedCallSite = sharedCallSiteRaw ? resolveCallSitePayloadCaptures(
44100
+ Object.fromEntries(
44101
+ Object.entries(sharedCallSiteRaw).filter(
44102
+ ([, v]) => !(typeof v === "string" && v.startsWith("@config."))
44103
+ )
44104
+ ),
44105
+ payload || {}
44106
+ ) : void 0;
44107
+ if (sharedDeclared || sharedResolved || sharedCallSite) {
44631
44108
  sharedBindings.config = {
44632
44109
  ...sharedDeclared ?? {},
44110
+ ...sharedResolved ?? {},
44633
44111
  ...sharedCallSite ?? {}
44634
44112
  };
44635
44113
  }
@@ -44663,7 +44141,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
44663
44141
  ...handlers,
44664
44142
  set: async (targetId, field, value) => {
44665
44143
  if (baseSet) await baseSet(targetId, field, value);
44666
- log10.debug("set:write", {
44144
+ log9.debug("set:write", {
44667
44145
  traitName,
44668
44146
  field,
44669
44147
  value: JSON.stringify(value),
@@ -44677,11 +44155,21 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
44677
44155
  state: previousState
44678
44156
  };
44679
44157
  const declaredDefaults = collectDeclaredConfigDefaults(binding.trait);
44158
+ const resolvedDefaults = traitConfigsByName?.[traitName];
44680
44159
  const callSiteConfig = getBindingConfig(binding);
44681
- if (declaredDefaults || callSiteConfig) {
44160
+ const callSiteOverrides = callSiteConfig ? resolveCallSitePayloadCaptures(
44161
+ Object.fromEntries(
44162
+ Object.entries(callSiteConfig).filter(
44163
+ ([, v]) => !(typeof v === "string" && v.startsWith("@config."))
44164
+ )
44165
+ ),
44166
+ payload || {}
44167
+ ) : void 0;
44168
+ if (declaredDefaults || resolvedDefaults || callSiteOverrides) {
44682
44169
  bindingCtx.config = {
44683
44170
  ...declaredDefaults ?? {},
44684
- ...callSiteConfig ?? {}
44171
+ ...resolvedDefaults ?? {},
44172
+ ...callSiteOverrides ?? {}
44685
44173
  };
44686
44174
  }
44687
44175
  if (traitName === "Authority" || traitName === "Hero") {
@@ -44730,7 +44218,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
44730
44218
  if (sharedKey !== void 0) {
44731
44219
  sharedEntityStore.commit(sharedKey, liveEntity);
44732
44220
  }
44733
- log10.debug("effects:executed", () => ({
44221
+ log9.debug("effects:executed", () => ({
44734
44222
  traitName,
44735
44223
  transition: `${previousState}->${newState}`,
44736
44224
  event: flushEvent,
@@ -44740,7 +44228,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
44740
44228
  slotsTouched: Array.from(pendingSlots.keys()).join(",")
44741
44229
  }));
44742
44230
  for (const [slot, patterns] of pendingSlots) {
44743
- log10.debug("flush:slot", {
44231
+ log9.debug("flush:slot", {
44744
44232
  traitName,
44745
44233
  slot,
44746
44234
  patternCount: patterns.length,
@@ -44755,7 +44243,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
44755
44243
  });
44756
44244
  }
44757
44245
  } catch (error) {
44758
- log10.error("effects:error", {
44246
+ log9.error("effects:error", {
44759
44247
  traitName,
44760
44248
  transition: `${previousState}->${newState}`,
44761
44249
  event: flushEvent,
@@ -44777,7 +44265,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
44777
44265
  payload: {},
44778
44266
  state: currentState
44779
44267
  };
44780
- const bindingCfg = getBindingConfig(binding);
44268
+ const bindingCfg = getBindingConfig(binding) ?? traitConfigsByName?.[traitName];
44781
44269
  if (bindingCfg) {
44782
44270
  guardCtx.config = bindingCfg;
44783
44271
  }
@@ -45140,17 +44628,19 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
45140
44628
  }, [traitBindings, eventBus, enqueueAndDrain]);
45141
44629
  useEffect(() => {
45142
44630
  const mgr = managerRef.current;
45143
- const inited = initedTraitsRef.current;
44631
+ const eventsToFire = /* @__PURE__ */ new Set();
45144
44632
  for (const binding of traitBindings) {
45145
44633
  const traitName = binding.trait.name;
45146
- if (inited.has(traitName)) continue;
45147
44634
  const lifecycleEvent = LIFECYCLE_EVENTS.find(
45148
44635
  (evt) => mgr.canHandleEvent(traitName, evt)
45149
44636
  );
45150
- if (lifecycleEvent === void 0) continue;
45151
- inited.add(traitName);
45152
- stateLog.debug("mount:fire-lifecycle", { traitName, event: lifecycleEvent });
45153
- enqueueAndDrain(lifecycleEvent, {});
44637
+ if (lifecycleEvent !== void 0) {
44638
+ eventsToFire.add(lifecycleEvent);
44639
+ }
44640
+ }
44641
+ for (const event of eventsToFire) {
44642
+ stateLog.debug("mount:fire-lifecycle", { event, traitCount: traitBindings.length });
44643
+ enqueueAndDrain(event, {});
45154
44644
  }
45155
44645
  return () => {
45156
44646
  initedTraitsRef.current = /* @__PURE__ */ new Set();
@@ -45265,343 +44755,8 @@ init_Typography();
45265
44755
  init_UISlotRenderer();
45266
44756
  init_useEventBus();
45267
44757
 
45268
- // lib/embedded-traits.ts
45269
- var TRAIT_BINDING_PREFIX = "@trait.";
45270
- function collectTraitRefsFromValue(value, into) {
45271
- if (value === null || value === void 0) return;
45272
- if (typeof value === "string") {
45273
- if (value.startsWith(TRAIT_BINDING_PREFIX)) {
45274
- const rest = value.slice(TRAIT_BINDING_PREFIX.length);
45275
- const dot = rest.indexOf(".");
45276
- const traitName = dot === -1 ? rest : rest.slice(0, dot);
45277
- if (traitName.length > 0) into.add(traitName);
45278
- }
45279
- return;
45280
- }
45281
- if (Array.isArray(value)) {
45282
- for (const item of value) collectTraitRefsFromValue(item, into);
45283
- return;
45284
- }
45285
- if (typeof value === "object") {
45286
- for (const v of Object.values(value)) {
45287
- collectTraitRefsFromValue(v, into);
45288
- }
45289
- }
45290
- }
45291
- function collectTraitRefsFromEffects(effects, into) {
45292
- if (!effects) return;
45293
- for (const effect of effects) {
45294
- if (!Array.isArray(effect)) continue;
45295
- if (effect[0] === "render-ui" && effect.length >= 3) {
45296
- collectTraitRefsFromValue(effect[2], into);
45297
- continue;
45298
- }
45299
- for (let i = 1; i < effect.length; i++) {
45300
- const arg = effect[i];
45301
- if (Array.isArray(arg)) collectTraitRefsFromEffects([arg], into);
45302
- else collectTraitRefsFromValue(arg, into);
45303
- }
45304
- }
45305
- }
45306
- function collectTraitRefsFromResolvedTrait(trait) {
45307
- const out = /* @__PURE__ */ new Set();
45308
- for (const transition of trait.transitions ?? []) {
45309
- collectTraitRefsFromEffects(transition.effects, out);
45310
- }
45311
- for (const tick of trait.ticks ?? []) {
45312
- collectTraitRefsFromEffects(tick.effects, out);
45313
- }
45314
- return out;
45315
- }
45316
- function collectEmbeddedTraits(schema) {
45317
- const out = /* @__PURE__ */ new Set();
45318
- if (!schema?.orbitals) return out;
45319
- for (const orbital of schema.orbitals) {
45320
- const traits2 = orbital.traits;
45321
- if (!Array.isArray(traits2)) continue;
45322
- for (const traitRef of traits2) {
45323
- if (!traitRef || typeof traitRef !== "object") continue;
45324
- const resolved = traitRef._resolved;
45325
- const target = resolved && typeof resolved === "object" ? resolved : traitRef;
45326
- if (target.config) {
45327
- collectTraitRefsFromValue(target.config, out);
45328
- }
45329
- const transitions = target.stateMachine?.transitions;
45330
- if (!Array.isArray(transitions)) continue;
45331
- for (const t of transitions) {
45332
- collectTraitRefsFromEffects(t.effects, out);
45333
- }
45334
- collectTraitRefsFromEffects(target.initialEffects, out);
45335
- const ticks2 = target.ticks;
45336
- if (Array.isArray(ticks2)) {
45337
- for (const tick of ticks2) {
45338
- collectTraitRefsFromEffects(tick.effects, out);
45339
- }
45340
- }
45341
- }
45342
- }
45343
- return out;
45344
- }
45345
-
45346
- // lib/orbitalsByTrait.ts
45347
- function buildOrbitalsByTrait(schema, resolvedPages = []) {
45348
- const map = {};
45349
- if (!schema?.orbitals) return map;
45350
- const pagePathToOrbital = {};
45351
- for (const orb of schema.orbitals) {
45352
- for (const traitRef of orb.traits ?? []) {
45353
- let traitName;
45354
- if (typeof traitRef === "string") {
45355
- const parts = traitRef.split(".");
45356
- traitName = parts[parts.length - 1];
45357
- } else if (typeof traitRef.ref === "string") {
45358
- const parts = traitRef.ref.split(".");
45359
- traitName = traitRef.name ?? parts[parts.length - 1];
45360
- } else if (typeof traitRef.name === "string") {
45361
- traitName = traitRef.name;
45362
- }
45363
- if (traitName) map[traitName] = orb.name;
45364
- }
45365
- for (const pg of orb.pages ?? []) {
45366
- const path = typeof pg === "string" ? pg : pg?.path;
45367
- if (path) pagePathToOrbital[path] = orb.name;
45368
- }
45369
- }
45370
- for (const page of resolvedPages) {
45371
- const orbital = page.path ? pagePathToOrbital[page.path] : void 0;
45372
- if (!orbital) continue;
45373
- for (const traitName of page.traitNames) {
45374
- if (traitName && !(traitName in map)) map[traitName] = orbital;
45375
- }
45376
- }
45377
- return map;
45378
- }
45379
-
45380
44758
  // runtime/OrbPreview.tsx
45381
44759
  init_verificationRegistry();
45382
- var PERF_NAMESPACE = "almadar:perf:canvas";
45383
- var log9 = createLogger(PERF_NAMESPACE);
45384
- var RING_SIZE = 50;
45385
- var ring = [];
45386
- var writeIdx = 0;
45387
- var subscribers = /* @__PURE__ */ new Set();
45388
- var notifyScheduled = false;
45389
- var revision = 0;
45390
- var cachedSnapshot = [];
45391
- var cachedRevision = -1;
45392
- function scheduleNotify() {
45393
- if (notifyScheduled) return;
45394
- notifyScheduled = true;
45395
- queueMicrotask(() => {
45396
- notifyScheduled = false;
45397
- revision++;
45398
- for (const fn of subscribers) fn();
45399
- });
45400
- }
45401
- function push(entry) {
45402
- if (ring.length < RING_SIZE) {
45403
- ring.push(entry);
45404
- } else {
45405
- ring[writeIdx] = entry;
45406
- }
45407
- writeIdx = (writeIdx + 1) % RING_SIZE;
45408
- scheduleNotify();
45409
- }
45410
- function isEnabled() {
45411
- return isLogLevelEnabled("DEBUG", PERF_NAMESPACE);
45412
- }
45413
- function now() {
45414
- return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
45415
- }
45416
- function perfStart(name) {
45417
- if (!isEnabled()) return -1;
45418
- if (typeof performance !== "undefined" && typeof performance.mark === "function") {
45419
- try {
45420
- performance.mark(`${name}-start`);
45421
- } catch {
45422
- }
45423
- }
45424
- return now();
45425
- }
45426
- function perfEnd(name, startToken, detail) {
45427
- if (startToken < 0 || !isEnabled()) return;
45428
- const endTs = now();
45429
- const durationMs = endTs - startToken;
45430
- if (typeof performance !== "undefined" && typeof performance.measure === "function") {
45431
- try {
45432
- performance.mark(`${name}-end`);
45433
- performance.measure(name, `${name}-start`, `${name}-end`);
45434
- } catch {
45435
- }
45436
- }
45437
- push({ name, durationMs, ts: endTs, detail });
45438
- log9.debug(name, () => ({ durationMs, ...detail ?? {} }));
45439
- }
45440
- function perfTime(name, fn, detail) {
45441
- const t = perfStart(name);
45442
- try {
45443
- return fn();
45444
- } finally {
45445
- perfEnd(name, t, detail);
45446
- }
45447
- }
45448
- var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
45449
- if (!isEnabled()) return;
45450
- push({
45451
- name: `profiler:${id}:${phase}`,
45452
- durationMs: actualDuration,
45453
- ts: commitTime,
45454
- detail: { baseDuration }
45455
- });
45456
- log9.debug(`profiler:${id}:${phase}`, () => ({ actualDuration, baseDuration }));
45457
- };
45458
- function getPerfSnapshot() {
45459
- if (ring.length < RING_SIZE) return ring.slice();
45460
- return [...ring.slice(writeIdx), ...ring.slice(0, writeIdx)];
45461
- }
45462
- function getSnapshot2() {
45463
- if (cachedRevision !== revision) {
45464
- cachedSnapshot = getPerfSnapshot();
45465
- cachedRevision = revision;
45466
- }
45467
- return cachedSnapshot;
45468
- }
45469
- function subscribe(fn) {
45470
- subscribers.add(fn);
45471
- return () => {
45472
- subscribers.delete(fn);
45473
- };
45474
- }
45475
- function usePerfBuffer() {
45476
- return useSyncExternalStore(subscribe, getSnapshot2, getSnapshot2);
45477
- }
45478
- function clearPerf() {
45479
- ring.length = 0;
45480
- writeIdx = 0;
45481
- scheduleNotify();
45482
- }
45483
-
45484
- // lib/prepareSchemaForPreview.ts
45485
- function generateEntityRow(entity, idx) {
45486
- const row = { id: String(idx) };
45487
- for (const f3 of entity.fields) {
45488
- if (f3.name === void 0 || f3.name === "id") continue;
45489
- row[f3.name] = generateFieldValue(entity.name, f3, idx);
45490
- }
45491
- return row;
45492
- }
45493
- function generateFieldValue(entityName, field, idx) {
45494
- if ("values" in field && field.values && field.values.length > 0) {
45495
- return field.values[(idx - 1) % field.values.length];
45496
- }
45497
- const fieldName = field.name ?? "";
45498
- switch (field.type) {
45499
- case "string":
45500
- return `${entityName} ${fieldName.charAt(0).toUpperCase() + fieldName.slice(1)} ${idx}`;
45501
- case "number":
45502
- return idx * 10;
45503
- case "boolean":
45504
- return idx % 2 === 0;
45505
- default:
45506
- return field.default ?? null;
45507
- }
45508
- }
45509
- function buildMockData(schema) {
45510
- const t = perfStart("build-mock-data");
45511
- const result = {};
45512
- for (const orbital of schema.orbitals) {
45513
- const entity = orbital.entity;
45514
- if (!entity || typeof entity === "string") continue;
45515
- if (isEntityCall(entity)) continue;
45516
- const entityName = entity.name;
45517
- if (!entityName) continue;
45518
- if (entity.instances && entity.instances.length > 0) {
45519
- result[entityName] = entity.instances;
45520
- continue;
45521
- }
45522
- const rows = Array.from(
45523
- { length: 10 },
45524
- (_, i) => generateEntityRow(entity, i + 1)
45525
- );
45526
- result[entityName] = rows;
45527
- }
45528
- for (const orbital of schema.orbitals) {
45529
- for (const traitRef of orbital.traits ?? []) {
45530
- if (!isInlineTrait3(traitRef)) continue;
45531
- const trait = traitRef;
45532
- const sourceEntity = trait.sourceEntityDefinition;
45533
- if (!sourceEntity || isEntityCall(sourceEntity)) continue;
45534
- const sourceName = sourceEntity.name;
45535
- if (!sourceName) continue;
45536
- if (!result[sourceName]) {
45537
- result[sourceName] = sourceEntity.instances && sourceEntity.instances.length > 0 ? sourceEntity.instances : Array.from(
45538
- { length: 10 },
45539
- (_, i) => generateEntityRow(sourceEntity, i + 1)
45540
- );
45541
- }
45542
- const reboundName = trait.linkedEntity;
45543
- if (!reboundName || reboundName === sourceName) continue;
45544
- const reboundRows = result[reboundName];
45545
- if (!reboundRows || reboundRows.length === 0) continue;
45546
- reboundRows.forEach((row, i) => {
45547
- for (const f3 of sourceEntity.fields) {
45548
- if (f3.name === void 0 || f3.name === "id") continue;
45549
- if (row[f3.name] !== void 0) continue;
45550
- row[f3.name] = generateFieldValue(sourceName, f3, i + 1);
45551
- }
45552
- });
45553
- }
45554
- }
45555
- perfEnd("build-mock-data", t, { orbitalCount: schema.orbitals.length, entityCount: Object.keys(result).length });
45556
- return result;
45557
- }
45558
- function isInlineTrait3(traitRef) {
45559
- return typeof traitRef === "object" && traitRef !== null && "stateMachine" in traitRef;
45560
- }
45561
- function findDataState(sm, initialStateName) {
45562
- return sm.states.find((s) => {
45563
- if (s.name === initialStateName) return false;
45564
- return sm.transitions.some(
45565
- (t) => t.event === "INIT" && (t.from === s.name || Array.isArray(t.from) && t.from.includes(s.name))
45566
- );
45567
- });
45568
- }
45569
- function rewriteTraitInitialState(trait, mockData) {
45570
- const sm = trait.stateMachine;
45571
- if (!sm) return trait;
45572
- const linkedEntity = trait.linkedEntity;
45573
- if (!linkedEntity || !mockData[linkedEntity]?.length) return trait;
45574
- const initialStateName = sm.states.find((s) => s.isInitial)?.name ?? sm.states[0]?.name;
45575
- if (!initialStateName) return trait;
45576
- const dataState = findDataState(sm, initialStateName);
45577
- if (!dataState) return trait;
45578
- const updatedStates = sm.states.map((s) => {
45579
- if (s.name === initialStateName) return { ...s, isInitial: false };
45580
- if (s.name === dataState.name) return { ...s, isInitial: true };
45581
- return s;
45582
- });
45583
- return { ...trait, stateMachine: { ...sm, states: updatedStates } };
45584
- }
45585
- function adjustSchemaForMockData(schema, mockData) {
45586
- let changed = false;
45587
- const updatedOrbitals = schema.orbitals.map((orbital) => {
45588
- const traits2 = orbital.traits ?? [];
45589
- const updatedTraits = traits2.map((traitRef) => {
45590
- if (!isInlineTrait3(traitRef)) return traitRef;
45591
- const updated = rewriteTraitInitialState(traitRef, mockData);
45592
- if (updated !== traitRef) changed = true;
45593
- return updated;
45594
- });
45595
- return changed ? { ...orbital, traits: updatedTraits } : orbital;
45596
- });
45597
- return changed ? { ...schema, orbitals: updatedOrbitals } : schema;
45598
- }
45599
- function prepareSchemaForPreview(input) {
45600
- const parsed = typeof input === "string" ? JSON.parse(input) : input;
45601
- const mockData = buildMockData(parsed);
45602
- const schema = adjustSchemaForMockData(parsed, mockData);
45603
- return { schema, mockData };
45604
- }
45605
44760
  var xOrbitalLog = createLogger("almadar:runtime:cross-orbital");
45606
44761
  var navLog = createLogger("almadar:runtime:navigation");
45607
44762
  function normalizeChild(child) {
@@ -45835,24 +44990,10 @@ function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, onNavi
45835
44990
  pageOrbitalNames: pageOrbitalNames.join(",")
45836
44991
  });
45837
44992
  }, [pageName, allPageTraits, orbitalsByTrait, pageOrbitalNames]);
45838
- const traitConfigsByName = useMemo(() => {
45839
- const map = {};
45840
- const orbitals = schema?.orbitals;
45841
- if (!orbitals) return map;
45842
- for (const orb of orbitals) {
45843
- const traitRefs = orb.traits;
45844
- if (!traitRefs) continue;
45845
- for (const t of traitRefs) {
45846
- if (typeof t === "string") continue;
45847
- const name = t.name ?? t.ref;
45848
- const config = t.config;
45849
- if (typeof name === "string" && config !== void 0) {
45850
- map[name] = config;
45851
- }
45852
- }
45853
- }
45854
- return map;
45855
- }, [schema]);
44993
+ const traitConfigsByName = useMemo(
44994
+ () => buildResolvedTraitConfigs(schema),
44995
+ [schema]
44996
+ );
45856
44997
  const embeddedTraits = useMemo(() => {
45857
44998
  const set = collectEmbeddedTraits(schema);
45858
44999
  xOrbitalLog.info("SchemaRunner:embeddedTraits", {
@@ -46114,5 +45255,16 @@ function BrowserPlayground({
46114
45255
  }
46115
45256
  );
46116
45257
  }
45258
+ function usePerfBuffer() {
45259
+ return useSyncExternalStore(perfStore.subscribe, perfStore.getSnapshot, perfStore.getSnapshot);
45260
+ }
45261
+ var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
45262
+ pushPerfEntry({
45263
+ name: `profiler:${id}:${phase}`,
45264
+ durationMs: actualDuration,
45265
+ ts: commitTime,
45266
+ detail: { baseDuration }
45267
+ });
45268
+ };
46117
45269
 
46118
- export { BrowserPlayground, OrbPreview, PERF_NAMESPACE, adjustSchemaForMockData, buildMockData, clearPerf, clearSchemaCache, createClientEffectHandlers, perfEnd, perfStart, perfTime, prepareSchemaForPreview, profilerOnRender, usePerfBuffer, useResolvedSchema, useTraitStateMachine, wrapCallbackForEvent };
45270
+ export { BrowserPlayground, OrbPreview, clearSchemaCache, createClientEffectHandlers, profilerOnRender, usePerfBuffer, useResolvedSchema, useTraitStateMachine };