@almadar/ui 5.158.0 → 5.160.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 +177 -54
- package/dist/avl/index.js +178 -55
- package/dist/components/index.cjs +225 -27
- package/dist/components/index.d.cts +8 -0
- package/dist/components/index.d.ts +8 -0
- package/dist/components/index.js +226 -28
- 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 +289 -116
- package/dist/providers/index.d.cts +1 -1
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.js +290 -117
- package/dist/runtime/index.cjs +185 -59
- package/dist/runtime/index.d.cts +5 -22
- package/dist/runtime/index.d.ts +5 -22
- package/dist/runtime/index.js +187 -60
- 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/runtime/index.cjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var React85 = require('react');
|
|
4
4
|
var providers = require('@almadar/ui/providers');
|
|
5
5
|
var logger = require('@almadar/logger');
|
|
6
|
+
var ui = require('@almadar/runtime/ui');
|
|
6
7
|
var runtime = require('@almadar/runtime');
|
|
7
8
|
var core = require('@almadar/core');
|
|
8
9
|
var clsx = require('clsx');
|
|
@@ -13,7 +14,6 @@ var reactDom = require('react-dom');
|
|
|
13
14
|
var hooks = require('@almadar/ui/hooks');
|
|
14
15
|
var context = require('@almadar/ui/context');
|
|
15
16
|
var evaluator = require('@almadar/evaluator');
|
|
16
|
-
var ui = require('@almadar/runtime/ui');
|
|
17
17
|
var reactRouterDom = require('react-router-dom');
|
|
18
18
|
var ELK = require('elkjs/lib/elk.bundled.js');
|
|
19
19
|
var SyntaxHighlighter = require('react-syntax-highlighter/dist/esm/prism-light.js');
|
|
@@ -867,6 +867,22 @@ var init_useTapReveal = __esm({
|
|
|
867
867
|
"hooks/useTapReveal.ts"() {
|
|
868
868
|
}
|
|
869
869
|
});
|
|
870
|
+
function usePerfBuffer() {
|
|
871
|
+
return React85.useSyncExternalStore(ui.perfStore.subscribe, ui.perfStore.getSnapshot, ui.perfStore.getSnapshot);
|
|
872
|
+
}
|
|
873
|
+
exports.profilerOnRender = void 0;
|
|
874
|
+
var init_perf = __esm({
|
|
875
|
+
"lib/perf.ts"() {
|
|
876
|
+
exports.profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
|
|
877
|
+
ui.pushPerfEntry({
|
|
878
|
+
name: `profiler:${id}:${phase}`,
|
|
879
|
+
durationMs: actualDuration,
|
|
880
|
+
ts: commitTime,
|
|
881
|
+
detail: { baseDuration }
|
|
882
|
+
});
|
|
883
|
+
};
|
|
884
|
+
}
|
|
885
|
+
});
|
|
870
886
|
function resolveMarkerExpression(expression, entity, config, state) {
|
|
871
887
|
const ctx = runtime.createContextFromBindings({
|
|
872
888
|
entity,
|
|
@@ -884,7 +900,16 @@ function isPlainObject(value) {
|
|
|
884
900
|
if (typeof value === "function") return false;
|
|
885
901
|
return true;
|
|
886
902
|
}
|
|
903
|
+
function isEvaluatorResolvedData(value) {
|
|
904
|
+
return evaluatorResolvedData.has(value);
|
|
905
|
+
}
|
|
906
|
+
function brandResolved(value) {
|
|
907
|
+
if (value !== null && typeof value === "object" && !React85__namespace.default.isValidElement(value) && !(value instanceof Date)) {
|
|
908
|
+
resolvedMarkerFree.add(value);
|
|
909
|
+
}
|
|
910
|
+
}
|
|
887
911
|
function subtreeHasMarker(value) {
|
|
912
|
+
if (resolvedMarkerFree.has(value)) return false;
|
|
888
913
|
const cached = markerPresenceCache.get(value);
|
|
889
914
|
if (cached !== void 0) return cached;
|
|
890
915
|
let found = false;
|
|
@@ -906,10 +931,23 @@ function subtreeHasMarker(value) {
|
|
|
906
931
|
}
|
|
907
932
|
function walkValue(value, scopeTrait, entity, config, state) {
|
|
908
933
|
if (core.isRenderBindingMarker(value)) {
|
|
909
|
-
|
|
934
|
+
const cached = markerResolutionCache.get(value);
|
|
935
|
+
if (cached !== void 0 && cached.entity === entity && cached.config === config && cached.state === state) {
|
|
936
|
+
return { resolved: cached.resolved, changed: false };
|
|
937
|
+
}
|
|
938
|
+
const resolved = resolveMarkerExpression(value.expression, entity, config, state);
|
|
939
|
+
markerResolutionCache.set(value, { entity, config, state, resolved });
|
|
940
|
+
if (resolved !== null && typeof resolved === "object" && !React85__namespace.default.isValidElement(resolved) && !(resolved instanceof Date)) {
|
|
941
|
+
resolvedMarkerFree.add(resolved);
|
|
942
|
+
evaluatorResolvedData.add(resolved);
|
|
943
|
+
}
|
|
944
|
+
return { resolved, changed: true };
|
|
910
945
|
}
|
|
911
946
|
if (Array.isArray(value)) {
|
|
912
|
-
if (!subtreeHasMarker(value))
|
|
947
|
+
if (!subtreeHasMarker(value)) {
|
|
948
|
+
brandResolved(value);
|
|
949
|
+
return { resolved: value, changed: false };
|
|
950
|
+
}
|
|
913
951
|
const out = [];
|
|
914
952
|
let changed = false;
|
|
915
953
|
for (const item of value) {
|
|
@@ -924,10 +962,14 @@ function walkValue(value, scopeTrait, entity, config, state) {
|
|
|
924
962
|
out.push(resolved);
|
|
925
963
|
if (itemChanged) changed = true;
|
|
926
964
|
}
|
|
965
|
+
brandResolved(out);
|
|
927
966
|
return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
|
|
928
967
|
}
|
|
929
968
|
if (isPlainObject(value)) {
|
|
930
|
-
if (!subtreeHasMarker(value))
|
|
969
|
+
if (!subtreeHasMarker(value)) {
|
|
970
|
+
brandResolved(value);
|
|
971
|
+
return { resolved: value, changed: false };
|
|
972
|
+
}
|
|
931
973
|
const sourceTrait = value._sourceTrait;
|
|
932
974
|
if (typeof sourceTrait === "string" && sourceTrait !== scopeTrait) {
|
|
933
975
|
return { resolved: value, changed: false };
|
|
@@ -939,11 +981,13 @@ function walkValue(value, scopeTrait, entity, config, state) {
|
|
|
939
981
|
out[key] = resolved;
|
|
940
982
|
if (itemChanged) changed = true;
|
|
941
983
|
}
|
|
984
|
+
brandResolved(out);
|
|
942
985
|
return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
|
|
943
986
|
}
|
|
944
987
|
return { resolved: value, changed: false };
|
|
945
988
|
}
|
|
946
989
|
function resolveRenderBindingMarkers(props, scopeTrait, entity, config, state) {
|
|
990
|
+
if (resolvedMarkerFree.has(props)) return props;
|
|
947
991
|
const out = {};
|
|
948
992
|
let changed = false;
|
|
949
993
|
for (const [key, value] of Object.entries(props)) {
|
|
@@ -951,13 +995,17 @@ function resolveRenderBindingMarkers(props, scopeTrait, entity, config, state) {
|
|
|
951
995
|
out[key] = resolved;
|
|
952
996
|
if (propChanged) changed = true;
|
|
953
997
|
}
|
|
998
|
+
brandResolved(out);
|
|
954
999
|
return changed ? out : props;
|
|
955
1000
|
}
|
|
956
|
-
var markerPresenceCache;
|
|
1001
|
+
var markerPresenceCache, markerResolutionCache, resolvedMarkerFree, evaluatorResolvedData;
|
|
957
1002
|
var init_resolve_render_bindings = __esm({
|
|
958
1003
|
"lib/resolve-render-bindings.ts"() {
|
|
959
1004
|
"use client";
|
|
960
1005
|
markerPresenceCache = /* @__PURE__ */ new WeakMap();
|
|
1006
|
+
markerResolutionCache = /* @__PURE__ */ new WeakMap();
|
|
1007
|
+
resolvedMarkerFree = /* @__PURE__ */ new WeakSet();
|
|
1008
|
+
evaluatorResolvedData = /* @__PURE__ */ new WeakSet();
|
|
961
1009
|
}
|
|
962
1010
|
});
|
|
963
1011
|
function cn(...inputs) {
|
|
@@ -12282,6 +12330,7 @@ var init_LearningCanvas = __esm({
|
|
|
12282
12330
|
"components/learning/atoms/LearningCanvas.tsx"() {
|
|
12283
12331
|
"use client";
|
|
12284
12332
|
init_cn();
|
|
12333
|
+
init_perf();
|
|
12285
12334
|
init_useEventBus();
|
|
12286
12335
|
DASH_PATTERNS = { dashed: [6, 4], dotted: [2, 3] };
|
|
12287
12336
|
TRACE_SERIES_COLORS = ["#2563eb", "#dc2626", "#16a34a", "#f59e0b"];
|
|
@@ -12325,6 +12374,7 @@ var init_LearningCanvas = __esm({
|
|
|
12325
12374
|
return [...shapes, ...traceOut, ...readoutOut];
|
|
12326
12375
|
}, [shapes, traces, readouts, width, height]);
|
|
12327
12376
|
const draw = React85.useCallback(() => {
|
|
12377
|
+
const _perfT = ui.perfStart("learningcanvas:paint");
|
|
12328
12378
|
const canvas = canvasRef.current;
|
|
12329
12379
|
if (!canvas) return;
|
|
12330
12380
|
const ctx = canvas.getContext("2d");
|
|
@@ -12346,6 +12396,7 @@ var init_LearningCanvas = __esm({
|
|
|
12346
12396
|
for (const shape of derivedShapes) {
|
|
12347
12397
|
if (shape.type === "text") drawShape(ctx, shape, width, height, derivedShapes);
|
|
12348
12398
|
}
|
|
12399
|
+
ui.perfEnd("learningcanvas:paint", _perfT);
|
|
12349
12400
|
}, [width, height, backgroundColor, derivedShapes]);
|
|
12350
12401
|
React85.useEffect(() => {
|
|
12351
12402
|
draw();
|
|
@@ -26128,8 +26179,8 @@ function DataGrid({
|
|
|
26128
26179
|
}
|
|
26129
26180
|
return /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
26130
26181
|
field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
|
|
26131
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: (field.label ?? fieldLabel2(field.name)) + ":" }),
|
|
26132
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", children: formatValue(value, field.format) })
|
|
26182
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", className: "sr-only", children: (field.label ?? fieldLabel2(field.name)) + ":" }),
|
|
26183
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "secondary", children: formatValue(value, field.format) })
|
|
26133
26184
|
] }, field.name);
|
|
26134
26185
|
}) })
|
|
26135
26186
|
] }) })
|
|
@@ -26557,7 +26608,11 @@ function DataList({
|
|
|
26557
26608
|
Box,
|
|
26558
26609
|
{
|
|
26559
26610
|
className: cn(
|
|
26560
|
-
|
|
26611
|
+
// items-start, not items-center: a multi-line row (title + meta +
|
|
26612
|
+
// progress) centred its action cluster in the vertical middle, so
|
|
26613
|
+
// the buttons floated between the meta fields instead of anchoring
|
|
26614
|
+
// to the title they act on (U-DATALIST-ACTIONS-FLOAT-MID-ROW).
|
|
26615
|
+
"group flex items-start gap-4 transition-all duration-fast",
|
|
26561
26616
|
isCompact ? "px-4 py-2" : "px-6 py-4",
|
|
26562
26617
|
"hover:bg-muted/80",
|
|
26563
26618
|
!isCard && !isCompact && "rounded-lg border border-transparent hover:border-border"
|
|
@@ -26588,11 +26643,19 @@ function DataList({
|
|
|
26588
26643
|
if (value === void 0 || value === null || value === "") return null;
|
|
26589
26644
|
return /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "items-center", children: [
|
|
26590
26645
|
field.icon && renderIconInput2(field.icon, { size: "xs", className: "text-muted-foreground" }),
|
|
26591
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
26592
|
-
|
|
26593
|
-
|
|
26594
|
-
|
|
26595
|
-
|
|
26646
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
26647
|
+
Typography,
|
|
26648
|
+
{
|
|
26649
|
+
variant: "caption",
|
|
26650
|
+
color: "secondary",
|
|
26651
|
+
className: cn(field.format !== "boolean" && "sr-only"),
|
|
26652
|
+
children: [
|
|
26653
|
+
field.label ?? fieldLabel3(field.name),
|
|
26654
|
+
":"
|
|
26655
|
+
]
|
|
26656
|
+
}
|
|
26657
|
+
),
|
|
26658
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "secondary", children: formatValue2(value, field.format, { yes: t("common.yes"), no: t("common.no") }) })
|
|
26596
26659
|
] }, field.name);
|
|
26597
26660
|
}) }),
|
|
26598
26661
|
progressFields.map((field) => {
|
|
@@ -26611,7 +26674,7 @@ function DataList({
|
|
|
26611
26674
|
]
|
|
26612
26675
|
}
|
|
26613
26676
|
),
|
|
26614
|
-
isCard && !isLast && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "
|
|
26677
|
+
(isCard || isCompact) && !isLast && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("border-b border-border/40", isCompact ? "mx-4" : "mx-6") })
|
|
26615
26678
|
] }, id)
|
|
26616
26679
|
);
|
|
26617
26680
|
};
|
|
@@ -26621,7 +26684,13 @@ function DataList({
|
|
|
26621
26684
|
{
|
|
26622
26685
|
className: cn(
|
|
26623
26686
|
isCard && "bg-card rounded-xl border border-border shadow-elevation-dialog overflow-hidden",
|
|
26624
|
-
|
|
26687
|
+
// `gap-*` is inert on a block container, and Box only emits a display
|
|
26688
|
+
// class when its `display` prop is set — so every non-card list had
|
|
26689
|
+
// been asking for a gap that CSS silently dropped. flex-col makes it
|
|
26690
|
+
// real. `compact` keeps gap-0 on purpose: it separates with the row
|
|
26691
|
+
// divider above instead, never both (Almadar_UI_Beauty.md 6).
|
|
26692
|
+
!isCard && "flex flex-col",
|
|
26693
|
+
!isCard && !isCompact && gapClass,
|
|
26625
26694
|
listLookStyles[look],
|
|
26626
26695
|
className
|
|
26627
26696
|
),
|
|
@@ -30172,6 +30241,7 @@ var init_MathCanvas = __esm({
|
|
|
30172
30241
|
"components/learning/molecules/MathCanvas.tsx"() {
|
|
30173
30242
|
"use client";
|
|
30174
30243
|
init_useEventBus();
|
|
30244
|
+
init_perf();
|
|
30175
30245
|
init_atoms();
|
|
30176
30246
|
init_Stack();
|
|
30177
30247
|
init_LearningCanvas();
|
|
@@ -30237,6 +30307,7 @@ var init_MathCanvas = __esm({
|
|
|
30237
30307
|
};
|
|
30238
30308
|
}, [stableKeyMap, stableKeyUpMap, eventBus]);
|
|
30239
30309
|
const derivedShapes = React85.useMemo(() => {
|
|
30310
|
+
const _perfT = ui.perfStart("mathcanvas:derive");
|
|
30240
30311
|
const out = [];
|
|
30241
30312
|
const margin = 24;
|
|
30242
30313
|
const plotW = width - margin * 2;
|
|
@@ -30480,6 +30551,7 @@ var init_MathCanvas = __esm({
|
|
|
30480
30551
|
}
|
|
30481
30552
|
}
|
|
30482
30553
|
out.push(...shapes);
|
|
30554
|
+
ui.perfEnd("mathcanvas:derive", _perfT);
|
|
30483
30555
|
return out;
|
|
30484
30556
|
}, [
|
|
30485
30557
|
width,
|
|
@@ -36695,7 +36767,7 @@ var init_RichBlockEditor = __esm({
|
|
|
36695
36767
|
{
|
|
36696
36768
|
variant: "bordered",
|
|
36697
36769
|
padding: "none",
|
|
36698
|
-
className: cn("flex flex-col", className),
|
|
36770
|
+
className: cn("flex flex-col text-card-foreground", className),
|
|
36699
36771
|
children: [
|
|
36700
36772
|
enableBlocks && showToolbar && !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
36701
36773
|
Box,
|
|
@@ -41923,6 +41995,7 @@ var init_DetailPanel = __esm({
|
|
|
41923
41995
|
"use client";
|
|
41924
41996
|
init_atoms();
|
|
41925
41997
|
init_Box();
|
|
41998
|
+
init_Input();
|
|
41926
41999
|
init_Stack();
|
|
41927
42000
|
init_SimpleGrid();
|
|
41928
42001
|
init_Menu();
|
|
@@ -41938,6 +42011,7 @@ var init_DetailPanel = __esm({
|
|
|
41938
42011
|
ReactMarkdown2 = React85.lazy(() => import('react-markdown'));
|
|
41939
42012
|
DetailPanel = ({
|
|
41940
42013
|
title: propTitle,
|
|
42014
|
+
onTitleCommit,
|
|
41941
42015
|
subtitle,
|
|
41942
42016
|
status,
|
|
41943
42017
|
avatar,
|
|
@@ -41959,6 +42033,7 @@ var init_DetailPanel = __esm({
|
|
|
41959
42033
|
}) => {
|
|
41960
42034
|
const eventBus = useEventBus();
|
|
41961
42035
|
const { t } = hooks.useTranslate();
|
|
42036
|
+
const [titleDraft, setTitleDraft] = React85__namespace.default.useState(null);
|
|
41962
42037
|
const isFieldDefArray = (arr) => {
|
|
41963
42038
|
if (!arr || arr.length === 0) return false;
|
|
41964
42039
|
const first = arr[0];
|
|
@@ -42179,6 +42254,50 @@ var init_DetailPanel = __esm({
|
|
|
42179
42254
|
}),
|
|
42180
42255
|
status && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: status.variant ?? "default", children: status.label })
|
|
42181
42256
|
] });
|
|
42257
|
+
const commitTitle = () => {
|
|
42258
|
+
if (!onTitleCommit) return;
|
|
42259
|
+
const next = (titleDraft ?? "").trim();
|
|
42260
|
+
setTitleDraft(null);
|
|
42261
|
+
if (!next || next === title) return;
|
|
42262
|
+
onTitleCommit(next, normalizedData?.id !== void 0 ? String(normalizedData.id) : "");
|
|
42263
|
+
};
|
|
42264
|
+
const titleNode = onTitleCommit && titleDraft !== null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
42265
|
+
Input,
|
|
42266
|
+
{
|
|
42267
|
+
value: titleDraft,
|
|
42268
|
+
autoFocus: true,
|
|
42269
|
+
"aria-label": t("common.title"),
|
|
42270
|
+
className: "h-auto py-1 text-3xl font-bold tracking-tight",
|
|
42271
|
+
onChange: (e) => setTitleDraft(e.target.value),
|
|
42272
|
+
onBlur: commitTitle,
|
|
42273
|
+
onKeyDown: (e) => {
|
|
42274
|
+
if (e.key === "Enter") {
|
|
42275
|
+
e.preventDefault();
|
|
42276
|
+
commitTitle();
|
|
42277
|
+
} else if (e.key === "Escape") {
|
|
42278
|
+
e.preventDefault();
|
|
42279
|
+
setTitleDraft(null);
|
|
42280
|
+
}
|
|
42281
|
+
},
|
|
42282
|
+
"data-testid": "detail-title-input"
|
|
42283
|
+
}
|
|
42284
|
+
) : onTitleCommit ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
42285
|
+
Box,
|
|
42286
|
+
{
|
|
42287
|
+
role: "button",
|
|
42288
|
+
tabIndex: 0,
|
|
42289
|
+
className: "cursor-text rounded px-1 -mx-1 transition-colors hover:bg-muted/40",
|
|
42290
|
+
onClick: () => setTitleDraft(title ?? ""),
|
|
42291
|
+
onKeyDown: (e) => {
|
|
42292
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
42293
|
+
e.preventDefault();
|
|
42294
|
+
setTitleDraft(title ?? "");
|
|
42295
|
+
}
|
|
42296
|
+
},
|
|
42297
|
+
"data-testid": "detail-title-editable",
|
|
42298
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h2", weight: "bold", children: title || "Details" })
|
|
42299
|
+
}
|
|
42300
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h2", weight: "bold", children: title || "Details" });
|
|
42182
42301
|
const content = /* @__PURE__ */ jsxRuntime.jsx(Card, { variant: "elevated", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "md", className: "p-6", children: [
|
|
42183
42302
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { justify: "between", align: "start", gap: "md", children: [
|
|
42184
42303
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "start", gap: "sm", className: "min-w-0", children: [
|
|
@@ -42198,7 +42317,7 @@ var init_DetailPanel = __esm({
|
|
|
42198
42317
|
avatar,
|
|
42199
42318
|
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", className: "min-w-0", children: [
|
|
42200
42319
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "center", gap: "sm", wrap: true, children: [
|
|
42201
|
-
|
|
42320
|
+
titleNode,
|
|
42202
42321
|
statusBadges
|
|
42203
42322
|
] }),
|
|
42204
42323
|
subtitle && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", color: "secondary", children: subtitle })
|
|
@@ -42298,16 +42417,11 @@ var init_DetailPanel = __esm({
|
|
|
42298
42417
|
footer
|
|
42299
42418
|
] })
|
|
42300
42419
|
] }) });
|
|
42301
|
-
|
|
42302
|
-
Box,
|
|
42303
|
-
|
|
42304
|
-
|
|
42305
|
-
|
|
42306
|
-
className
|
|
42307
|
-
),
|
|
42308
|
-
children: content
|
|
42309
|
-
}
|
|
42310
|
-
);
|
|
42420
|
+
if (!slideOver) {
|
|
42421
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className, children: content });
|
|
42422
|
+
}
|
|
42423
|
+
const panel = /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("fixed inset-y-0 right-0 w-full max-w-2xl bg-card shadow-lg z-50 overflow-y-auto p-6", className), children: content });
|
|
42424
|
+
return typeof document === "undefined" ? panel : reactDom.createPortal(panel, document.body);
|
|
42311
42425
|
};
|
|
42312
42426
|
DetailPanel.displayName = "DetailPanel";
|
|
42313
42427
|
}
|
|
@@ -42759,7 +42873,7 @@ var init_Form = __esm({
|
|
|
42759
42873
|
});
|
|
42760
42874
|
debug(
|
|
42761
42875
|
"forms",
|
|
42762
|
-
`Calculation triggered: ${calc.variableName} = ${value}`
|
|
42876
|
+
`Calculation triggered: ${calc.variableName} = ${String(value)}`
|
|
42763
42877
|
);
|
|
42764
42878
|
}
|
|
42765
42879
|
});
|
|
@@ -49258,6 +49372,7 @@ function isPlainConfigObject(value) {
|
|
|
49258
49372
|
return proto === Object.prototype || proto === null;
|
|
49259
49373
|
}
|
|
49260
49374
|
function subtreeHasTraitRef(value) {
|
|
49375
|
+
if (isEvaluatorResolvedData(value)) return false;
|
|
49261
49376
|
const cached = traitRefPresenceCache.get(value);
|
|
49262
49377
|
if (cached !== void 0) return cached;
|
|
49263
49378
|
let found = false;
|
|
@@ -49330,6 +49445,10 @@ function renderPatternProps(props, onDismiss, propsSchema) {
|
|
|
49330
49445
|
};
|
|
49331
49446
|
rendered[key] = /* @__PURE__ */ jsxRuntime.jsx(SlotContentRenderer, { content: childContent, onDismiss });
|
|
49332
49447
|
} else if (Array.isArray(value)) {
|
|
49448
|
+
if (!isEvaluatorResolvedData(value) && value.some((el) => isPatternConfig(el))) ; else if (!subtreeHasTraitRef(value)) {
|
|
49449
|
+
rendered[key] = value;
|
|
49450
|
+
continue;
|
|
49451
|
+
}
|
|
49333
49452
|
const isDataArray = propsSchema?.[key]?.items?.types?.includes("object") ?? false;
|
|
49334
49453
|
rendered[key] = value.map((item, i) => {
|
|
49335
49454
|
const el = item;
|
|
@@ -49808,6 +49927,9 @@ function enqueueEvent(queue, entry) {
|
|
|
49808
49927
|
}
|
|
49809
49928
|
queue.push(entry);
|
|
49810
49929
|
}
|
|
49930
|
+
|
|
49931
|
+
// hooks/useTraitStateMachine.ts
|
|
49932
|
+
init_perf();
|
|
49811
49933
|
var lambdaLog = logger.createLogger("almadar:ui:fn-form-lambda");
|
|
49812
49934
|
function isOperatorCall(value) {
|
|
49813
49935
|
const first = value[0];
|
|
@@ -50666,6 +50788,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
50666
50788
|
}, [eventBus]);
|
|
50667
50789
|
React85.useEffect(() => {
|
|
50668
50790
|
const scheduler = runtime.createTickScheduler();
|
|
50791
|
+
const timedTick = (key, fn) => () => ui.perfTimeAsync(key, fn);
|
|
50669
50792
|
const pureWriterTickKeys = /* @__PURE__ */ new Set();
|
|
50670
50793
|
for (const group of sharedGroups.values()) {
|
|
50671
50794
|
const ticksByInterval = /* @__PURE__ */ new Map();
|
|
@@ -50682,12 +50805,12 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
50682
50805
|
}
|
|
50683
50806
|
for (const entries of ticksByInterval.values()) {
|
|
50684
50807
|
const interval = entries[0].tick.interval;
|
|
50685
|
-
const onDue = () => {
|
|
50808
|
+
const onDue = timedTick(`tick:shared:${group.storeKey}@${String(interval)}`, () => {
|
|
50686
50809
|
const writers = entries.map(
|
|
50687
50810
|
({ binding, tick }) => createSharedEntityWriter(binding, tick, traitStatesRef, emitFromSharedWriter)
|
|
50688
50811
|
);
|
|
50689
50812
|
runTickFrame(group.storeKey, writers, sharedEntityStore);
|
|
50690
|
-
};
|
|
50813
|
+
});
|
|
50691
50814
|
if (interval === "frame") {
|
|
50692
50815
|
scheduler.add(0, onDue);
|
|
50693
50816
|
} else if (typeof interval === "number") {
|
|
@@ -50705,14 +50828,15 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
50705
50828
|
if (sharedKey !== void 0 && pureWriterTickKeys.has(`${binding.trait.name}::${tick.name}`)) {
|
|
50706
50829
|
continue;
|
|
50707
50830
|
}
|
|
50831
|
+
const tickKey = `tick:${binding.trait.name}::${tick.name}`;
|
|
50708
50832
|
if (tick.interval === "frame") {
|
|
50709
|
-
scheduler.add(0, () => runTickEffects(tick, binding));
|
|
50833
|
+
scheduler.add(0, timedTick(tickKey, () => runTickEffects(tick, binding)));
|
|
50710
50834
|
} else if (typeof tick.interval === "number") {
|
|
50711
|
-
scheduler.add(tick.interval, () => runTickEffects(tick, binding));
|
|
50835
|
+
scheduler.add(tick.interval, timedTick(tickKey, () => runTickEffects(tick, binding)));
|
|
50712
50836
|
} else if (runtime.isValidCronExpression(tick.interval)) {
|
|
50713
|
-
scheduler.addCron(tick.interval, () => runTickEffects(tick, binding));
|
|
50837
|
+
scheduler.addCron(tick.interval, timedTick(tickKey, () => runTickEffects(tick, binding)));
|
|
50714
50838
|
} else {
|
|
50715
|
-
scheduler.add(runtime.parseDurationString(tick.interval), () => runTickEffects(tick, binding));
|
|
50839
|
+
scheduler.add(runtime.parseDurationString(tick.interval), timedTick(tickKey, () => runTickEffects(tick, binding)));
|
|
50716
50840
|
}
|
|
50717
50841
|
}
|
|
50718
50842
|
}
|
|
@@ -50720,6 +50844,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
50720
50844
|
}, [traitBindings, runTickEffects, sharedGroups, sharedEntityStore, emitFromSharedWriter]);
|
|
50721
50845
|
const processEventQueued = React85.useCallback(async (eventKey, payload, targetTrait, tick, sourceTrait) => {
|
|
50722
50846
|
const normalizedEvent = normalizeEventKey(eventKey);
|
|
50847
|
+
const _perfT0 = ui.perfStart("processEvent:total");
|
|
50723
50848
|
const bindings = traitBindingsRef.current;
|
|
50724
50849
|
const currentManager = managerRef.current;
|
|
50725
50850
|
crossTraitLog.debug("processEvent:enter", () => ({
|
|
@@ -50743,6 +50868,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
50743
50868
|
entityByTrait[name] = { ...sharedEntityStore.getSnapshot(sharedKey) };
|
|
50744
50869
|
}
|
|
50745
50870
|
}
|
|
50871
|
+
const _perfT1 = ui.perfStart("processEvent:guardMatch");
|
|
50746
50872
|
const results = currentManager.sendEvent(
|
|
50747
50873
|
normalizedEvent,
|
|
50748
50874
|
payload,
|
|
@@ -50751,6 +50877,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
50751
50877
|
void 0,
|
|
50752
50878
|
targetTrait
|
|
50753
50879
|
);
|
|
50880
|
+
ui.perfEnd("processEvent:guardMatch", _perfT1);
|
|
50754
50881
|
crossTraitLog.debug("processEvent:results", {
|
|
50755
50882
|
event: normalizedEvent,
|
|
50756
50883
|
executedCount: results.length,
|
|
@@ -50800,6 +50927,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
50800
50927
|
transition: `${result.previousState} -> ${result.newState}`,
|
|
50801
50928
|
effects: JSON.stringify(result.effects)
|
|
50802
50929
|
}));
|
|
50930
|
+
const _perfT2 = ui.perfStart("processEvent:executeAll");
|
|
50803
50931
|
const emittedDuringExec = await executeTransitionEffects({
|
|
50804
50932
|
binding,
|
|
50805
50933
|
// upstream gap: /runtime TransitionResult.effects is unknown[] — they are SExpr at runtime (see Almadar_UI_Gaps.md)
|
|
@@ -50811,6 +50939,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
50811
50939
|
syncOnly: false,
|
|
50812
50940
|
log: stateLog
|
|
50813
50941
|
});
|
|
50942
|
+
ui.perfEnd("processEvent:executeAll", _perfT2);
|
|
50814
50943
|
emittedByTrait.set(traitName, emittedDuringExec);
|
|
50815
50944
|
for (const emittedKey of emittedDuringExec) {
|
|
50816
50945
|
bridgeEchoPendingRef.current.set(
|
|
@@ -50907,27 +51036,31 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
50907
51036
|
if (orbital) dispatchedOrbitals.add(orbital);
|
|
50908
51037
|
}
|
|
50909
51038
|
const relayPayload = targetTrait !== void 0 ? { ...payload ?? {}, _targetTrait: targetTrait } : payload;
|
|
50910
|
-
|
|
50911
|
-
void onEventProcessed(normalizedEvent, relayPayload, dispatchedOrbitals, tick, sourceTrait);
|
|
50912
|
-
} else {
|
|
50913
|
-
await onEventProcessed(normalizedEvent, relayPayload, dispatchedOrbitals);
|
|
50914
|
-
}
|
|
51039
|
+
void onEventProcessed(normalizedEvent, relayPayload, dispatchedOrbitals, tick, sourceTrait);
|
|
50915
51040
|
}
|
|
51041
|
+
ui.perfEnd("processEvent:total", _perfT0);
|
|
51042
|
+
ui.perfEnd(`event:${normalizedEvent}`, _perfT0);
|
|
50916
51043
|
}, [entities, eventBus, sharedEntityStore]);
|
|
50917
51044
|
const drainEventQueue = React85.useCallback(async () => {
|
|
50918
51045
|
if (processingRef.current) return;
|
|
50919
51046
|
processingRef.current = true;
|
|
51047
|
+
const _perfT = ui.perfStart("drain:pass");
|
|
51048
|
+
let _perfN = 0;
|
|
50920
51049
|
try {
|
|
50921
51050
|
while (eventQueueRef.current.length > 0) {
|
|
50922
51051
|
const entry = eventQueueRef.current.shift();
|
|
51052
|
+
_perfN++;
|
|
50923
51053
|
await processEventQueued(entry.eventKey, entry.payload, entry.targetTrait, entry.tick, entry.sourceTrait);
|
|
50924
51054
|
}
|
|
50925
51055
|
} finally {
|
|
50926
51056
|
processingRef.current = false;
|
|
51057
|
+
ui.perfEnd("drain:pass", _perfT);
|
|
51058
|
+
ui.perfGauge("drain:passEntries", _perfN);
|
|
50927
51059
|
}
|
|
50928
51060
|
}, [processEventQueued]);
|
|
50929
51061
|
const enqueueAndDrain = React85.useCallback((eventKey, payload, targetTrait, tick, sourceTrait) => {
|
|
50930
51062
|
enqueueEvent(eventQueueRef.current, { eventKey, payload, targetTrait, tick, sourceTrait });
|
|
51063
|
+
ui.perfGauge("queue:depthAtEnqueue", eventQueueRef.current.length);
|
|
50931
51064
|
void drainEventQueue();
|
|
50932
51065
|
}, [drainEventQueue]);
|
|
50933
51066
|
React85.useCallback((eventKey, payload) => {
|
|
@@ -51329,7 +51462,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
|
|
|
51329
51462
|
[serverActiveTraits]
|
|
51330
51463
|
);
|
|
51331
51464
|
const uiSlots = context.useUISlots();
|
|
51332
|
-
const onEventProcessed = React85.useCallback(
|
|
51465
|
+
const onEventProcessed = React85.useCallback((event, payload, dispatchedOrbitals, tick, sourceTrait) => {
|
|
51333
51466
|
if (!bridge.connected || !orbitalNames?.length) return;
|
|
51334
51467
|
const targets = dispatchedOrbitals && dispatchedOrbitals.size > 0 ? orbitalNames.filter((n) => dispatchedOrbitals.has(n)) : orbitalNames;
|
|
51335
51468
|
xOrbitalLog.debug("TraitInitializer:fanout", () => ({
|
|
@@ -51343,9 +51476,10 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
|
|
|
51343
51476
|
void bridge.sendEvent(name, event, withActiveTraits(payload), tick, sourceTrait);
|
|
51344
51477
|
continue;
|
|
51345
51478
|
}
|
|
51346
|
-
|
|
51347
|
-
|
|
51348
|
-
|
|
51479
|
+
void bridge.sendEvent(name, event, withActiveTraits(payload)).then(({ effects, meta }) => {
|
|
51480
|
+
recordServerResponse(name, event, meta);
|
|
51481
|
+
applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits, activeTraitNames, onNavigateBack);
|
|
51482
|
+
});
|
|
51349
51483
|
}
|
|
51350
51484
|
}, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, onNavigateBack, embeddedTraits, activeTraitNames, withActiveTraits]);
|
|
51351
51485
|
const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, navigateBack: onNavigateBack, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams } : { navigate: onNavigate, navigateBack: onNavigateBack, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams };
|
|
@@ -51663,14 +51797,15 @@ function OrbPreview({
|
|
|
51663
51797
|
return pattern.replace(/:([A-Za-z0-9_]+)/g, (whole, key) => routeParams[key] ?? whole);
|
|
51664
51798
|
}, [currentPagePath, routeParams]);
|
|
51665
51799
|
const navStackRef = React85.useRef(null);
|
|
51666
|
-
const handleNavigate = React85.useCallback((path) => {
|
|
51800
|
+
const handleNavigate = React85.useCallback((path, navState) => {
|
|
51667
51801
|
const hit = providers.matchPathAmong(pages, path, (entry) => entry.page.path);
|
|
51668
51802
|
const match = hit?.candidate;
|
|
51669
|
-
const params = hit?.params ?? {};
|
|
51803
|
+
const params = { ...hit?.params ?? {}, ...navState ?? {} };
|
|
51670
51804
|
navLog.debug("handleNavigate", () => ({
|
|
51671
51805
|
path,
|
|
51672
51806
|
matched: match?.page.name ?? null,
|
|
51673
51807
|
params,
|
|
51808
|
+
navState: navState ? JSON.stringify(navState) : void 0,
|
|
51674
51809
|
availablePaths: pages.map((p) => p.page.path)
|
|
51675
51810
|
}));
|
|
51676
51811
|
if (match?.page.name) {
|
|
@@ -51685,9 +51820,9 @@ function OrbPreview({
|
|
|
51685
51820
|
}
|
|
51686
51821
|
}, [pages]);
|
|
51687
51822
|
const handleNavigateEffect = React85.useCallback(
|
|
51688
|
-
(path,
|
|
51823
|
+
(path, params, crumb) => {
|
|
51689
51824
|
navStackRef.current?.beginNavigate(path, crumb);
|
|
51690
|
-
handleNavigate(path);
|
|
51825
|
+
handleNavigate(path, params);
|
|
51691
51826
|
},
|
|
51692
51827
|
[handleNavigate]
|
|
51693
51828
|
);
|
|
@@ -51842,17 +51977,9 @@ function BrowserPlayground({
|
|
|
51842
51977
|
}
|
|
51843
51978
|
);
|
|
51844
51979
|
}
|
|
51845
|
-
|
|
51846
|
-
|
|
51847
|
-
|
|
51848
|
-
var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
|
|
51849
|
-
ui.pushPerfEntry({
|
|
51850
|
-
name: `profiler:${id}:${phase}`,
|
|
51851
|
-
durationMs: actualDuration,
|
|
51852
|
-
ts: commitTime,
|
|
51853
|
-
detail: { baseDuration }
|
|
51854
|
-
});
|
|
51855
|
-
};
|
|
51980
|
+
|
|
51981
|
+
// runtime/index.ts
|
|
51982
|
+
init_perf();
|
|
51856
51983
|
|
|
51857
51984
|
Object.defineProperty(exports, "EntitySchemaProvider", {
|
|
51858
51985
|
enumerable: true,
|
|
@@ -51930,7 +52057,6 @@ exports.BrowserPlayground = BrowserPlayground;
|
|
|
51930
52057
|
exports.OrbPreview = OrbPreview;
|
|
51931
52058
|
exports.clearSchemaCache = clearSchemaCache;
|
|
51932
52059
|
exports.createClientEffectHandlers = createClientEffectHandlers;
|
|
51933
|
-
exports.profilerOnRender = profilerOnRender;
|
|
51934
52060
|
exports.usePerfBuffer = usePerfBuffer;
|
|
51935
52061
|
exports.useResolvedSchema = useResolvedSchema;
|
|
51936
52062
|
exports.useTraitStateMachine = useTraitStateMachine;
|
package/dist/runtime/index.d.cts
CHANGED
|
@@ -5,11 +5,11 @@ import * as _almadar_runtime from '@almadar/runtime';
|
|
|
5
5
|
import { TraitState, EffectHandlers } from '@almadar/runtime';
|
|
6
6
|
import '../useEventBus-Ckr4wqW3.cjs';
|
|
7
7
|
import { c as useUISlots } from '../UISlotContext-BlRDbHDy.cjs';
|
|
8
|
-
import {
|
|
9
|
-
export {
|
|
10
|
-
import { PerfEntry } from '@almadar/runtime/ui';
|
|
8
|
+
import { E as EntityBindingSource, S as ServerBridgeTransport } from '../EntityBindingContext-0Evn_LcT.cjs';
|
|
9
|
+
export { a as EntitySchemaContextValue, b as EntitySchemaProvider, c as EntitySchemaProviderProps, d as ServerBridgeContextValue, e as ServerBridgeProvider, f as ServerClientEffect, T as TraitContext, g as TraitContextValue, h as TraitInstance, i as TraitProvider, j as TraitProviderProps, u as useEntitySchema, k as useEntitySchemaOptional, l as useServerBridge, m as useTrait, n as useTraitContext } from '../EntityBindingContext-0Evn_LcT.cjs';
|
|
11
10
|
export { PERF_NAMESPACE, PerfEntry, PreparedPreviewSchema, adjustSchemaForMockData, buildMockData, clearPerf, perfEnd, perfStart, perfTime, prepareSchemaForPreview, wrapCallbackForEvent } from '@almadar/runtime/ui';
|
|
12
|
-
import React__default
|
|
11
|
+
import React__default from 'react';
|
|
12
|
+
export { p as profilerOnRender, u as usePerfBuffer } from '../perf-DaVdsbU0.cjs';
|
|
13
13
|
import '../event-bus-types-Bl78kokd.cjs';
|
|
14
14
|
import '../useUISlots-GNwGLlW2.cjs';
|
|
15
15
|
import '@almadar/core/patterns';
|
|
@@ -312,21 +312,4 @@ interface BrowserPlaygroundProps {
|
|
|
312
312
|
}
|
|
313
313
|
declare function BrowserPlayground({ schema, mode, initialPagePath, height, className, }: BrowserPlaygroundProps): React__default.ReactElement;
|
|
314
314
|
|
|
315
|
-
|
|
316
|
-
* @almadar/ui/runtime — perf instrumentation
|
|
317
|
-
*
|
|
318
|
-
* React-specific consumption layer on top of the renderer-agnostic perf ring
|
|
319
|
-
* now living in `@almadar/runtime/ui/perf`. Re-exports the framework-free
|
|
320
|
-
* timing primitives and adds `useSyncExternalStore` / `React.Profiler` hooks.
|
|
321
|
-
*/
|
|
322
|
-
|
|
323
|
-
/**
|
|
324
|
-
* React hook: returns the current perf ring snapshot, re-renders on push.
|
|
325
|
-
*/
|
|
326
|
-
declare function usePerfBuffer(): readonly PerfEntry[];
|
|
327
|
-
/**
|
|
328
|
-
* React.Profiler `onRender` callback. Records `actualDuration` per commit.
|
|
329
|
-
*/
|
|
330
|
-
declare const profilerOnRender: ProfilerOnRenderCallback;
|
|
331
|
-
|
|
332
|
-
export { BrowserPlayground, type BrowserPlaygroundProps, type ClientEventBus, type CreateClientEffectHandlersOptions, OrbPreview, type OrbPreviewProps, type ResolvedSchemaResult, ServerBridgeTransport, type SlotPatternEntry, type SlotSetter, type SlotSource, type TraitStateMachineResult, type UseTraitStateMachineOptions, clearSchemaCache, createClientEffectHandlers, profilerOnRender, usePerfBuffer, useResolvedSchema, useTraitStateMachine };
|
|
315
|
+
export { BrowserPlayground, type BrowserPlaygroundProps, type ClientEventBus, type CreateClientEffectHandlersOptions, OrbPreview, type OrbPreviewProps, type ResolvedSchemaResult, ServerBridgeTransport, type SlotPatternEntry, type SlotSetter, type SlotSource, type TraitStateMachineResult, type UseTraitStateMachineOptions, clearSchemaCache, createClientEffectHandlers, useResolvedSchema, useTraitStateMachine };
|