@almadar/ui 5.158.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-Bn3ePJQC.d.cts → EntityBindingContext-0Evn_LcT.d.cts} +1 -1
- package/dist/{EntityBindingContext-Bn3ePJQC.d.ts → EntityBindingContext-0Evn_LcT.d.ts} +1 -1
- package/dist/avl/index.cjs +144 -34
- package/dist/avl/index.js +145 -35
- package/dist/components/index.cjs +192 -7
- package/dist/components/index.d.cts +8 -0
- package/dist/components/index.d.ts +8 -0
- package/dist/components/index.js +193 -8
- 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 +256 -96
- package/dist/providers/index.d.cts +1 -1
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.js +257 -97
- package/dist/runtime/index.cjs +152 -39
- package/dist/runtime/index.d.cts +5 -22
- package/dist/runtime/index.d.ts +5 -22
- package/dist/runtime/index.js +154 -40
- 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.js
CHANGED
|
@@ -13,7 +13,7 @@ import { Loader2, X, Code, FileText, WrapText, Check, Copy, Lightbulb, CheckCirc
|
|
|
13
13
|
import { createPortal } from 'react-dom';
|
|
14
14
|
import { UISlotProvider, useUISlots, useTheme } from '@almadar/ui/context';
|
|
15
15
|
import { evaluateGuard, evaluateListenPayloadExpr, evaluate, createMinimalContext, executeEffects } from '@almadar/evaluator';
|
|
16
|
-
import { prepareSchemaForPreview, collectTraitRefsFromResolvedTrait, buildOrbitalsByTrait, collectEmbeddedTraits,
|
|
16
|
+
import { prepareSchemaForPreview, collectTraitRefsFromResolvedTrait, buildOrbitalsByTrait, collectEmbeddedTraits, perfStart, perfEnd, perfGauge, perfTimeAsync, wrapCallbackForEvent, pushPerfEntry } from '@almadar/runtime/ui';
|
|
17
17
|
import { Link, Outlet, useLocation } from 'react-router-dom';
|
|
18
18
|
import SyntaxHighlighter from 'react-syntax-highlighter/dist/esm/prism-light.js';
|
|
19
19
|
import dark from 'react-syntax-highlighter/dist/esm/styles/prism/vsc-dark-plus.js';
|
|
@@ -4588,7 +4588,16 @@ function isPlainObject(value) {
|
|
|
4588
4588
|
if (typeof value === "function") return false;
|
|
4589
4589
|
return true;
|
|
4590
4590
|
}
|
|
4591
|
+
function isEvaluatorResolvedData(value) {
|
|
4592
|
+
return evaluatorResolvedData.has(value);
|
|
4593
|
+
}
|
|
4594
|
+
function brandResolved(value) {
|
|
4595
|
+
if (value !== null && typeof value === "object" && !React94__default.isValidElement(value) && !(value instanceof Date)) {
|
|
4596
|
+
resolvedMarkerFree.add(value);
|
|
4597
|
+
}
|
|
4598
|
+
}
|
|
4591
4599
|
function subtreeHasMarker(value) {
|
|
4600
|
+
if (resolvedMarkerFree.has(value)) return false;
|
|
4592
4601
|
const cached = markerPresenceCache.get(value);
|
|
4593
4602
|
if (cached !== void 0) return cached;
|
|
4594
4603
|
let found = false;
|
|
@@ -4610,10 +4619,23 @@ function subtreeHasMarker(value) {
|
|
|
4610
4619
|
}
|
|
4611
4620
|
function walkValue(value, scopeTrait, entity, config, state) {
|
|
4612
4621
|
if (isRenderBindingMarker(value)) {
|
|
4613
|
-
|
|
4622
|
+
const cached = markerResolutionCache.get(value);
|
|
4623
|
+
if (cached !== void 0 && cached.entity === entity && cached.config === config && cached.state === state) {
|
|
4624
|
+
return { resolved: cached.resolved, changed: false };
|
|
4625
|
+
}
|
|
4626
|
+
const resolved = resolveMarkerExpression(value.expression, entity, config, state);
|
|
4627
|
+
markerResolutionCache.set(value, { entity, config, state, resolved });
|
|
4628
|
+
if (resolved !== null && typeof resolved === "object" && !React94__default.isValidElement(resolved) && !(resolved instanceof Date)) {
|
|
4629
|
+
resolvedMarkerFree.add(resolved);
|
|
4630
|
+
evaluatorResolvedData.add(resolved);
|
|
4631
|
+
}
|
|
4632
|
+
return { resolved, changed: true };
|
|
4614
4633
|
}
|
|
4615
4634
|
if (Array.isArray(value)) {
|
|
4616
|
-
if (!subtreeHasMarker(value))
|
|
4635
|
+
if (!subtreeHasMarker(value)) {
|
|
4636
|
+
brandResolved(value);
|
|
4637
|
+
return { resolved: value, changed: false };
|
|
4638
|
+
}
|
|
4617
4639
|
const out = [];
|
|
4618
4640
|
let changed = false;
|
|
4619
4641
|
for (const item of value) {
|
|
@@ -4628,10 +4650,14 @@ function walkValue(value, scopeTrait, entity, config, state) {
|
|
|
4628
4650
|
out.push(resolved);
|
|
4629
4651
|
if (itemChanged) changed = true;
|
|
4630
4652
|
}
|
|
4653
|
+
brandResolved(out);
|
|
4631
4654
|
return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
|
|
4632
4655
|
}
|
|
4633
4656
|
if (isPlainObject(value)) {
|
|
4634
|
-
if (!subtreeHasMarker(value))
|
|
4657
|
+
if (!subtreeHasMarker(value)) {
|
|
4658
|
+
brandResolved(value);
|
|
4659
|
+
return { resolved: value, changed: false };
|
|
4660
|
+
}
|
|
4635
4661
|
const sourceTrait = value._sourceTrait;
|
|
4636
4662
|
if (typeof sourceTrait === "string" && sourceTrait !== scopeTrait) {
|
|
4637
4663
|
return { resolved: value, changed: false };
|
|
@@ -4643,11 +4669,13 @@ function walkValue(value, scopeTrait, entity, config, state) {
|
|
|
4643
4669
|
out[key] = resolved;
|
|
4644
4670
|
if (itemChanged) changed = true;
|
|
4645
4671
|
}
|
|
4672
|
+
brandResolved(out);
|
|
4646
4673
|
return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
|
|
4647
4674
|
}
|
|
4648
4675
|
return { resolved: value, changed: false };
|
|
4649
4676
|
}
|
|
4650
4677
|
function resolveRenderBindingMarkers(props, scopeTrait, entity, config, state) {
|
|
4678
|
+
if (resolvedMarkerFree.has(props)) return props;
|
|
4651
4679
|
const out = {};
|
|
4652
4680
|
let changed = false;
|
|
4653
4681
|
for (const [key, value] of Object.entries(props)) {
|
|
@@ -4655,13 +4683,17 @@ function resolveRenderBindingMarkers(props, scopeTrait, entity, config, state) {
|
|
|
4655
4683
|
out[key] = resolved;
|
|
4656
4684
|
if (propChanged) changed = true;
|
|
4657
4685
|
}
|
|
4686
|
+
brandResolved(out);
|
|
4658
4687
|
return changed ? out : props;
|
|
4659
4688
|
}
|
|
4660
|
-
var markerPresenceCache;
|
|
4689
|
+
var markerPresenceCache, markerResolutionCache, resolvedMarkerFree, evaluatorResolvedData;
|
|
4661
4690
|
var init_resolve_render_bindings = __esm({
|
|
4662
4691
|
"lib/resolve-render-bindings.ts"() {
|
|
4663
4692
|
"use client";
|
|
4664
4693
|
markerPresenceCache = /* @__PURE__ */ new WeakMap();
|
|
4694
|
+
markerResolutionCache = /* @__PURE__ */ new WeakMap();
|
|
4695
|
+
resolvedMarkerFree = /* @__PURE__ */ new WeakSet();
|
|
4696
|
+
evaluatorResolvedData = /* @__PURE__ */ new WeakSet();
|
|
4665
4697
|
}
|
|
4666
4698
|
});
|
|
4667
4699
|
function getCurrentIconFamily() {
|
|
@@ -15266,6 +15298,19 @@ var init_molecules = __esm({
|
|
|
15266
15298
|
init_puzzleObject();
|
|
15267
15299
|
}
|
|
15268
15300
|
});
|
|
15301
|
+
var profilerOnRender;
|
|
15302
|
+
var init_perf = __esm({
|
|
15303
|
+
"lib/perf.ts"() {
|
|
15304
|
+
profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
|
|
15305
|
+
pushPerfEntry({
|
|
15306
|
+
name: `profiler:${id}:${phase}`,
|
|
15307
|
+
durationMs: actualDuration,
|
|
15308
|
+
ts: commitTime,
|
|
15309
|
+
detail: { baseDuration }
|
|
15310
|
+
});
|
|
15311
|
+
};
|
|
15312
|
+
}
|
|
15313
|
+
});
|
|
15269
15314
|
function themeBodyFont(el) {
|
|
15270
15315
|
if (typeof getComputedStyle !== "function") return "system-ui, sans-serif";
|
|
15271
15316
|
const v = getComputedStyle(el).getPropertyValue("--font-family-body").trim();
|
|
@@ -15614,6 +15659,7 @@ var init_LearningCanvas = __esm({
|
|
|
15614
15659
|
"components/learning/atoms/LearningCanvas.tsx"() {
|
|
15615
15660
|
"use client";
|
|
15616
15661
|
init_cn();
|
|
15662
|
+
init_perf();
|
|
15617
15663
|
init_useEventBus();
|
|
15618
15664
|
DASH_PATTERNS = { dashed: [6, 4], dotted: [2, 3] };
|
|
15619
15665
|
TRACE_SERIES_COLORS = ["#2563eb", "#dc2626", "#16a34a", "#f59e0b"];
|
|
@@ -15657,6 +15703,7 @@ var init_LearningCanvas = __esm({
|
|
|
15657
15703
|
return [...shapes, ...traceOut, ...readoutOut];
|
|
15658
15704
|
}, [shapes, traces, readouts, width, height]);
|
|
15659
15705
|
const draw = useCallback(() => {
|
|
15706
|
+
const _perfT = perfStart("learningcanvas:paint");
|
|
15660
15707
|
const canvas = canvasRef.current;
|
|
15661
15708
|
if (!canvas) return;
|
|
15662
15709
|
const ctx = canvas.getContext("2d");
|
|
@@ -15678,6 +15725,7 @@ var init_LearningCanvas = __esm({
|
|
|
15678
15725
|
for (const shape of derivedShapes) {
|
|
15679
15726
|
if (shape.type === "text") drawShape(ctx, shape, width, height, derivedShapes);
|
|
15680
15727
|
}
|
|
15728
|
+
perfEnd("learningcanvas:paint", _perfT);
|
|
15681
15729
|
}, [width, height, backgroundColor, derivedShapes]);
|
|
15682
15730
|
useEffect(() => {
|
|
15683
15731
|
draw();
|
|
@@ -32872,6 +32920,7 @@ var init_MathCanvas = __esm({
|
|
|
32872
32920
|
"components/learning/molecules/MathCanvas.tsx"() {
|
|
32873
32921
|
"use client";
|
|
32874
32922
|
init_useEventBus();
|
|
32923
|
+
init_perf();
|
|
32875
32924
|
init_atoms();
|
|
32876
32925
|
init_Stack();
|
|
32877
32926
|
init_LearningCanvas();
|
|
@@ -32937,6 +32986,7 @@ var init_MathCanvas = __esm({
|
|
|
32937
32986
|
};
|
|
32938
32987
|
}, [stableKeyMap, stableKeyUpMap, eventBus]);
|
|
32939
32988
|
const derivedShapes = useMemo(() => {
|
|
32989
|
+
const _perfT = perfStart("mathcanvas:derive");
|
|
32940
32990
|
const out = [];
|
|
32941
32991
|
const margin = 24;
|
|
32942
32992
|
const plotW = width - margin * 2;
|
|
@@ -33180,6 +33230,7 @@ var init_MathCanvas = __esm({
|
|
|
33180
33230
|
}
|
|
33181
33231
|
}
|
|
33182
33232
|
out.push(...shapes);
|
|
33233
|
+
perfEnd("mathcanvas:derive", _perfT);
|
|
33183
33234
|
return out;
|
|
33184
33235
|
}, [
|
|
33185
33236
|
width,
|
|
@@ -39533,7 +39584,7 @@ var init_RichBlockEditor = __esm({
|
|
|
39533
39584
|
{
|
|
39534
39585
|
variant: "bordered",
|
|
39535
39586
|
padding: "none",
|
|
39536
|
-
className: cn("flex flex-col", className),
|
|
39587
|
+
className: cn("flex flex-col text-card-foreground", className),
|
|
39537
39588
|
children: [
|
|
39538
39589
|
enableBlocks && showToolbar && !readOnly && /* @__PURE__ */ jsx(
|
|
39539
39590
|
Box,
|
|
@@ -44352,6 +44403,7 @@ var init_DetailPanel = __esm({
|
|
|
44352
44403
|
"use client";
|
|
44353
44404
|
init_atoms();
|
|
44354
44405
|
init_Box();
|
|
44406
|
+
init_Input();
|
|
44355
44407
|
init_Stack();
|
|
44356
44408
|
init_SimpleGrid();
|
|
44357
44409
|
init_Menu();
|
|
@@ -44367,6 +44419,7 @@ var init_DetailPanel = __esm({
|
|
|
44367
44419
|
ReactMarkdown2 = lazy(() => import('react-markdown'));
|
|
44368
44420
|
DetailPanel = ({
|
|
44369
44421
|
title: propTitle,
|
|
44422
|
+
onTitleCommit,
|
|
44370
44423
|
subtitle,
|
|
44371
44424
|
status,
|
|
44372
44425
|
avatar,
|
|
@@ -44388,6 +44441,7 @@ var init_DetailPanel = __esm({
|
|
|
44388
44441
|
}) => {
|
|
44389
44442
|
const eventBus = useEventBus();
|
|
44390
44443
|
const { t } = useTranslate();
|
|
44444
|
+
const [titleDraft, setTitleDraft] = React94__default.useState(null);
|
|
44391
44445
|
const isFieldDefArray = (arr) => {
|
|
44392
44446
|
if (!arr || arr.length === 0) return false;
|
|
44393
44447
|
const first = arr[0];
|
|
@@ -44608,6 +44662,50 @@ var init_DetailPanel = __esm({
|
|
|
44608
44662
|
}),
|
|
44609
44663
|
status && /* @__PURE__ */ jsx(Badge, { variant: status.variant ?? "default", children: status.label })
|
|
44610
44664
|
] });
|
|
44665
|
+
const commitTitle = () => {
|
|
44666
|
+
if (!onTitleCommit) return;
|
|
44667
|
+
const next = (titleDraft ?? "").trim();
|
|
44668
|
+
setTitleDraft(null);
|
|
44669
|
+
if (!next || next === title) return;
|
|
44670
|
+
onTitleCommit(next, normalizedData?.id !== void 0 ? String(normalizedData.id) : "");
|
|
44671
|
+
};
|
|
44672
|
+
const titleNode = onTitleCommit && titleDraft !== null ? /* @__PURE__ */ jsx(
|
|
44673
|
+
Input,
|
|
44674
|
+
{
|
|
44675
|
+
value: titleDraft,
|
|
44676
|
+
autoFocus: true,
|
|
44677
|
+
"aria-label": t("common.title"),
|
|
44678
|
+
className: "h-auto py-1 text-3xl font-bold tracking-tight",
|
|
44679
|
+
onChange: (e) => setTitleDraft(e.target.value),
|
|
44680
|
+
onBlur: commitTitle,
|
|
44681
|
+
onKeyDown: (e) => {
|
|
44682
|
+
if (e.key === "Enter") {
|
|
44683
|
+
e.preventDefault();
|
|
44684
|
+
commitTitle();
|
|
44685
|
+
} else if (e.key === "Escape") {
|
|
44686
|
+
e.preventDefault();
|
|
44687
|
+
setTitleDraft(null);
|
|
44688
|
+
}
|
|
44689
|
+
},
|
|
44690
|
+
"data-testid": "detail-title-input"
|
|
44691
|
+
}
|
|
44692
|
+
) : onTitleCommit ? /* @__PURE__ */ jsx(
|
|
44693
|
+
Box,
|
|
44694
|
+
{
|
|
44695
|
+
role: "button",
|
|
44696
|
+
tabIndex: 0,
|
|
44697
|
+
className: "cursor-text rounded px-1 -mx-1 transition-colors hover:bg-muted/40",
|
|
44698
|
+
onClick: () => setTitleDraft(title ?? ""),
|
|
44699
|
+
onKeyDown: (e) => {
|
|
44700
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
44701
|
+
e.preventDefault();
|
|
44702
|
+
setTitleDraft(title ?? "");
|
|
44703
|
+
}
|
|
44704
|
+
},
|
|
44705
|
+
"data-testid": "detail-title-editable",
|
|
44706
|
+
children: /* @__PURE__ */ jsx(Typography, { variant: "h2", weight: "bold", children: title || "Details" })
|
|
44707
|
+
}
|
|
44708
|
+
) : /* @__PURE__ */ jsx(Typography, { variant: "h2", weight: "bold", children: title || "Details" });
|
|
44611
44709
|
const content = /* @__PURE__ */ jsx(Card, { variant: "elevated", children: /* @__PURE__ */ jsxs(VStack, { gap: "md", className: "p-6", children: [
|
|
44612
44710
|
/* @__PURE__ */ jsxs(HStack, { justify: "between", align: "start", gap: "md", children: [
|
|
44613
44711
|
/* @__PURE__ */ jsxs(HStack, { align: "start", gap: "sm", className: "min-w-0", children: [
|
|
@@ -44627,7 +44725,7 @@ var init_DetailPanel = __esm({
|
|
|
44627
44725
|
avatar,
|
|
44628
44726
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "min-w-0", children: [
|
|
44629
44727
|
/* @__PURE__ */ jsxs(HStack, { align: "center", gap: "sm", wrap: true, children: [
|
|
44630
|
-
|
|
44728
|
+
titleNode,
|
|
44631
44729
|
statusBadges
|
|
44632
44730
|
] }),
|
|
44633
44731
|
subtitle && /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: subtitle })
|
|
@@ -45188,7 +45286,7 @@ var init_Form = __esm({
|
|
|
45188
45286
|
});
|
|
45189
45287
|
debug(
|
|
45190
45288
|
"forms",
|
|
45191
|
-
`Calculation triggered: ${calc.variableName} = ${value}`
|
|
45289
|
+
`Calculation triggered: ${calc.variableName} = ${String(value)}`
|
|
45192
45290
|
);
|
|
45193
45291
|
}
|
|
45194
45292
|
});
|
|
@@ -51687,6 +51785,7 @@ function isPlainConfigObject(value) {
|
|
|
51687
51785
|
return proto === Object.prototype || proto === null;
|
|
51688
51786
|
}
|
|
51689
51787
|
function subtreeHasTraitRef(value) {
|
|
51788
|
+
if (isEvaluatorResolvedData(value)) return false;
|
|
51690
51789
|
const cached = traitRefPresenceCache.get(value);
|
|
51691
51790
|
if (cached !== void 0) return cached;
|
|
51692
51791
|
let found = false;
|
|
@@ -51759,6 +51858,10 @@ function renderPatternProps(props, onDismiss, propsSchema) {
|
|
|
51759
51858
|
};
|
|
51760
51859
|
rendered[key] = /* @__PURE__ */ jsx(SlotContentRenderer, { content: childContent, onDismiss });
|
|
51761
51860
|
} else if (Array.isArray(value)) {
|
|
51861
|
+
if (!isEvaluatorResolvedData(value) && value.some((el) => isPatternConfig(el))) ; else if (!subtreeHasTraitRef(value)) {
|
|
51862
|
+
rendered[key] = value;
|
|
51863
|
+
continue;
|
|
51864
|
+
}
|
|
51762
51865
|
const isDataArray = propsSchema?.[key]?.items?.types?.includes("object") ?? false;
|
|
51763
51866
|
rendered[key] = value.map((item, i) => {
|
|
51764
51867
|
const el = item;
|
|
@@ -55785,6 +55888,7 @@ function enqueueEvent(queue, entry) {
|
|
|
55785
55888
|
}
|
|
55786
55889
|
|
|
55787
55890
|
// hooks/useTraitStateMachine.ts
|
|
55891
|
+
init_perf();
|
|
55788
55892
|
init_traitRegistry();
|
|
55789
55893
|
init_verificationRegistry();
|
|
55790
55894
|
var crossTraitLog = createLogger("almadar:ui:cross-trait");
|
|
@@ -56471,6 +56575,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
56471
56575
|
}, [eventBus]);
|
|
56472
56576
|
useEffect(() => {
|
|
56473
56577
|
const scheduler = createTickScheduler();
|
|
56578
|
+
const timedTick = (key, fn) => () => perfTimeAsync(key, fn);
|
|
56474
56579
|
const pureWriterTickKeys = /* @__PURE__ */ new Set();
|
|
56475
56580
|
for (const group of sharedGroups.values()) {
|
|
56476
56581
|
const ticksByInterval = /* @__PURE__ */ new Map();
|
|
@@ -56487,12 +56592,12 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
56487
56592
|
}
|
|
56488
56593
|
for (const entries of ticksByInterval.values()) {
|
|
56489
56594
|
const interval = entries[0].tick.interval;
|
|
56490
|
-
const onDue = () => {
|
|
56595
|
+
const onDue = timedTick(`tick:shared:${group.storeKey}@${String(interval)}`, () => {
|
|
56491
56596
|
const writers = entries.map(
|
|
56492
56597
|
({ binding, tick }) => createSharedEntityWriter(binding, tick, traitStatesRef, emitFromSharedWriter)
|
|
56493
56598
|
);
|
|
56494
56599
|
runTickFrame(group.storeKey, writers, sharedEntityStore);
|
|
56495
|
-
};
|
|
56600
|
+
});
|
|
56496
56601
|
if (interval === "frame") {
|
|
56497
56602
|
scheduler.add(0, onDue);
|
|
56498
56603
|
} else if (typeof interval === "number") {
|
|
@@ -56510,14 +56615,15 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
56510
56615
|
if (sharedKey !== void 0 && pureWriterTickKeys.has(`${binding.trait.name}::${tick.name}`)) {
|
|
56511
56616
|
continue;
|
|
56512
56617
|
}
|
|
56618
|
+
const tickKey = `tick:${binding.trait.name}::${tick.name}`;
|
|
56513
56619
|
if (tick.interval === "frame") {
|
|
56514
|
-
scheduler.add(0, () => runTickEffects(tick, binding));
|
|
56620
|
+
scheduler.add(0, timedTick(tickKey, () => runTickEffects(tick, binding)));
|
|
56515
56621
|
} else if (typeof tick.interval === "number") {
|
|
56516
|
-
scheduler.add(tick.interval, () => runTickEffects(tick, binding));
|
|
56622
|
+
scheduler.add(tick.interval, timedTick(tickKey, () => runTickEffects(tick, binding)));
|
|
56517
56623
|
} else if (isValidCronExpression(tick.interval)) {
|
|
56518
|
-
scheduler.addCron(tick.interval, () => runTickEffects(tick, binding));
|
|
56624
|
+
scheduler.addCron(tick.interval, timedTick(tickKey, () => runTickEffects(tick, binding)));
|
|
56519
56625
|
} else {
|
|
56520
|
-
scheduler.add(parseDurationString(tick.interval), () => runTickEffects(tick, binding));
|
|
56626
|
+
scheduler.add(parseDurationString(tick.interval), timedTick(tickKey, () => runTickEffects(tick, binding)));
|
|
56521
56627
|
}
|
|
56522
56628
|
}
|
|
56523
56629
|
}
|
|
@@ -56525,6 +56631,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
56525
56631
|
}, [traitBindings, runTickEffects, sharedGroups, sharedEntityStore, emitFromSharedWriter]);
|
|
56526
56632
|
const processEventQueued = useCallback(async (eventKey, payload, targetTrait, tick, sourceTrait) => {
|
|
56527
56633
|
const normalizedEvent = normalizeEventKey(eventKey);
|
|
56634
|
+
const _perfT0 = perfStart("processEvent:total");
|
|
56528
56635
|
const bindings = traitBindingsRef.current;
|
|
56529
56636
|
const currentManager = managerRef.current;
|
|
56530
56637
|
crossTraitLog.debug("processEvent:enter", () => ({
|
|
@@ -56548,6 +56655,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
56548
56655
|
entityByTrait[name] = { ...sharedEntityStore.getSnapshot(sharedKey) };
|
|
56549
56656
|
}
|
|
56550
56657
|
}
|
|
56658
|
+
const _perfT1 = perfStart("processEvent:guardMatch");
|
|
56551
56659
|
const results = currentManager.sendEvent(
|
|
56552
56660
|
normalizedEvent,
|
|
56553
56661
|
payload,
|
|
@@ -56556,6 +56664,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
56556
56664
|
void 0,
|
|
56557
56665
|
targetTrait
|
|
56558
56666
|
);
|
|
56667
|
+
perfEnd("processEvent:guardMatch", _perfT1);
|
|
56559
56668
|
crossTraitLog.debug("processEvent:results", {
|
|
56560
56669
|
event: normalizedEvent,
|
|
56561
56670
|
executedCount: results.length,
|
|
@@ -56605,6 +56714,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
56605
56714
|
transition: `${result.previousState} -> ${result.newState}`,
|
|
56606
56715
|
effects: JSON.stringify(result.effects)
|
|
56607
56716
|
}));
|
|
56717
|
+
const _perfT2 = perfStart("processEvent:executeAll");
|
|
56608
56718
|
const emittedDuringExec = await executeTransitionEffects({
|
|
56609
56719
|
binding,
|
|
56610
56720
|
// upstream gap: /runtime TransitionResult.effects is unknown[] — they are SExpr at runtime (see Almadar_UI_Gaps.md)
|
|
@@ -56616,6 +56726,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
56616
56726
|
syncOnly: false,
|
|
56617
56727
|
log: stateLog
|
|
56618
56728
|
});
|
|
56729
|
+
perfEnd("processEvent:executeAll", _perfT2);
|
|
56619
56730
|
emittedByTrait.set(traitName, emittedDuringExec);
|
|
56620
56731
|
for (const emittedKey of emittedDuringExec) {
|
|
56621
56732
|
bridgeEchoPendingRef.current.set(
|
|
@@ -56712,27 +56823,31 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
56712
56823
|
if (orbital) dispatchedOrbitals.add(orbital);
|
|
56713
56824
|
}
|
|
56714
56825
|
const relayPayload = targetTrait !== void 0 ? { ...payload ?? {}, _targetTrait: targetTrait } : payload;
|
|
56715
|
-
|
|
56716
|
-
void onEventProcessed(normalizedEvent, relayPayload, dispatchedOrbitals, tick, sourceTrait);
|
|
56717
|
-
} else {
|
|
56718
|
-
await onEventProcessed(normalizedEvent, relayPayload, dispatchedOrbitals);
|
|
56719
|
-
}
|
|
56826
|
+
void onEventProcessed(normalizedEvent, relayPayload, dispatchedOrbitals, tick, sourceTrait);
|
|
56720
56827
|
}
|
|
56828
|
+
perfEnd("processEvent:total", _perfT0);
|
|
56829
|
+
perfEnd(`event:${normalizedEvent}`, _perfT0);
|
|
56721
56830
|
}, [entities, eventBus, sharedEntityStore]);
|
|
56722
56831
|
const drainEventQueue = useCallback(async () => {
|
|
56723
56832
|
if (processingRef.current) return;
|
|
56724
56833
|
processingRef.current = true;
|
|
56834
|
+
const _perfT = perfStart("drain:pass");
|
|
56835
|
+
let _perfN = 0;
|
|
56725
56836
|
try {
|
|
56726
56837
|
while (eventQueueRef.current.length > 0) {
|
|
56727
56838
|
const entry = eventQueueRef.current.shift();
|
|
56839
|
+
_perfN++;
|
|
56728
56840
|
await processEventQueued(entry.eventKey, entry.payload, entry.targetTrait, entry.tick, entry.sourceTrait);
|
|
56729
56841
|
}
|
|
56730
56842
|
} finally {
|
|
56731
56843
|
processingRef.current = false;
|
|
56844
|
+
perfEnd("drain:pass", _perfT);
|
|
56845
|
+
perfGauge("drain:passEntries", _perfN);
|
|
56732
56846
|
}
|
|
56733
56847
|
}, [processEventQueued]);
|
|
56734
56848
|
const enqueueAndDrain = useCallback((eventKey, payload, targetTrait, tick, sourceTrait) => {
|
|
56735
56849
|
enqueueEvent(eventQueueRef.current, { eventKey, payload, targetTrait, tick, sourceTrait });
|
|
56850
|
+
perfGauge("queue:depthAtEnqueue", eventQueueRef.current.length);
|
|
56736
56851
|
void drainEventQueue();
|
|
56737
56852
|
}, [drainEventQueue]);
|
|
56738
56853
|
useCallback((eventKey, payload) => {
|
|
@@ -57031,7 +57146,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
|
|
|
57031
57146
|
[serverActiveTraits]
|
|
57032
57147
|
);
|
|
57033
57148
|
const uiSlots = useUISlots();
|
|
57034
|
-
const onEventProcessed = useCallback(
|
|
57149
|
+
const onEventProcessed = useCallback((event, payload, dispatchedOrbitals, tick, sourceTrait) => {
|
|
57035
57150
|
if (!bridge.connected || !orbitalNames?.length) return;
|
|
57036
57151
|
const targets = dispatchedOrbitals && dispatchedOrbitals.size > 0 ? orbitalNames.filter((n) => dispatchedOrbitals.has(n)) : orbitalNames;
|
|
57037
57152
|
xOrbitalLog.debug("TraitInitializer:fanout", () => ({
|
|
@@ -57045,9 +57160,10 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
|
|
|
57045
57160
|
void bridge.sendEvent(name, event, withActiveTraits(payload), tick, sourceTrait);
|
|
57046
57161
|
continue;
|
|
57047
57162
|
}
|
|
57048
|
-
|
|
57049
|
-
|
|
57050
|
-
|
|
57163
|
+
void bridge.sendEvent(name, event, withActiveTraits(payload)).then(({ effects, meta }) => {
|
|
57164
|
+
recordServerResponse(name, event, meta);
|
|
57165
|
+
applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits, activeTraitNames, onNavigateBack);
|
|
57166
|
+
});
|
|
57051
57167
|
}
|
|
57052
57168
|
}, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, onNavigateBack, embeddedTraits, activeTraitNames, withActiveTraits]);
|
|
57053
57169
|
const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, navigateBack: onNavigateBack, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams } : { navigate: onNavigate, navigateBack: onNavigateBack, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams };
|
|
@@ -57365,14 +57481,15 @@ function OrbPreview({
|
|
|
57365
57481
|
return pattern.replace(/:([A-Za-z0-9_]+)/g, (whole, key) => routeParams[key] ?? whole);
|
|
57366
57482
|
}, [currentPagePath, routeParams]);
|
|
57367
57483
|
const navStackRef = useRef(null);
|
|
57368
|
-
const handleNavigate = useCallback((path) => {
|
|
57484
|
+
const handleNavigate = useCallback((path, navState) => {
|
|
57369
57485
|
const hit = matchPathAmong(pages, path, (entry) => entry.page.path);
|
|
57370
57486
|
const match = hit?.candidate;
|
|
57371
|
-
const params = hit?.params ?? {};
|
|
57487
|
+
const params = { ...hit?.params ?? {}, ...navState ?? {} };
|
|
57372
57488
|
navLog.debug("handleNavigate", () => ({
|
|
57373
57489
|
path,
|
|
57374
57490
|
matched: match?.page.name ?? null,
|
|
57375
57491
|
params,
|
|
57492
|
+
navState: navState ? JSON.stringify(navState) : void 0,
|
|
57376
57493
|
availablePaths: pages.map((p) => p.page.path)
|
|
57377
57494
|
}));
|
|
57378
57495
|
if (match?.page.name) {
|
|
@@ -57387,9 +57504,9 @@ function OrbPreview({
|
|
|
57387
57504
|
}
|
|
57388
57505
|
}, [pages]);
|
|
57389
57506
|
const handleNavigateEffect = useCallback(
|
|
57390
|
-
(path,
|
|
57507
|
+
(path, params, crumb) => {
|
|
57391
57508
|
navStackRef.current?.beginNavigate(path, crumb);
|
|
57392
|
-
handleNavigate(path);
|
|
57509
|
+
handleNavigate(path, params);
|
|
57393
57510
|
},
|
|
57394
57511
|
[handleNavigate]
|
|
57395
57512
|
);
|
|
@@ -59706,14 +59823,7 @@ TraitCardNode.displayName = "TraitCardNode";
|
|
|
59706
59823
|
|
|
59707
59824
|
// components/avl/organisms/FlowCanvas.tsx
|
|
59708
59825
|
init_useEventBus();
|
|
59709
|
-
|
|
59710
|
-
pushPerfEntry({
|
|
59711
|
-
name: `profiler:${id}:${phase}`,
|
|
59712
|
-
durationMs: actualDuration,
|
|
59713
|
-
ts: commitTime,
|
|
59714
|
-
detail: { baseDuration }
|
|
59715
|
-
});
|
|
59716
|
-
};
|
|
59826
|
+
init_perf();
|
|
59717
59827
|
var flowCanvasLog = createLogger("almadar:ui:flow-canvas");
|
|
59718
59828
|
var NODE_TYPES = {
|
|
59719
59829
|
preview: OrbPreviewNode,
|