@almadar/ui 5.157.0 → 5.159.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{EntityBindingContext-BfZGeDfX.d.cts → EntityBindingContext-0Evn_LcT.d.cts} +7 -3
- package/dist/{EntityBindingContext-BfZGeDfX.d.ts → EntityBindingContext-0Evn_LcT.d.ts} +7 -3
- package/dist/avl/index.cjs +379 -50
- package/dist/avl/index.js +380 -51
- package/dist/components/index.cjs +394 -17
- package/dist/components/index.d.cts +48 -6
- package/dist/components/index.d.ts +48 -6
- package/dist/components/index.js +395 -18
- package/dist/context/index.cjs +134 -39
- package/dist/context/index.js +92 -1
- package/dist/hooks/index.cjs +328 -233
- package/dist/hooks/index.js +93 -2
- package/dist/lib/index.cjs +92 -0
- package/dist/lib/index.d.cts +58 -1
- package/dist/lib/index.d.ts +58 -1
- package/dist/lib/index.js +62 -1
- package/dist/locales/index.cjs +3 -0
- package/dist/locales/index.js +3 -0
- package/dist/perf-DaVdsbU0.d.cts +21 -0
- package/dist/perf-DaVdsbU0.d.ts +21 -0
- package/dist/providers/index.cjs +461 -106
- package/dist/providers/index.d.cts +1 -1
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.js +462 -107
- package/dist/runtime/index.cjs +387 -55
- package/dist/runtime/index.d.cts +15 -23
- package/dist/runtime/index.d.ts +15 -23
- package/dist/runtime/index.js +389 -56
- package/locales/ar.json +1 -0
- package/locales/en.json +1 -0
- package/locales/sl.json +1 -0
- package/package.json +5 -5
package/dist/avl/index.cjs
CHANGED
|
@@ -4664,11 +4664,54 @@ function isPlainObject(value) {
|
|
|
4664
4664
|
if (typeof value === "function") return false;
|
|
4665
4665
|
return true;
|
|
4666
4666
|
}
|
|
4667
|
+
function isEvaluatorResolvedData(value) {
|
|
4668
|
+
return evaluatorResolvedData.has(value);
|
|
4669
|
+
}
|
|
4670
|
+
function brandResolved(value) {
|
|
4671
|
+
if (value !== null && typeof value === "object" && !React94__namespace.default.isValidElement(value) && !(value instanceof Date)) {
|
|
4672
|
+
resolvedMarkerFree.add(value);
|
|
4673
|
+
}
|
|
4674
|
+
}
|
|
4675
|
+
function subtreeHasMarker(value) {
|
|
4676
|
+
if (resolvedMarkerFree.has(value)) return false;
|
|
4677
|
+
const cached = markerPresenceCache.get(value);
|
|
4678
|
+
if (cached !== void 0) return cached;
|
|
4679
|
+
let found = false;
|
|
4680
|
+
const children = Array.isArray(value) ? value : Object.values(value);
|
|
4681
|
+
for (const child of children) {
|
|
4682
|
+
if (core.isRenderBindingMarker(child)) {
|
|
4683
|
+
found = true;
|
|
4684
|
+
break;
|
|
4685
|
+
}
|
|
4686
|
+
if (Array.isArray(child) || isPlainObject(child)) {
|
|
4687
|
+
if (subtreeHasMarker(child)) {
|
|
4688
|
+
found = true;
|
|
4689
|
+
break;
|
|
4690
|
+
}
|
|
4691
|
+
}
|
|
4692
|
+
}
|
|
4693
|
+
markerPresenceCache.set(value, found);
|
|
4694
|
+
return found;
|
|
4695
|
+
}
|
|
4667
4696
|
function walkValue(value, scopeTrait, entity, config, state) {
|
|
4668
4697
|
if (core.isRenderBindingMarker(value)) {
|
|
4669
|
-
|
|
4698
|
+
const cached = markerResolutionCache.get(value);
|
|
4699
|
+
if (cached !== void 0 && cached.entity === entity && cached.config === config && cached.state === state) {
|
|
4700
|
+
return { resolved: cached.resolved, changed: false };
|
|
4701
|
+
}
|
|
4702
|
+
const resolved = resolveMarkerExpression(value.expression, entity, config, state);
|
|
4703
|
+
markerResolutionCache.set(value, { entity, config, state, resolved });
|
|
4704
|
+
if (resolved !== null && typeof resolved === "object" && !React94__namespace.default.isValidElement(resolved) && !(resolved instanceof Date)) {
|
|
4705
|
+
resolvedMarkerFree.add(resolved);
|
|
4706
|
+
evaluatorResolvedData.add(resolved);
|
|
4707
|
+
}
|
|
4708
|
+
return { resolved, changed: true };
|
|
4670
4709
|
}
|
|
4671
4710
|
if (Array.isArray(value)) {
|
|
4711
|
+
if (!subtreeHasMarker(value)) {
|
|
4712
|
+
brandResolved(value);
|
|
4713
|
+
return { resolved: value, changed: false };
|
|
4714
|
+
}
|
|
4672
4715
|
const out = [];
|
|
4673
4716
|
let changed = false;
|
|
4674
4717
|
for (const item of value) {
|
|
@@ -4683,9 +4726,14 @@ function walkValue(value, scopeTrait, entity, config, state) {
|
|
|
4683
4726
|
out.push(resolved);
|
|
4684
4727
|
if (itemChanged) changed = true;
|
|
4685
4728
|
}
|
|
4729
|
+
brandResolved(out);
|
|
4686
4730
|
return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
|
|
4687
4731
|
}
|
|
4688
4732
|
if (isPlainObject(value)) {
|
|
4733
|
+
if (!subtreeHasMarker(value)) {
|
|
4734
|
+
brandResolved(value);
|
|
4735
|
+
return { resolved: value, changed: false };
|
|
4736
|
+
}
|
|
4689
4737
|
const sourceTrait = value._sourceTrait;
|
|
4690
4738
|
if (typeof sourceTrait === "string" && sourceTrait !== scopeTrait) {
|
|
4691
4739
|
return { resolved: value, changed: false };
|
|
@@ -4697,11 +4745,13 @@ function walkValue(value, scopeTrait, entity, config, state) {
|
|
|
4697
4745
|
out[key] = resolved;
|
|
4698
4746
|
if (itemChanged) changed = true;
|
|
4699
4747
|
}
|
|
4748
|
+
brandResolved(out);
|
|
4700
4749
|
return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
|
|
4701
4750
|
}
|
|
4702
4751
|
return { resolved: value, changed: false };
|
|
4703
4752
|
}
|
|
4704
4753
|
function resolveRenderBindingMarkers(props, scopeTrait, entity, config, state) {
|
|
4754
|
+
if (resolvedMarkerFree.has(props)) return props;
|
|
4705
4755
|
const out = {};
|
|
4706
4756
|
let changed = false;
|
|
4707
4757
|
for (const [key, value] of Object.entries(props)) {
|
|
@@ -4709,11 +4759,17 @@ function resolveRenderBindingMarkers(props, scopeTrait, entity, config, state) {
|
|
|
4709
4759
|
out[key] = resolved;
|
|
4710
4760
|
if (propChanged) changed = true;
|
|
4711
4761
|
}
|
|
4762
|
+
brandResolved(out);
|
|
4712
4763
|
return changed ? out : props;
|
|
4713
4764
|
}
|
|
4765
|
+
var markerPresenceCache, markerResolutionCache, resolvedMarkerFree, evaluatorResolvedData;
|
|
4714
4766
|
var init_resolve_render_bindings = __esm({
|
|
4715
4767
|
"lib/resolve-render-bindings.ts"() {
|
|
4716
4768
|
"use client";
|
|
4769
|
+
markerPresenceCache = /* @__PURE__ */ new WeakMap();
|
|
4770
|
+
markerResolutionCache = /* @__PURE__ */ new WeakMap();
|
|
4771
|
+
resolvedMarkerFree = /* @__PURE__ */ new WeakSet();
|
|
4772
|
+
evaluatorResolvedData = /* @__PURE__ */ new WeakSet();
|
|
4717
4773
|
}
|
|
4718
4774
|
});
|
|
4719
4775
|
function getCurrentIconFamily() {
|
|
@@ -15318,6 +15374,19 @@ var init_molecules = __esm({
|
|
|
15318
15374
|
init_puzzleObject();
|
|
15319
15375
|
}
|
|
15320
15376
|
});
|
|
15377
|
+
var profilerOnRender;
|
|
15378
|
+
var init_perf = __esm({
|
|
15379
|
+
"lib/perf.ts"() {
|
|
15380
|
+
profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
|
|
15381
|
+
ui.pushPerfEntry({
|
|
15382
|
+
name: `profiler:${id}:${phase}`,
|
|
15383
|
+
durationMs: actualDuration,
|
|
15384
|
+
ts: commitTime,
|
|
15385
|
+
detail: { baseDuration }
|
|
15386
|
+
});
|
|
15387
|
+
};
|
|
15388
|
+
}
|
|
15389
|
+
});
|
|
15321
15390
|
function themeBodyFont(el) {
|
|
15322
15391
|
if (typeof getComputedStyle !== "function") return "system-ui, sans-serif";
|
|
15323
15392
|
const v = getComputedStyle(el).getPropertyValue("--font-family-body").trim();
|
|
@@ -15666,6 +15735,7 @@ var init_LearningCanvas = __esm({
|
|
|
15666
15735
|
"components/learning/atoms/LearningCanvas.tsx"() {
|
|
15667
15736
|
"use client";
|
|
15668
15737
|
init_cn();
|
|
15738
|
+
init_perf();
|
|
15669
15739
|
init_useEventBus();
|
|
15670
15740
|
DASH_PATTERNS = { dashed: [6, 4], dotted: [2, 3] };
|
|
15671
15741
|
TRACE_SERIES_COLORS = ["#2563eb", "#dc2626", "#16a34a", "#f59e0b"];
|
|
@@ -15709,6 +15779,7 @@ var init_LearningCanvas = __esm({
|
|
|
15709
15779
|
return [...shapes, ...traceOut, ...readoutOut];
|
|
15710
15780
|
}, [shapes, traces, readouts, width, height]);
|
|
15711
15781
|
const draw = React94.useCallback(() => {
|
|
15782
|
+
const _perfT = ui.perfStart("learningcanvas:paint");
|
|
15712
15783
|
const canvas = canvasRef.current;
|
|
15713
15784
|
if (!canvas) return;
|
|
15714
15785
|
const ctx = canvas.getContext("2d");
|
|
@@ -15730,6 +15801,7 @@ var init_LearningCanvas = __esm({
|
|
|
15730
15801
|
for (const shape of derivedShapes) {
|
|
15731
15802
|
if (shape.type === "text") drawShape(ctx, shape, width, height, derivedShapes);
|
|
15732
15803
|
}
|
|
15804
|
+
ui.perfEnd("learningcanvas:paint", _perfT);
|
|
15733
15805
|
}, [width, height, backgroundColor, derivedShapes]);
|
|
15734
15806
|
React94.useEffect(() => {
|
|
15735
15807
|
draw();
|
|
@@ -29707,7 +29779,7 @@ function fileIcon(name) {
|
|
|
29707
29779
|
return "file";
|
|
29708
29780
|
}
|
|
29709
29781
|
}
|
|
29710
|
-
var TreeNodeItem, FileTree;
|
|
29782
|
+
var TreeNodeItem, FlatTreeNodeItem, FileTree;
|
|
29711
29783
|
var init_FileTree = __esm({
|
|
29712
29784
|
"components/core/molecules/FileTree.tsx"() {
|
|
29713
29785
|
"use client";
|
|
@@ -29792,14 +29864,101 @@ var init_FileTree = __esm({
|
|
|
29792
29864
|
)) })
|
|
29793
29865
|
] });
|
|
29794
29866
|
};
|
|
29867
|
+
FlatTreeNodeItem = ({
|
|
29868
|
+
item,
|
|
29869
|
+
depth,
|
|
29870
|
+
indent,
|
|
29871
|
+
childrenByParent,
|
|
29872
|
+
onNodeSelect,
|
|
29873
|
+
defaultExpanded = false
|
|
29874
|
+
}) => {
|
|
29875
|
+
const [expanded, setExpanded] = React94.useState(defaultExpanded || depth < 1);
|
|
29876
|
+
const children = childrenByParent.get(item.id);
|
|
29877
|
+
const hasChildren = !!children && children.length > 0;
|
|
29878
|
+
const handleClick = React94.useCallback(() => {
|
|
29879
|
+
if (hasChildren) setExpanded((prev) => !prev);
|
|
29880
|
+
onNodeSelect?.(item.id);
|
|
29881
|
+
}, [hasChildren, item.id, onNodeSelect]);
|
|
29882
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
29883
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
29884
|
+
Box,
|
|
29885
|
+
{
|
|
29886
|
+
className: "flex items-center gap-1.5 py-0.5 px-2 cursor-pointer rounded-sm transition-colors hover:bg-muted",
|
|
29887
|
+
style: { paddingLeft: depth * indent + 8 },
|
|
29888
|
+
onClick: handleClick,
|
|
29889
|
+
role: "treeitem",
|
|
29890
|
+
"aria-expanded": hasChildren ? expanded : void 0,
|
|
29891
|
+
children: [
|
|
29892
|
+
hasChildren ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
29893
|
+
Icon,
|
|
29894
|
+
{
|
|
29895
|
+
name: expanded ? "chevron-down" : "chevron-right",
|
|
29896
|
+
size: "xs",
|
|
29897
|
+
className: "text-[var(--color-muted-foreground)] flex-shrink-0"
|
|
29898
|
+
}
|
|
29899
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(Box, { style: { width: 12, flexShrink: 0 } }),
|
|
29900
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29901
|
+
Icon,
|
|
29902
|
+
{
|
|
29903
|
+
name: item.icon ?? (hasChildren ? expanded ? "folder-open" : "folder" : "file"),
|
|
29904
|
+
size: "xs",
|
|
29905
|
+
className: hasChildren ? "text-[var(--color-warning)]" : "text-[var(--color-muted-foreground)]"
|
|
29906
|
+
}
|
|
29907
|
+
),
|
|
29908
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "truncate font-mono text-xs", children: item.label })
|
|
29909
|
+
]
|
|
29910
|
+
}
|
|
29911
|
+
),
|
|
29912
|
+
hasChildren && expanded && /* @__PURE__ */ jsxRuntime.jsx(Box, { role: "group", children: children.map((child) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
29913
|
+
FlatTreeNodeItem,
|
|
29914
|
+
{
|
|
29915
|
+
item: child,
|
|
29916
|
+
depth: depth + 1,
|
|
29917
|
+
indent,
|
|
29918
|
+
childrenByParent,
|
|
29919
|
+
onNodeSelect
|
|
29920
|
+
},
|
|
29921
|
+
child.id
|
|
29922
|
+
)) })
|
|
29923
|
+
] });
|
|
29924
|
+
};
|
|
29795
29925
|
FileTree = ({
|
|
29796
29926
|
tree,
|
|
29927
|
+
items,
|
|
29797
29928
|
selectedPath,
|
|
29798
29929
|
onFileSelect,
|
|
29930
|
+
onNodeSelect,
|
|
29799
29931
|
className,
|
|
29800
29932
|
indent = 16
|
|
29801
29933
|
}) => {
|
|
29802
|
-
if (
|
|
29934
|
+
if (items) {
|
|
29935
|
+
if (items.length === 0) return null;
|
|
29936
|
+
const ids = new Set(items.map((node) => node.id));
|
|
29937
|
+
const childrenByParent = /* @__PURE__ */ new Map();
|
|
29938
|
+
const roots = [];
|
|
29939
|
+
for (const item of items) {
|
|
29940
|
+
if (item.parentId && ids.has(item.parentId)) {
|
|
29941
|
+
const siblings = childrenByParent.get(item.parentId);
|
|
29942
|
+
if (siblings) siblings.push(item);
|
|
29943
|
+
else childrenByParent.set(item.parentId, [item]);
|
|
29944
|
+
} else {
|
|
29945
|
+
roots.push(item);
|
|
29946
|
+
}
|
|
29947
|
+
}
|
|
29948
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: `py-1 overflow-y-auto ${className ?? ""}`, role: "tree", children: roots.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
29949
|
+
FlatTreeNodeItem,
|
|
29950
|
+
{
|
|
29951
|
+
item,
|
|
29952
|
+
depth: 0,
|
|
29953
|
+
indent,
|
|
29954
|
+
childrenByParent,
|
|
29955
|
+
onNodeSelect,
|
|
29956
|
+
defaultExpanded: true
|
|
29957
|
+
},
|
|
29958
|
+
item.id
|
|
29959
|
+
)) });
|
|
29960
|
+
}
|
|
29961
|
+
if (!tree || tree.length === 0) return null;
|
|
29803
29962
|
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: `py-1 overflow-y-auto ${className ?? ""}`, role: "tree", children: tree.map((node) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
29804
29963
|
TreeNodeItem,
|
|
29805
29964
|
{
|
|
@@ -31194,7 +31353,7 @@ var init_debug = __esm({
|
|
|
31194
31353
|
logger.createLogger("almadar:ui:debug:game-state");
|
|
31195
31354
|
}
|
|
31196
31355
|
});
|
|
31197
|
-
var isRelationsDebugEnabled, RelationSelect;
|
|
31356
|
+
var isRelationsDebugEnabled, MANY_CARDINALITIES, RelationSelect;
|
|
31198
31357
|
var init_RelationSelect = __esm({
|
|
31199
31358
|
"components/core/molecules/RelationSelect.tsx"() {
|
|
31200
31359
|
"use client";
|
|
@@ -31208,6 +31367,11 @@ var init_RelationSelect = __esm({
|
|
|
31208
31367
|
init_Typography();
|
|
31209
31368
|
init_debug();
|
|
31210
31369
|
isRelationsDebugEnabled = () => isDebugEnabled();
|
|
31370
|
+
MANY_CARDINALITIES = [
|
|
31371
|
+
"many",
|
|
31372
|
+
"one-to-many",
|
|
31373
|
+
"many-to-many"
|
|
31374
|
+
];
|
|
31211
31375
|
RelationSelect = ({
|
|
31212
31376
|
value,
|
|
31213
31377
|
onChange,
|
|
@@ -32832,6 +32996,7 @@ var init_MathCanvas = __esm({
|
|
|
32832
32996
|
"components/learning/molecules/MathCanvas.tsx"() {
|
|
32833
32997
|
"use client";
|
|
32834
32998
|
init_useEventBus();
|
|
32999
|
+
init_perf();
|
|
32835
33000
|
init_atoms();
|
|
32836
33001
|
init_Stack();
|
|
32837
33002
|
init_LearningCanvas();
|
|
@@ -32872,17 +33037,21 @@ var init_MathCanvas = __esm({
|
|
|
32872
33037
|
error
|
|
32873
33038
|
}) => {
|
|
32874
33039
|
const eventBus = useEventBus();
|
|
33040
|
+
const keyMapKey = keyMap ? JSON.stringify(keyMap) : null;
|
|
33041
|
+
const keyUpMapKey = keyUpMap ? JSON.stringify(keyUpMap) : null;
|
|
33042
|
+
const stableKeyMap = React94.useMemo(() => keyMap, [keyMapKey]);
|
|
33043
|
+
const stableKeyUpMap = React94.useMemo(() => keyUpMap, [keyUpMapKey]);
|
|
32875
33044
|
React94.useEffect(() => {
|
|
32876
|
-
if (!
|
|
33045
|
+
if (!stableKeyMap && !stableKeyUpMap) return;
|
|
32877
33046
|
const onDown = (e) => {
|
|
32878
|
-
const ev =
|
|
33047
|
+
const ev = stableKeyMap?.[e.code];
|
|
32879
33048
|
if (ev) {
|
|
32880
33049
|
eventBus.emit(`UI:${ev}`, {});
|
|
32881
33050
|
e.preventDefault();
|
|
32882
33051
|
}
|
|
32883
33052
|
};
|
|
32884
33053
|
const onUp = (e) => {
|
|
32885
|
-
const ev =
|
|
33054
|
+
const ev = stableKeyUpMap?.[e.code];
|
|
32886
33055
|
if (ev) eventBus.emit(`UI:${ev}`, {});
|
|
32887
33056
|
};
|
|
32888
33057
|
window.addEventListener("keydown", onDown);
|
|
@@ -32891,8 +33060,9 @@ var init_MathCanvas = __esm({
|
|
|
32891
33060
|
window.removeEventListener("keydown", onDown);
|
|
32892
33061
|
window.removeEventListener("keyup", onUp);
|
|
32893
33062
|
};
|
|
32894
|
-
}, [
|
|
33063
|
+
}, [stableKeyMap, stableKeyUpMap, eventBus]);
|
|
32895
33064
|
const derivedShapes = React94.useMemo(() => {
|
|
33065
|
+
const _perfT = ui.perfStart("mathcanvas:derive");
|
|
32896
33066
|
const out = [];
|
|
32897
33067
|
const margin = 24;
|
|
32898
33068
|
const plotW = width - margin * 2;
|
|
@@ -33136,6 +33306,7 @@ var init_MathCanvas = __esm({
|
|
|
33136
33306
|
}
|
|
33137
33307
|
}
|
|
33138
33308
|
out.push(...shapes);
|
|
33309
|
+
ui.perfEnd("mathcanvas:derive", _perfT);
|
|
33139
33310
|
return out;
|
|
33140
33311
|
}, [
|
|
33141
33312
|
width,
|
|
@@ -39489,7 +39660,7 @@ var init_RichBlockEditor = __esm({
|
|
|
39489
39660
|
{
|
|
39490
39661
|
variant: "bordered",
|
|
39491
39662
|
padding: "none",
|
|
39492
|
-
className: cn("flex flex-col", className),
|
|
39663
|
+
className: cn("flex flex-col text-card-foreground", className),
|
|
39493
39664
|
children: [
|
|
39494
39665
|
enableBlocks && showToolbar && !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
39495
39666
|
Box,
|
|
@@ -44308,6 +44479,7 @@ var init_DetailPanel = __esm({
|
|
|
44308
44479
|
"use client";
|
|
44309
44480
|
init_atoms();
|
|
44310
44481
|
init_Box();
|
|
44482
|
+
init_Input();
|
|
44311
44483
|
init_Stack();
|
|
44312
44484
|
init_SimpleGrid();
|
|
44313
44485
|
init_Menu();
|
|
@@ -44323,6 +44495,7 @@ var init_DetailPanel = __esm({
|
|
|
44323
44495
|
ReactMarkdown2 = React94.lazy(() => import('react-markdown'));
|
|
44324
44496
|
DetailPanel = ({
|
|
44325
44497
|
title: propTitle,
|
|
44498
|
+
onTitleCommit,
|
|
44326
44499
|
subtitle,
|
|
44327
44500
|
status,
|
|
44328
44501
|
avatar,
|
|
@@ -44344,6 +44517,7 @@ var init_DetailPanel = __esm({
|
|
|
44344
44517
|
}) => {
|
|
44345
44518
|
const eventBus = useEventBus();
|
|
44346
44519
|
const { t } = hooks.useTranslate();
|
|
44520
|
+
const [titleDraft, setTitleDraft] = React94__namespace.default.useState(null);
|
|
44347
44521
|
const isFieldDefArray = (arr) => {
|
|
44348
44522
|
if (!arr || arr.length === 0) return false;
|
|
44349
44523
|
const first = arr[0];
|
|
@@ -44564,6 +44738,50 @@ var init_DetailPanel = __esm({
|
|
|
44564
44738
|
}),
|
|
44565
44739
|
status && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: status.variant ?? "default", children: status.label })
|
|
44566
44740
|
] });
|
|
44741
|
+
const commitTitle = () => {
|
|
44742
|
+
if (!onTitleCommit) return;
|
|
44743
|
+
const next = (titleDraft ?? "").trim();
|
|
44744
|
+
setTitleDraft(null);
|
|
44745
|
+
if (!next || next === title) return;
|
|
44746
|
+
onTitleCommit(next, normalizedData?.id !== void 0 ? String(normalizedData.id) : "");
|
|
44747
|
+
};
|
|
44748
|
+
const titleNode = onTitleCommit && titleDraft !== null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
44749
|
+
Input,
|
|
44750
|
+
{
|
|
44751
|
+
value: titleDraft,
|
|
44752
|
+
autoFocus: true,
|
|
44753
|
+
"aria-label": t("common.title"),
|
|
44754
|
+
className: "h-auto py-1 text-3xl font-bold tracking-tight",
|
|
44755
|
+
onChange: (e) => setTitleDraft(e.target.value),
|
|
44756
|
+
onBlur: commitTitle,
|
|
44757
|
+
onKeyDown: (e) => {
|
|
44758
|
+
if (e.key === "Enter") {
|
|
44759
|
+
e.preventDefault();
|
|
44760
|
+
commitTitle();
|
|
44761
|
+
} else if (e.key === "Escape") {
|
|
44762
|
+
e.preventDefault();
|
|
44763
|
+
setTitleDraft(null);
|
|
44764
|
+
}
|
|
44765
|
+
},
|
|
44766
|
+
"data-testid": "detail-title-input"
|
|
44767
|
+
}
|
|
44768
|
+
) : onTitleCommit ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
44769
|
+
Box,
|
|
44770
|
+
{
|
|
44771
|
+
role: "button",
|
|
44772
|
+
tabIndex: 0,
|
|
44773
|
+
className: "cursor-text rounded px-1 -mx-1 transition-colors hover:bg-muted/40",
|
|
44774
|
+
onClick: () => setTitleDraft(title ?? ""),
|
|
44775
|
+
onKeyDown: (e) => {
|
|
44776
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
44777
|
+
e.preventDefault();
|
|
44778
|
+
setTitleDraft(title ?? "");
|
|
44779
|
+
}
|
|
44780
|
+
},
|
|
44781
|
+
"data-testid": "detail-title-editable",
|
|
44782
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h2", weight: "bold", children: title || "Details" })
|
|
44783
|
+
}
|
|
44784
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h2", weight: "bold", children: title || "Details" });
|
|
44567
44785
|
const content = /* @__PURE__ */ jsxRuntime.jsx(Card, { variant: "elevated", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "md", className: "p-6", children: [
|
|
44568
44786
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { justify: "between", align: "start", gap: "md", children: [
|
|
44569
44787
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "start", gap: "sm", className: "min-w-0", children: [
|
|
@@ -44583,7 +44801,7 @@ var init_DetailPanel = __esm({
|
|
|
44583
44801
|
avatar,
|
|
44584
44802
|
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", className: "min-w-0", children: [
|
|
44585
44803
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "center", gap: "sm", wrap: true, children: [
|
|
44586
|
-
|
|
44804
|
+
titleNode,
|
|
44587
44805
|
statusBadges
|
|
44588
44806
|
] }),
|
|
44589
44807
|
subtitle && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "secondary", children: subtitle })
|
|
@@ -44919,6 +45137,9 @@ function determineInputType(field) {
|
|
|
44919
45137
|
if (field.type === "relation" || field.relation) {
|
|
44920
45138
|
return "relation";
|
|
44921
45139
|
}
|
|
45140
|
+
if (field.type === "array") {
|
|
45141
|
+
return "array";
|
|
45142
|
+
}
|
|
44922
45143
|
if (field.type === "enum" || field.values || getEnumOptions(field).length > 0) {
|
|
44923
45144
|
return "select";
|
|
44924
45145
|
}
|
|
@@ -44994,6 +45215,7 @@ var init_Form = __esm({
|
|
|
44994
45215
|
init_Typography();
|
|
44995
45216
|
init_Icon();
|
|
44996
45217
|
init_RelationSelect();
|
|
45218
|
+
init_TagInput();
|
|
44997
45219
|
init_UploadDropZone();
|
|
44998
45220
|
init_Alert();
|
|
44999
45221
|
init_useEventBus();
|
|
@@ -45073,7 +45295,7 @@ var init_Form = __esm({
|
|
|
45073
45295
|
values: "values" in f3 ? f3.values : void 0,
|
|
45074
45296
|
min: f3.min,
|
|
45075
45297
|
max: f3.max,
|
|
45076
|
-
relation: "relation" in f3 ? { entity: f3.relation.entity } : void 0
|
|
45298
|
+
relation: "relation" in f3 ? { entity: f3.relation.entity, cardinality: f3.relation.cardinality } : void 0
|
|
45077
45299
|
})
|
|
45078
45300
|
);
|
|
45079
45301
|
}, [entity, fields]);
|
|
@@ -45140,7 +45362,7 @@ var init_Form = __esm({
|
|
|
45140
45362
|
});
|
|
45141
45363
|
debug(
|
|
45142
45364
|
"forms",
|
|
45143
|
-
`Calculation triggered: ${calc.variableName} = ${value}`
|
|
45365
|
+
`Calculation triggered: ${calc.variableName} = ${String(value)}`
|
|
45144
45366
|
);
|
|
45145
45367
|
}
|
|
45146
45368
|
});
|
|
@@ -45308,7 +45530,7 @@ var init_Form = __esm({
|
|
|
45308
45530
|
values: "values" in entityField ? entityField.values : void 0,
|
|
45309
45531
|
min: entityField.min,
|
|
45310
45532
|
max: entityField.max,
|
|
45311
|
-
relation: "relation" in entityField ? { entity: entityField.relation.entity } : void 0
|
|
45533
|
+
relation: "relation" in entityField ? { entity: entityField.relation.entity, cardinality: entityField.relation.cardinality } : void 0
|
|
45312
45534
|
};
|
|
45313
45535
|
}
|
|
45314
45536
|
return { name: field, type: "string" };
|
|
@@ -45420,6 +45642,22 @@ var init_Form = __esm({
|
|
|
45420
45642
|
case "relation": {
|
|
45421
45643
|
const relationOptions = relationsData[fieldName] || [];
|
|
45422
45644
|
const relationLoading = relationsLoading[fieldName] || false;
|
|
45645
|
+
if (field.relation?.cardinality !== void 0 && MANY_CARDINALITIES.includes(field.relation.cardinality)) {
|
|
45646
|
+
const selectedValues = Array.isArray(currentValue) ? currentValue.map((v) => String(v)) : [];
|
|
45647
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
45648
|
+
Select,
|
|
45649
|
+
{
|
|
45650
|
+
...commonProps,
|
|
45651
|
+
multiple: true,
|
|
45652
|
+
searchable: true,
|
|
45653
|
+
clearable: true,
|
|
45654
|
+
options: [...relationOptions],
|
|
45655
|
+
value: selectedValues,
|
|
45656
|
+
onValueChange: (value) => handleChange(fieldName, Array.isArray(value) ? value : [value]),
|
|
45657
|
+
placeholder: field.placeholder || `Select ${label}...`
|
|
45658
|
+
}
|
|
45659
|
+
);
|
|
45660
|
+
}
|
|
45423
45661
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
45424
45662
|
RelationSelect,
|
|
45425
45663
|
{
|
|
@@ -45434,6 +45672,18 @@ var init_Form = __esm({
|
|
|
45434
45672
|
}
|
|
45435
45673
|
);
|
|
45436
45674
|
}
|
|
45675
|
+
case "array": {
|
|
45676
|
+
const arrayValue = Array.isArray(currentValue) ? currentValue.map((v) => String(v)) : currentValue != null && currentValue !== "" ? [String(currentValue)] : [];
|
|
45677
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
45678
|
+
TagInput,
|
|
45679
|
+
{
|
|
45680
|
+
placeholder: field.placeholder,
|
|
45681
|
+
disabled: isLoading,
|
|
45682
|
+
value: arrayValue,
|
|
45683
|
+
onChange: (next) => handleChange(fieldName, [...next])
|
|
45684
|
+
}
|
|
45685
|
+
);
|
|
45686
|
+
}
|
|
45437
45687
|
case "number":
|
|
45438
45688
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
45439
45689
|
Input,
|
|
@@ -51002,7 +51252,10 @@ function enrichFormFields(fields, entityDef) {
|
|
|
51002
51252
|
enriched.values = entityField.enumValues;
|
|
51003
51253
|
}
|
|
51004
51254
|
if (entityField.relation) {
|
|
51005
|
-
enriched.relation =
|
|
51255
|
+
enriched.relation = {
|
|
51256
|
+
entity: entityField.relation.entity,
|
|
51257
|
+
cardinality: entityField.relation.cardinality
|
|
51258
|
+
};
|
|
51006
51259
|
}
|
|
51007
51260
|
return enriched;
|
|
51008
51261
|
}
|
|
@@ -51030,7 +51283,10 @@ function enrichFormFields(fields, entityDef) {
|
|
|
51030
51283
|
}
|
|
51031
51284
|
}
|
|
51032
51285
|
if (!obj.relation && entityField.relation) {
|
|
51033
|
-
enriched.relation =
|
|
51286
|
+
enriched.relation = {
|
|
51287
|
+
entity: entityField.relation.entity,
|
|
51288
|
+
cardinality: entityField.relation.cardinality
|
|
51289
|
+
};
|
|
51034
51290
|
}
|
|
51035
51291
|
return enriched;
|
|
51036
51292
|
}
|
|
@@ -51045,7 +51301,12 @@ function enrichDetailFields(fields, entityDef) {
|
|
|
51045
51301
|
const meta = { type: entityField.type };
|
|
51046
51302
|
const values = entityField.values ?? entityField.enumValues;
|
|
51047
51303
|
if (values && values.length > 0) meta.values = values;
|
|
51048
|
-
if (entityField.relation)
|
|
51304
|
+
if (entityField.relation) {
|
|
51305
|
+
meta.relation = {
|
|
51306
|
+
entity: entityField.relation.entity,
|
|
51307
|
+
cardinality: entityField.relation.cardinality
|
|
51308
|
+
};
|
|
51309
|
+
}
|
|
51049
51310
|
return meta;
|
|
51050
51311
|
};
|
|
51051
51312
|
return fields.map((field) => {
|
|
@@ -51599,6 +51860,33 @@ function isPlainConfigObject(value) {
|
|
|
51599
51860
|
const proto = Object.getPrototypeOf(value);
|
|
51600
51861
|
return proto === Object.prototype || proto === null;
|
|
51601
51862
|
}
|
|
51863
|
+
function subtreeHasTraitRef(value) {
|
|
51864
|
+
if (isEvaluatorResolvedData(value)) return false;
|
|
51865
|
+
const cached = traitRefPresenceCache.get(value);
|
|
51866
|
+
if (cached !== void 0) return cached;
|
|
51867
|
+
let found = false;
|
|
51868
|
+
const children = Array.isArray(value) ? value : Object.values(value);
|
|
51869
|
+
for (const child of children) {
|
|
51870
|
+
if (typeof child === "string" && TRAIT_BINDING_RE.test(child)) {
|
|
51871
|
+
found = true;
|
|
51872
|
+
break;
|
|
51873
|
+
}
|
|
51874
|
+
if (core.isRenderBindingMarker(child)) continue;
|
|
51875
|
+
if (Array.isArray(child)) {
|
|
51876
|
+
if (subtreeHasTraitRef(child)) {
|
|
51877
|
+
found = true;
|
|
51878
|
+
break;
|
|
51879
|
+
}
|
|
51880
|
+
} else if (child !== null && typeof child === "object" && isPlainConfigObject(child)) {
|
|
51881
|
+
if (subtreeHasTraitRef(child)) {
|
|
51882
|
+
found = true;
|
|
51883
|
+
break;
|
|
51884
|
+
}
|
|
51885
|
+
}
|
|
51886
|
+
}
|
|
51887
|
+
traitRefPresenceCache.set(value, found);
|
|
51888
|
+
return found;
|
|
51889
|
+
}
|
|
51602
51890
|
function substituteTraitRefsDeep(value, pathKey) {
|
|
51603
51891
|
if (core.isRenderBindingMarker(value)) return value;
|
|
51604
51892
|
if (typeof value === "string") {
|
|
@@ -51613,11 +51901,13 @@ function substituteTraitRefsDeep(value, pathKey) {
|
|
|
51613
51901
|
return value;
|
|
51614
51902
|
}
|
|
51615
51903
|
if (Array.isArray(value)) {
|
|
51904
|
+
if (!subtreeHasTraitRef(value)) return value;
|
|
51616
51905
|
return value.map(
|
|
51617
51906
|
(item, i) => substituteTraitRefsDeep(item, `${pathKey}[${i}]`)
|
|
51618
51907
|
);
|
|
51619
51908
|
}
|
|
51620
51909
|
if (typeof value === "object" && isPlainConfigObject(value)) {
|
|
51910
|
+
if (!subtreeHasTraitRef(value)) return value;
|
|
51621
51911
|
const out = {};
|
|
51622
51912
|
for (const [k, v] of Object.entries(value)) {
|
|
51623
51913
|
out[k] = substituteTraitRefsDeep(v, `${pathKey}.${k}`);
|
|
@@ -51644,6 +51934,10 @@ function renderPatternProps(props, onDismiss, propsSchema) {
|
|
|
51644
51934
|
};
|
|
51645
51935
|
rendered[key] = /* @__PURE__ */ jsxRuntime.jsx(SlotContentRenderer, { content: childContent, onDismiss });
|
|
51646
51936
|
} else if (Array.isArray(value)) {
|
|
51937
|
+
if (!isEvaluatorResolvedData(value) && value.some((el) => isPatternConfig(el))) ; else if (!subtreeHasTraitRef(value)) {
|
|
51938
|
+
rendered[key] = value;
|
|
51939
|
+
continue;
|
|
51940
|
+
}
|
|
51647
51941
|
const isDataArray = propsSchema?.[key]?.items?.types?.includes("object") ?? false;
|
|
51648
51942
|
rendered[key] = value.map((item, i) => {
|
|
51649
51943
|
const el = item;
|
|
@@ -51906,7 +52200,7 @@ function UISlotRenderer({
|
|
|
51906
52200
|
}
|
|
51907
52201
|
return wrapped;
|
|
51908
52202
|
}
|
|
51909
|
-
var scopeWrapLog, TRAIT_BINDING_RE, SuspenseConfigContext, SlotContainedContext, SLOT_SKELETON_MAP, SELF_OVERLAY_PATTERNS, CONTENT_NODE_SLOTS, PATTERNS_WITH_CHILDREN;
|
|
52203
|
+
var scopeWrapLog, TRAIT_BINDING_RE, SuspenseConfigContext, SlotContainedContext, SLOT_SKELETON_MAP, SELF_OVERLAY_PATTERNS, CONTENT_NODE_SLOTS, PATTERNS_WITH_CHILDREN, traitRefPresenceCache;
|
|
51910
52204
|
var init_UISlotRenderer = __esm({
|
|
51911
52205
|
"components/core/organisms/UISlotRenderer.tsx"() {
|
|
51912
52206
|
"use client";
|
|
@@ -51980,6 +52274,7 @@ var init_UISlotRenderer = __esm({
|
|
|
51980
52274
|
"alert",
|
|
51981
52275
|
"dialog"
|
|
51982
52276
|
]);
|
|
52277
|
+
traitRefPresenceCache = /* @__PURE__ */ new WeakMap();
|
|
51983
52278
|
UISlotRenderer.displayName = "UISlotRenderer";
|
|
51984
52279
|
}
|
|
51985
52280
|
});
|
|
@@ -55654,7 +55949,22 @@ function createClientEffectHandlers(options) {
|
|
|
55654
55949
|
};
|
|
55655
55950
|
}
|
|
55656
55951
|
|
|
55952
|
+
// lib/event-queue-coalesce.ts
|
|
55953
|
+
function enqueueEvent(queue, entry) {
|
|
55954
|
+
if (entry.tick !== void 0) {
|
|
55955
|
+
const pending = queue.find(
|
|
55956
|
+
(e) => e.tick !== void 0 && e.eventKey === entry.eventKey && e.targetTrait === entry.targetTrait
|
|
55957
|
+
);
|
|
55958
|
+
if (pending !== void 0) {
|
|
55959
|
+
pending.payload = entry.payload;
|
|
55960
|
+
return;
|
|
55961
|
+
}
|
|
55962
|
+
}
|
|
55963
|
+
queue.push(entry);
|
|
55964
|
+
}
|
|
55965
|
+
|
|
55657
55966
|
// hooks/useTraitStateMachine.ts
|
|
55967
|
+
init_perf();
|
|
55658
55968
|
init_traitRegistry();
|
|
55659
55969
|
init_verificationRegistry();
|
|
55660
55970
|
var crossTraitLog = logger.createLogger("almadar:ui:cross-trait");
|
|
@@ -56228,12 +56538,13 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
56228
56538
|
entityId
|
|
56229
56539
|
};
|
|
56230
56540
|
const emittedDuringExec = [];
|
|
56541
|
+
const tickName = flushEvent.startsWith("tick:") ? flushEvent.slice(5) : void 0;
|
|
56231
56542
|
const baseEmit = handlers.emit;
|
|
56232
56543
|
const trackingHandlers = {
|
|
56233
56544
|
...handlers,
|
|
56234
56545
|
emit: (event, eventPayload, source) => {
|
|
56235
56546
|
emittedDuringExec.push(event);
|
|
56236
|
-
baseEmit(event, eventPayload, source);
|
|
56547
|
+
baseEmit(event, eventPayload, tickName !== void 0 ? { ...source, tick: tickName } : source);
|
|
56237
56548
|
}
|
|
56238
56549
|
};
|
|
56239
56550
|
if (traitName === "Hero") {
|
|
@@ -56340,6 +56651,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
56340
56651
|
}, [eventBus]);
|
|
56341
56652
|
React94.useEffect(() => {
|
|
56342
56653
|
const scheduler = runtime.createTickScheduler();
|
|
56654
|
+
const timedTick = (key, fn) => () => ui.perfTimeAsync(key, fn);
|
|
56343
56655
|
const pureWriterTickKeys = /* @__PURE__ */ new Set();
|
|
56344
56656
|
for (const group of sharedGroups.values()) {
|
|
56345
56657
|
const ticksByInterval = /* @__PURE__ */ new Map();
|
|
@@ -56356,12 +56668,12 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
56356
56668
|
}
|
|
56357
56669
|
for (const entries of ticksByInterval.values()) {
|
|
56358
56670
|
const interval = entries[0].tick.interval;
|
|
56359
|
-
const onDue = () => {
|
|
56671
|
+
const onDue = timedTick(`tick:shared:${group.storeKey}@${String(interval)}`, () => {
|
|
56360
56672
|
const writers = entries.map(
|
|
56361
56673
|
({ binding, tick }) => createSharedEntityWriter(binding, tick, traitStatesRef, emitFromSharedWriter)
|
|
56362
56674
|
);
|
|
56363
56675
|
runTickFrame(group.storeKey, writers, sharedEntityStore);
|
|
56364
|
-
};
|
|
56676
|
+
});
|
|
56365
56677
|
if (interval === "frame") {
|
|
56366
56678
|
scheduler.add(0, onDue);
|
|
56367
56679
|
} else if (typeof interval === "number") {
|
|
@@ -56379,21 +56691,23 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
56379
56691
|
if (sharedKey !== void 0 && pureWriterTickKeys.has(`${binding.trait.name}::${tick.name}`)) {
|
|
56380
56692
|
continue;
|
|
56381
56693
|
}
|
|
56694
|
+
const tickKey = `tick:${binding.trait.name}::${tick.name}`;
|
|
56382
56695
|
if (tick.interval === "frame") {
|
|
56383
|
-
scheduler.add(0, () => runTickEffects(tick, binding));
|
|
56696
|
+
scheduler.add(0, timedTick(tickKey, () => runTickEffects(tick, binding)));
|
|
56384
56697
|
} else if (typeof tick.interval === "number") {
|
|
56385
|
-
scheduler.add(tick.interval, () => runTickEffects(tick, binding));
|
|
56698
|
+
scheduler.add(tick.interval, timedTick(tickKey, () => runTickEffects(tick, binding)));
|
|
56386
56699
|
} else if (runtime.isValidCronExpression(tick.interval)) {
|
|
56387
|
-
scheduler.addCron(tick.interval, () => runTickEffects(tick, binding));
|
|
56700
|
+
scheduler.addCron(tick.interval, timedTick(tickKey, () => runTickEffects(tick, binding)));
|
|
56388
56701
|
} else {
|
|
56389
|
-
scheduler.add(runtime.parseDurationString(tick.interval), () => runTickEffects(tick, binding));
|
|
56702
|
+
scheduler.add(runtime.parseDurationString(tick.interval), timedTick(tickKey, () => runTickEffects(tick, binding)));
|
|
56390
56703
|
}
|
|
56391
56704
|
}
|
|
56392
56705
|
}
|
|
56393
56706
|
return () => scheduler.stopAll();
|
|
56394
56707
|
}, [traitBindings, runTickEffects, sharedGroups, sharedEntityStore, emitFromSharedWriter]);
|
|
56395
|
-
const processEventQueued = React94.useCallback(async (eventKey, payload, targetTrait) => {
|
|
56708
|
+
const processEventQueued = React94.useCallback(async (eventKey, payload, targetTrait, tick, sourceTrait) => {
|
|
56396
56709
|
const normalizedEvent = normalizeEventKey(eventKey);
|
|
56710
|
+
const _perfT0 = ui.perfStart("processEvent:total");
|
|
56397
56711
|
const bindings = traitBindingsRef.current;
|
|
56398
56712
|
const currentManager = managerRef.current;
|
|
56399
56713
|
crossTraitLog.debug("processEvent:enter", () => ({
|
|
@@ -56417,6 +56731,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
56417
56731
|
entityByTrait[name] = { ...sharedEntityStore.getSnapshot(sharedKey) };
|
|
56418
56732
|
}
|
|
56419
56733
|
}
|
|
56734
|
+
const _perfT1 = ui.perfStart("processEvent:guardMatch");
|
|
56420
56735
|
const results = currentManager.sendEvent(
|
|
56421
56736
|
normalizedEvent,
|
|
56422
56737
|
payload,
|
|
@@ -56425,6 +56740,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
56425
56740
|
void 0,
|
|
56426
56741
|
targetTrait
|
|
56427
56742
|
);
|
|
56743
|
+
ui.perfEnd("processEvent:guardMatch", _perfT1);
|
|
56428
56744
|
crossTraitLog.debug("processEvent:results", {
|
|
56429
56745
|
event: normalizedEvent,
|
|
56430
56746
|
executedCount: results.length,
|
|
@@ -56474,6 +56790,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
56474
56790
|
transition: `${result.previousState} -> ${result.newState}`,
|
|
56475
56791
|
effects: JSON.stringify(result.effects)
|
|
56476
56792
|
}));
|
|
56793
|
+
const _perfT2 = ui.perfStart("processEvent:executeAll");
|
|
56477
56794
|
const emittedDuringExec = await executeTransitionEffects({
|
|
56478
56795
|
binding,
|
|
56479
56796
|
// upstream gap: /runtime TransitionResult.effects is unknown[] — they are SExpr at runtime (see Almadar_UI_Gaps.md)
|
|
@@ -56485,6 +56802,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
56485
56802
|
syncOnly: false,
|
|
56486
56803
|
log: stateLog
|
|
56487
56804
|
});
|
|
56805
|
+
ui.perfEnd("processEvent:executeAll", _perfT2);
|
|
56488
56806
|
emittedByTrait.set(traitName, emittedDuringExec);
|
|
56489
56807
|
for (const emittedKey of emittedDuringExec) {
|
|
56490
56808
|
bridgeEchoPendingRef.current.set(
|
|
@@ -56581,23 +56899,31 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
56581
56899
|
if (orbital) dispatchedOrbitals.add(orbital);
|
|
56582
56900
|
}
|
|
56583
56901
|
const relayPayload = targetTrait !== void 0 ? { ...payload ?? {}, _targetTrait: targetTrait } : payload;
|
|
56584
|
-
|
|
56902
|
+
void onEventProcessed(normalizedEvent, relayPayload, dispatchedOrbitals, tick, sourceTrait);
|
|
56585
56903
|
}
|
|
56904
|
+
ui.perfEnd("processEvent:total", _perfT0);
|
|
56905
|
+
ui.perfEnd(`event:${normalizedEvent}`, _perfT0);
|
|
56586
56906
|
}, [entities, eventBus, sharedEntityStore]);
|
|
56587
56907
|
const drainEventQueue = React94.useCallback(async () => {
|
|
56588
56908
|
if (processingRef.current) return;
|
|
56589
56909
|
processingRef.current = true;
|
|
56910
|
+
const _perfT = ui.perfStart("drain:pass");
|
|
56911
|
+
let _perfN = 0;
|
|
56590
56912
|
try {
|
|
56591
56913
|
while (eventQueueRef.current.length > 0) {
|
|
56592
56914
|
const entry = eventQueueRef.current.shift();
|
|
56593
|
-
|
|
56915
|
+
_perfN++;
|
|
56916
|
+
await processEventQueued(entry.eventKey, entry.payload, entry.targetTrait, entry.tick, entry.sourceTrait);
|
|
56594
56917
|
}
|
|
56595
56918
|
} finally {
|
|
56596
56919
|
processingRef.current = false;
|
|
56920
|
+
ui.perfEnd("drain:pass", _perfT);
|
|
56921
|
+
ui.perfGauge("drain:passEntries", _perfN);
|
|
56597
56922
|
}
|
|
56598
56923
|
}, [processEventQueued]);
|
|
56599
|
-
const enqueueAndDrain = React94.useCallback((eventKey, payload, targetTrait) => {
|
|
56600
|
-
eventQueueRef.current
|
|
56924
|
+
const enqueueAndDrain = React94.useCallback((eventKey, payload, targetTrait, tick, sourceTrait) => {
|
|
56925
|
+
enqueueEvent(eventQueueRef.current, { eventKey, payload, targetTrait, tick, sourceTrait });
|
|
56926
|
+
ui.perfGauge("queue:depthAtEnqueue", eventQueueRef.current.length);
|
|
56601
56927
|
void drainEventQueue();
|
|
56602
56928
|
}, [drainEventQueue]);
|
|
56603
56929
|
React94.useCallback((eventKey, payload) => {
|
|
@@ -56650,7 +56976,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
56650
56976
|
crossTraitLog.debug("self:fire-server-cascade", { traitName, busKey: selfBusKey, eventKey });
|
|
56651
56977
|
}
|
|
56652
56978
|
crossTraitLog.debug("self:fire", { traitName, busKey: selfBusKey, eventKey });
|
|
56653
|
-
enqueueAndDrain(eventKey, event.payload, traitName);
|
|
56979
|
+
enqueueAndDrain(eventKey, event.payload, traitName, event.source?.tick, event.source?.trait);
|
|
56654
56980
|
});
|
|
56655
56981
|
unsubscribes.push(() => {
|
|
56656
56982
|
crossTraitLog.debug("self:unsubscribe", { traitName, busKey: selfBusKey, eventKey });
|
|
@@ -56668,7 +56994,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
56668
56994
|
const bareKey = `UI:${eventKey}`;
|
|
56669
56995
|
const unsub = eventBus.on(bareKey, (event) => {
|
|
56670
56996
|
crossTraitLog.debug("bare-cascade:fire", { bareKey, eventKey });
|
|
56671
|
-
enqueueAndDrain(eventKey, event.payload);
|
|
56997
|
+
enqueueAndDrain(eventKey, event.payload, void 0, event.source?.tick, event.source?.trait);
|
|
56672
56998
|
});
|
|
56673
56999
|
unsubscribes.push(() => {
|
|
56674
57000
|
crossTraitLog.debug("bare-cascade:unsubscribe", { bareKey, eventKey });
|
|
@@ -56702,7 +57028,9 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
56702
57028
|
enqueueAndDrain(
|
|
56703
57029
|
listen.triggers,
|
|
56704
57030
|
core.applyListenPayloadMapping(listen.payloadMapping, event.payload, evaluator.evaluateListenPayloadExpr),
|
|
56705
|
-
binding.trait.name
|
|
57031
|
+
binding.trait.name,
|
|
57032
|
+
event.source?.tick,
|
|
57033
|
+
event.source?.trait
|
|
56706
57034
|
);
|
|
56707
57035
|
});
|
|
56708
57036
|
unsubscribes.push(() => {
|
|
@@ -56894,7 +57222,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
|
|
|
56894
57222
|
[serverActiveTraits]
|
|
56895
57223
|
);
|
|
56896
57224
|
const uiSlots = context.useUISlots();
|
|
56897
|
-
const onEventProcessed = React94.useCallback(
|
|
57225
|
+
const onEventProcessed = React94.useCallback((event, payload, dispatchedOrbitals, tick, sourceTrait) => {
|
|
56898
57226
|
if (!bridge.connected || !orbitalNames?.length) return;
|
|
56899
57227
|
const targets = dispatchedOrbitals && dispatchedOrbitals.size > 0 ? orbitalNames.filter((n) => dispatchedOrbitals.has(n)) : orbitalNames;
|
|
56900
57228
|
xOrbitalLog.debug("TraitInitializer:fanout", () => ({
|
|
@@ -56904,9 +57232,14 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
|
|
|
56904
57232
|
dispatchedOrbitalsSize: dispatchedOrbitals?.size ?? 0
|
|
56905
57233
|
}));
|
|
56906
57234
|
for (const name of targets) {
|
|
56907
|
-
|
|
56908
|
-
|
|
56909
|
-
|
|
57235
|
+
if (tick !== void 0) {
|
|
57236
|
+
void bridge.sendEvent(name, event, withActiveTraits(payload), tick, sourceTrait);
|
|
57237
|
+
continue;
|
|
57238
|
+
}
|
|
57239
|
+
void bridge.sendEvent(name, event, withActiveTraits(payload)).then(({ effects, meta }) => {
|
|
57240
|
+
recordServerResponse(name, event, meta);
|
|
57241
|
+
applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits, activeTraitNames, onNavigateBack);
|
|
57242
|
+
});
|
|
56910
57243
|
}
|
|
56911
57244
|
}, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, onNavigateBack, embeddedTraits, activeTraitNames, withActiveTraits]);
|
|
56912
57245
|
const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, navigateBack: onNavigateBack, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams } : { navigate: onNavigate, navigateBack: onNavigateBack, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams };
|
|
@@ -57224,14 +57557,15 @@ function OrbPreview({
|
|
|
57224
57557
|
return pattern.replace(/:([A-Za-z0-9_]+)/g, (whole, key) => routeParams[key] ?? whole);
|
|
57225
57558
|
}, [currentPagePath, routeParams]);
|
|
57226
57559
|
const navStackRef = React94.useRef(null);
|
|
57227
|
-
const handleNavigate = React94.useCallback((path) => {
|
|
57560
|
+
const handleNavigate = React94.useCallback((path, navState) => {
|
|
57228
57561
|
const hit = providers.matchPathAmong(pages, path, (entry) => entry.page.path);
|
|
57229
57562
|
const match = hit?.candidate;
|
|
57230
|
-
const params = hit?.params ?? {};
|
|
57563
|
+
const params = { ...hit?.params ?? {}, ...navState ?? {} };
|
|
57231
57564
|
navLog.debug("handleNavigate", () => ({
|
|
57232
57565
|
path,
|
|
57233
57566
|
matched: match?.page.name ?? null,
|
|
57234
57567
|
params,
|
|
57568
|
+
navState: navState ? JSON.stringify(navState) : void 0,
|
|
57235
57569
|
availablePaths: pages.map((p) => p.page.path)
|
|
57236
57570
|
}));
|
|
57237
57571
|
if (match?.page.name) {
|
|
@@ -57246,9 +57580,9 @@ function OrbPreview({
|
|
|
57246
57580
|
}
|
|
57247
57581
|
}, [pages]);
|
|
57248
57582
|
const handleNavigateEffect = React94.useCallback(
|
|
57249
|
-
(path,
|
|
57583
|
+
(path, params, crumb) => {
|
|
57250
57584
|
navStackRef.current?.beginNavigate(path, crumb);
|
|
57251
|
-
handleNavigate(path);
|
|
57585
|
+
handleNavigate(path, params);
|
|
57252
57586
|
},
|
|
57253
57587
|
[handleNavigate]
|
|
57254
57588
|
);
|
|
@@ -57379,11 +57713,13 @@ function BrowserPlayground({
|
|
|
57379
57713
|
unregister: async () => {
|
|
57380
57714
|
runtime.unregisterAll();
|
|
57381
57715
|
},
|
|
57382
|
-
sendEvent: async (orbitalName, event, payload) => {
|
|
57716
|
+
sendEvent: async (orbitalName, event, payload, _clientId, tick, sourceTrait) => {
|
|
57383
57717
|
await registrationReady;
|
|
57384
57718
|
return runtime.processOrbitalEvent(orbitalName, {
|
|
57385
57719
|
event,
|
|
57386
|
-
payload
|
|
57720
|
+
payload,
|
|
57721
|
+
tick,
|
|
57722
|
+
sourceTrait
|
|
57387
57723
|
// @almadar/runtime OrbitalEventResponse.clientEffects uses a wider ClientEffectTuple than
|
|
57388
57724
|
// ServerBridge's local definition — cast at this boundary (upstream fix queued).
|
|
57389
57725
|
});
|
|
@@ -59563,14 +59899,7 @@ TraitCardNode.displayName = "TraitCardNode";
|
|
|
59563
59899
|
|
|
59564
59900
|
// components/avl/organisms/FlowCanvas.tsx
|
|
59565
59901
|
init_useEventBus();
|
|
59566
|
-
|
|
59567
|
-
ui.pushPerfEntry({
|
|
59568
|
-
name: `profiler:${id}:${phase}`,
|
|
59569
|
-
durationMs: actualDuration,
|
|
59570
|
-
ts: commitTime,
|
|
59571
|
-
detail: { baseDuration }
|
|
59572
|
-
});
|
|
59573
|
-
};
|
|
59902
|
+
init_perf();
|
|
59574
59903
|
var flowCanvasLog = logger.createLogger("almadar:ui:flow-canvas");
|
|
59575
59904
|
var NODE_TYPES = {
|
|
59576
59905
|
preview: OrbPreviewNode,
|