@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/providers/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import { useTranslate } from '@almadar/ui/hooks';
|
|
|
15
15
|
import { useUISlots, ThemeProvider, useTheme } from '@almadar/ui/context';
|
|
16
16
|
export { DesignThemeProvider, useDesignTheme } from '@almadar/ui/context';
|
|
17
17
|
import { evaluate, createMinimalContext } from '@almadar/evaluator';
|
|
18
|
-
import { wrapCallbackForEvent } from '@almadar/runtime/ui';
|
|
18
|
+
import { wrapCallbackForEvent, perfStart, perfEnd } from '@almadar/runtime/ui';
|
|
19
19
|
import { useLocation, useNavigate, Link, Outlet } from 'react-router-dom';
|
|
20
20
|
import ELK from 'elkjs/lib/elk.bundled.js';
|
|
21
21
|
import SyntaxHighlighter from 'react-syntax-highlighter/dist/esm/prism-light.js';
|
|
@@ -286,7 +286,16 @@ function isPlainObject(value) {
|
|
|
286
286
|
if (typeof value === "function") return false;
|
|
287
287
|
return true;
|
|
288
288
|
}
|
|
289
|
+
function isEvaluatorResolvedData(value) {
|
|
290
|
+
return evaluatorResolvedData.has(value);
|
|
291
|
+
}
|
|
292
|
+
function brandResolved(value) {
|
|
293
|
+
if (value !== null && typeof value === "object" && !React87__default.isValidElement(value) && !(value instanceof Date)) {
|
|
294
|
+
resolvedMarkerFree.add(value);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
289
297
|
function subtreeHasMarker(value) {
|
|
298
|
+
if (resolvedMarkerFree.has(value)) return false;
|
|
290
299
|
const cached = markerPresenceCache.get(value);
|
|
291
300
|
if (cached !== void 0) return cached;
|
|
292
301
|
let found = false;
|
|
@@ -308,10 +317,23 @@ function subtreeHasMarker(value) {
|
|
|
308
317
|
}
|
|
309
318
|
function walkValue(value, scopeTrait, entity, config, state) {
|
|
310
319
|
if (isRenderBindingMarker(value)) {
|
|
311
|
-
|
|
320
|
+
const cached = markerResolutionCache.get(value);
|
|
321
|
+
if (cached !== void 0 && cached.entity === entity && cached.config === config && cached.state === state) {
|
|
322
|
+
return { resolved: cached.resolved, changed: false };
|
|
323
|
+
}
|
|
324
|
+
const resolved = resolveMarkerExpression(value.expression, entity, config, state);
|
|
325
|
+
markerResolutionCache.set(value, { entity, config, state, resolved });
|
|
326
|
+
if (resolved !== null && typeof resolved === "object" && !React87__default.isValidElement(resolved) && !(resolved instanceof Date)) {
|
|
327
|
+
resolvedMarkerFree.add(resolved);
|
|
328
|
+
evaluatorResolvedData.add(resolved);
|
|
329
|
+
}
|
|
330
|
+
return { resolved, changed: true };
|
|
312
331
|
}
|
|
313
332
|
if (Array.isArray(value)) {
|
|
314
|
-
if (!subtreeHasMarker(value))
|
|
333
|
+
if (!subtreeHasMarker(value)) {
|
|
334
|
+
brandResolved(value);
|
|
335
|
+
return { resolved: value, changed: false };
|
|
336
|
+
}
|
|
315
337
|
const out = [];
|
|
316
338
|
let changed = false;
|
|
317
339
|
for (const item of value) {
|
|
@@ -326,10 +348,14 @@ function walkValue(value, scopeTrait, entity, config, state) {
|
|
|
326
348
|
out.push(resolved);
|
|
327
349
|
if (itemChanged) changed = true;
|
|
328
350
|
}
|
|
351
|
+
brandResolved(out);
|
|
329
352
|
return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
|
|
330
353
|
}
|
|
331
354
|
if (isPlainObject(value)) {
|
|
332
|
-
if (!subtreeHasMarker(value))
|
|
355
|
+
if (!subtreeHasMarker(value)) {
|
|
356
|
+
brandResolved(value);
|
|
357
|
+
return { resolved: value, changed: false };
|
|
358
|
+
}
|
|
333
359
|
const sourceTrait = value._sourceTrait;
|
|
334
360
|
if (typeof sourceTrait === "string" && sourceTrait !== scopeTrait) {
|
|
335
361
|
return { resolved: value, changed: false };
|
|
@@ -341,11 +367,13 @@ function walkValue(value, scopeTrait, entity, config, state) {
|
|
|
341
367
|
out[key] = resolved;
|
|
342
368
|
if (itemChanged) changed = true;
|
|
343
369
|
}
|
|
370
|
+
brandResolved(out);
|
|
344
371
|
return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
|
|
345
372
|
}
|
|
346
373
|
return { resolved: value, changed: false };
|
|
347
374
|
}
|
|
348
375
|
function resolveRenderBindingMarkers(props, scopeTrait, entity, config, state) {
|
|
376
|
+
if (resolvedMarkerFree.has(props)) return props;
|
|
349
377
|
const out = {};
|
|
350
378
|
let changed = false;
|
|
351
379
|
for (const [key, value] of Object.entries(props)) {
|
|
@@ -353,13 +381,17 @@ function resolveRenderBindingMarkers(props, scopeTrait, entity, config, state) {
|
|
|
353
381
|
out[key] = resolved;
|
|
354
382
|
if (propChanged) changed = true;
|
|
355
383
|
}
|
|
384
|
+
brandResolved(out);
|
|
356
385
|
return changed ? out : props;
|
|
357
386
|
}
|
|
358
|
-
var markerPresenceCache;
|
|
387
|
+
var markerPresenceCache, markerResolutionCache, resolvedMarkerFree, evaluatorResolvedData;
|
|
359
388
|
var init_resolve_render_bindings = __esm({
|
|
360
389
|
"lib/resolve-render-bindings.ts"() {
|
|
361
390
|
"use client";
|
|
362
391
|
markerPresenceCache = /* @__PURE__ */ new WeakMap();
|
|
392
|
+
markerResolutionCache = /* @__PURE__ */ new WeakMap();
|
|
393
|
+
resolvedMarkerFree = /* @__PURE__ */ new WeakSet();
|
|
394
|
+
evaluatorResolvedData = /* @__PURE__ */ new WeakSet();
|
|
363
395
|
}
|
|
364
396
|
});
|
|
365
397
|
function cn(...inputs) {
|
|
@@ -11793,6 +11825,10 @@ var init_molecules = __esm({
|
|
|
11793
11825
|
init_puzzleObject();
|
|
11794
11826
|
}
|
|
11795
11827
|
});
|
|
11828
|
+
var init_perf = __esm({
|
|
11829
|
+
"lib/perf.ts"() {
|
|
11830
|
+
}
|
|
11831
|
+
});
|
|
11796
11832
|
function themeBodyFont(el) {
|
|
11797
11833
|
if (typeof getComputedStyle !== "function") return "system-ui, sans-serif";
|
|
11798
11834
|
const v = getComputedStyle(el).getPropertyValue("--font-family-body").trim();
|
|
@@ -12141,6 +12177,7 @@ var init_LearningCanvas = __esm({
|
|
|
12141
12177
|
"components/learning/atoms/LearningCanvas.tsx"() {
|
|
12142
12178
|
"use client";
|
|
12143
12179
|
init_cn();
|
|
12180
|
+
init_perf();
|
|
12144
12181
|
init_useEventBus();
|
|
12145
12182
|
DASH_PATTERNS = { dashed: [6, 4], dotted: [2, 3] };
|
|
12146
12183
|
TRACE_SERIES_COLORS = ["#2563eb", "#dc2626", "#16a34a", "#f59e0b"];
|
|
@@ -12184,6 +12221,7 @@ var init_LearningCanvas = __esm({
|
|
|
12184
12221
|
return [...shapes, ...traceOut, ...readoutOut];
|
|
12185
12222
|
}, [shapes, traces, readouts, width, height]);
|
|
12186
12223
|
const draw = useCallback(() => {
|
|
12224
|
+
const _perfT = perfStart("learningcanvas:paint");
|
|
12187
12225
|
const canvas = canvasRef.current;
|
|
12188
12226
|
if (!canvas) return;
|
|
12189
12227
|
const ctx = canvas.getContext("2d");
|
|
@@ -12205,6 +12243,7 @@ var init_LearningCanvas = __esm({
|
|
|
12205
12243
|
for (const shape of derivedShapes) {
|
|
12206
12244
|
if (shape.type === "text") drawShape(ctx, shape, width, height, derivedShapes);
|
|
12207
12245
|
}
|
|
12246
|
+
perfEnd("learningcanvas:paint", _perfT);
|
|
12208
12247
|
}, [width, height, backgroundColor, derivedShapes]);
|
|
12209
12248
|
useEffect(() => {
|
|
12210
12249
|
draw();
|
|
@@ -30609,6 +30648,7 @@ var init_MathCanvas = __esm({
|
|
|
30609
30648
|
"components/learning/molecules/MathCanvas.tsx"() {
|
|
30610
30649
|
"use client";
|
|
30611
30650
|
init_useEventBus();
|
|
30651
|
+
init_perf();
|
|
30612
30652
|
init_atoms();
|
|
30613
30653
|
init_Stack();
|
|
30614
30654
|
init_LearningCanvas();
|
|
@@ -30674,6 +30714,7 @@ var init_MathCanvas = __esm({
|
|
|
30674
30714
|
};
|
|
30675
30715
|
}, [stableKeyMap, stableKeyUpMap, eventBus]);
|
|
30676
30716
|
const derivedShapes = useMemo(() => {
|
|
30717
|
+
const _perfT = perfStart("mathcanvas:derive");
|
|
30677
30718
|
const out = [];
|
|
30678
30719
|
const margin = 24;
|
|
30679
30720
|
const plotW = width - margin * 2;
|
|
@@ -30917,6 +30958,7 @@ var init_MathCanvas = __esm({
|
|
|
30917
30958
|
}
|
|
30918
30959
|
}
|
|
30919
30960
|
out.push(...shapes);
|
|
30961
|
+
perfEnd("mathcanvas:derive", _perfT);
|
|
30920
30962
|
return out;
|
|
30921
30963
|
}, [
|
|
30922
30964
|
width,
|
|
@@ -32180,12 +32222,12 @@ var init_MapView = __esm({
|
|
|
32180
32222
|
shadowSize: [41, 41]
|
|
32181
32223
|
});
|
|
32182
32224
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
32183
|
-
const { useEffect: useEffect67, useRef:
|
|
32225
|
+
const { useEffect: useEffect67, useRef: useRef65, useCallback: useCallback97, useState: useState95 } = React87__default;
|
|
32184
32226
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
32185
32227
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
32186
32228
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
32187
32229
|
const map = useMap();
|
|
32188
|
-
const prevRef =
|
|
32230
|
+
const prevRef = useRef65({ centerLat, centerLng, zoom });
|
|
32189
32231
|
useEffect67(() => {
|
|
32190
32232
|
const prev = prevRef.current;
|
|
32191
32233
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
@@ -37270,7 +37312,7 @@ var init_RichBlockEditor = __esm({
|
|
|
37270
37312
|
{
|
|
37271
37313
|
variant: "bordered",
|
|
37272
37314
|
padding: "none",
|
|
37273
|
-
className: cn("flex flex-col", className),
|
|
37315
|
+
className: cn("flex flex-col text-card-foreground", className),
|
|
37274
37316
|
children: [
|
|
37275
37317
|
enableBlocks && showToolbar && !readOnly && /* @__PURE__ */ jsx(
|
|
37276
37318
|
Box,
|
|
@@ -42498,6 +42540,7 @@ var init_DetailPanel = __esm({
|
|
|
42498
42540
|
"use client";
|
|
42499
42541
|
init_atoms();
|
|
42500
42542
|
init_Box();
|
|
42543
|
+
init_Input();
|
|
42501
42544
|
init_Stack();
|
|
42502
42545
|
init_SimpleGrid();
|
|
42503
42546
|
init_Menu();
|
|
@@ -42513,6 +42556,7 @@ var init_DetailPanel = __esm({
|
|
|
42513
42556
|
ReactMarkdown2 = lazy(() => import('react-markdown'));
|
|
42514
42557
|
DetailPanel = ({
|
|
42515
42558
|
title: propTitle,
|
|
42559
|
+
onTitleCommit,
|
|
42516
42560
|
subtitle,
|
|
42517
42561
|
status,
|
|
42518
42562
|
avatar,
|
|
@@ -42534,6 +42578,7 @@ var init_DetailPanel = __esm({
|
|
|
42534
42578
|
}) => {
|
|
42535
42579
|
const eventBus = useEventBus();
|
|
42536
42580
|
const { t } = useTranslate();
|
|
42581
|
+
const [titleDraft, setTitleDraft] = React87__default.useState(null);
|
|
42537
42582
|
const isFieldDefArray = (arr) => {
|
|
42538
42583
|
if (!arr || arr.length === 0) return false;
|
|
42539
42584
|
const first = arr[0];
|
|
@@ -42754,6 +42799,50 @@ var init_DetailPanel = __esm({
|
|
|
42754
42799
|
}),
|
|
42755
42800
|
status && /* @__PURE__ */ jsx(Badge, { variant: status.variant ?? "default", children: status.label })
|
|
42756
42801
|
] });
|
|
42802
|
+
const commitTitle = () => {
|
|
42803
|
+
if (!onTitleCommit) return;
|
|
42804
|
+
const next = (titleDraft ?? "").trim();
|
|
42805
|
+
setTitleDraft(null);
|
|
42806
|
+
if (!next || next === title) return;
|
|
42807
|
+
onTitleCommit(next, normalizedData?.id !== void 0 ? String(normalizedData.id) : "");
|
|
42808
|
+
};
|
|
42809
|
+
const titleNode = onTitleCommit && titleDraft !== null ? /* @__PURE__ */ jsx(
|
|
42810
|
+
Input,
|
|
42811
|
+
{
|
|
42812
|
+
value: titleDraft,
|
|
42813
|
+
autoFocus: true,
|
|
42814
|
+
"aria-label": t("common.title"),
|
|
42815
|
+
className: "h-auto py-1 text-3xl font-bold tracking-tight",
|
|
42816
|
+
onChange: (e) => setTitleDraft(e.target.value),
|
|
42817
|
+
onBlur: commitTitle,
|
|
42818
|
+
onKeyDown: (e) => {
|
|
42819
|
+
if (e.key === "Enter") {
|
|
42820
|
+
e.preventDefault();
|
|
42821
|
+
commitTitle();
|
|
42822
|
+
} else if (e.key === "Escape") {
|
|
42823
|
+
e.preventDefault();
|
|
42824
|
+
setTitleDraft(null);
|
|
42825
|
+
}
|
|
42826
|
+
},
|
|
42827
|
+
"data-testid": "detail-title-input"
|
|
42828
|
+
}
|
|
42829
|
+
) : onTitleCommit ? /* @__PURE__ */ jsx(
|
|
42830
|
+
Box,
|
|
42831
|
+
{
|
|
42832
|
+
role: "button",
|
|
42833
|
+
tabIndex: 0,
|
|
42834
|
+
className: "cursor-text rounded px-1 -mx-1 transition-colors hover:bg-muted/40",
|
|
42835
|
+
onClick: () => setTitleDraft(title ?? ""),
|
|
42836
|
+
onKeyDown: (e) => {
|
|
42837
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
42838
|
+
e.preventDefault();
|
|
42839
|
+
setTitleDraft(title ?? "");
|
|
42840
|
+
}
|
|
42841
|
+
},
|
|
42842
|
+
"data-testid": "detail-title-editable",
|
|
42843
|
+
children: /* @__PURE__ */ jsx(Typography, { variant: "h2", weight: "bold", children: title || "Details" })
|
|
42844
|
+
}
|
|
42845
|
+
) : /* @__PURE__ */ jsx(Typography, { variant: "h2", weight: "bold", children: title || "Details" });
|
|
42757
42846
|
const content = /* @__PURE__ */ jsx(Card, { variant: "elevated", children: /* @__PURE__ */ jsxs(VStack, { gap: "md", className: "p-6", children: [
|
|
42758
42847
|
/* @__PURE__ */ jsxs(HStack, { justify: "between", align: "start", gap: "md", children: [
|
|
42759
42848
|
/* @__PURE__ */ jsxs(HStack, { align: "start", gap: "sm", className: "min-w-0", children: [
|
|
@@ -42773,7 +42862,7 @@ var init_DetailPanel = __esm({
|
|
|
42773
42862
|
avatar,
|
|
42774
42863
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "min-w-0", children: [
|
|
42775
42864
|
/* @__PURE__ */ jsxs(HStack, { align: "center", gap: "sm", wrap: true, children: [
|
|
42776
|
-
|
|
42865
|
+
titleNode,
|
|
42777
42866
|
statusBadges
|
|
42778
42867
|
] }),
|
|
42779
42868
|
subtitle && /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: subtitle })
|
|
@@ -43334,7 +43423,7 @@ var init_Form = __esm({
|
|
|
43334
43423
|
});
|
|
43335
43424
|
debug(
|
|
43336
43425
|
"forms",
|
|
43337
|
-
`Calculation triggered: ${calc.variableName} = ${value}`
|
|
43426
|
+
`Calculation triggered: ${calc.variableName} = ${String(value)}`
|
|
43338
43427
|
);
|
|
43339
43428
|
}
|
|
43340
43429
|
});
|
|
@@ -49814,6 +49903,7 @@ function isPlainConfigObject(value) {
|
|
|
49814
49903
|
return proto === Object.prototype || proto === null;
|
|
49815
49904
|
}
|
|
49816
49905
|
function subtreeHasTraitRef(value) {
|
|
49906
|
+
if (isEvaluatorResolvedData(value)) return false;
|
|
49817
49907
|
const cached = traitRefPresenceCache.get(value);
|
|
49818
49908
|
if (cached !== void 0) return cached;
|
|
49819
49909
|
let found = false;
|
|
@@ -49886,6 +49976,10 @@ function renderPatternProps(props, onDismiss, propsSchema) {
|
|
|
49886
49976
|
};
|
|
49887
49977
|
rendered[key] = /* @__PURE__ */ jsx(SlotContentRenderer, { content: childContent, onDismiss });
|
|
49888
49978
|
} else if (Array.isArray(value)) {
|
|
49979
|
+
if (!isEvaluatorResolvedData(value) && value.some((el) => isPatternConfig(el))) ; else if (!subtreeHasTraitRef(value)) {
|
|
49980
|
+
rendered[key] = value;
|
|
49981
|
+
continue;
|
|
49982
|
+
}
|
|
49889
49983
|
const isDataArray = propsSchema?.[key]?.items?.types?.includes("object") ?? false;
|
|
49890
49984
|
rendered[key] = value.map((item, i) => {
|
|
49891
49985
|
const el = item;
|
|
@@ -51327,6 +51421,53 @@ function useNavigationId2() {
|
|
|
51327
51421
|
|
|
51328
51422
|
// providers/ServerBridge.tsx
|
|
51329
51423
|
init_useEventBus();
|
|
51424
|
+
|
|
51425
|
+
// lib/tick-send-relay.ts
|
|
51426
|
+
function createTickSendRelay(send) {
|
|
51427
|
+
const lanes = /* @__PURE__ */ new Map();
|
|
51428
|
+
const flush = (key, lane) => {
|
|
51429
|
+
const next = lane.pending;
|
|
51430
|
+
lane.pending = void 0;
|
|
51431
|
+
if (next === void 0) {
|
|
51432
|
+
lane.inFlight = false;
|
|
51433
|
+
return;
|
|
51434
|
+
}
|
|
51435
|
+
lane.inFlight = true;
|
|
51436
|
+
void send(key, next).catch(() => void 0).then(() => flush(key, lane));
|
|
51437
|
+
};
|
|
51438
|
+
return {
|
|
51439
|
+
send(key, value) {
|
|
51440
|
+
const lane = lanes.get(key) ?? { inFlight: false };
|
|
51441
|
+
lanes.set(key, lane);
|
|
51442
|
+
if (lane.inFlight) {
|
|
51443
|
+
lane.pending = value;
|
|
51444
|
+
return;
|
|
51445
|
+
}
|
|
51446
|
+
lane.pending = value;
|
|
51447
|
+
flush(key, lane);
|
|
51448
|
+
},
|
|
51449
|
+
clear() {
|
|
51450
|
+
for (const lane of lanes.values()) {
|
|
51451
|
+
lane.pending = void 0;
|
|
51452
|
+
}
|
|
51453
|
+
}
|
|
51454
|
+
};
|
|
51455
|
+
}
|
|
51456
|
+
|
|
51457
|
+
// lib/command-send-pump.ts
|
|
51458
|
+
function createCommandSendPump() {
|
|
51459
|
+
let tail = Promise.resolve();
|
|
51460
|
+
return {
|
|
51461
|
+
enqueue(job) {
|
|
51462
|
+
const result = tail.then(job);
|
|
51463
|
+
tail = result.then(
|
|
51464
|
+
() => void 0,
|
|
51465
|
+
() => void 0
|
|
51466
|
+
);
|
|
51467
|
+
return result;
|
|
51468
|
+
}
|
|
51469
|
+
};
|
|
51470
|
+
}
|
|
51330
51471
|
var xOrbitalLog = createLogger("almadar:runtime:cross-orbital");
|
|
51331
51472
|
var serverBridgeLog = createLogger("almadar:ui:server-bridge");
|
|
51332
51473
|
function reEmitServerEvent(eventBus, emitted, origin) {
|
|
@@ -51461,99 +51602,118 @@ function ServerBridgeProvider({
|
|
|
51461
51602
|
async () => transport.unregister(),
|
|
51462
51603
|
[transport]
|
|
51463
51604
|
);
|
|
51605
|
+
const tickRelay = useMemo(
|
|
51606
|
+
() => createTickSendRelay(async (_key, snap) => {
|
|
51607
|
+
await transport.sendEvent(snap.orbitalName, snap.event, snap.payload, getTabClientId(), snap.tick, snap.sourceTrait);
|
|
51608
|
+
}),
|
|
51609
|
+
[transport]
|
|
51610
|
+
);
|
|
51611
|
+
useEffect(() => () => tickRelay.clear(), [tickRelay]);
|
|
51612
|
+
const commandPump = useMemo(createCommandSendPump, []);
|
|
51613
|
+
const disposedRef = useRef(false);
|
|
51614
|
+
useEffect(() => {
|
|
51615
|
+
disposedRef.current = false;
|
|
51616
|
+
return () => {
|
|
51617
|
+
disposedRef.current = true;
|
|
51618
|
+
};
|
|
51619
|
+
}, []);
|
|
51464
51620
|
const sendEvent = useCallback(async (orbitalName, event, payload, tick, sourceTrait) => {
|
|
51465
51621
|
const emptyMeta = { success: false, clientEffects: 0, dataEntities: {}, emittedEvents: [] };
|
|
51466
51622
|
if (!connected) return { effects: [], meta: emptyMeta };
|
|
51467
|
-
|
|
51468
|
-
|
|
51469
|
-
|
|
51470
|
-
|
|
51471
|
-
|
|
51472
|
-
}
|
|
51473
|
-
|
|
51474
|
-
|
|
51475
|
-
|
|
51476
|
-
|
|
51477
|
-
|
|
51478
|
-
|
|
51479
|
-
|
|
51480
|
-
|
|
51481
|
-
|
|
51482
|
-
|
|
51483
|
-
|
|
51484
|
-
|
|
51485
|
-
|
|
51486
|
-
|
|
51487
|
-
|
|
51488
|
-
|
|
51489
|
-
|
|
51490
|
-
const
|
|
51491
|
-
|
|
51492
|
-
|
|
51493
|
-
const
|
|
51494
|
-
|
|
51495
|
-
|
|
51496
|
-
|
|
51497
|
-
|
|
51498
|
-
|
|
51499
|
-
|
|
51500
|
-
|
|
51501
|
-
|
|
51502
|
-
|
|
51503
|
-
|
|
51504
|
-
|
|
51505
|
-
|
|
51506
|
-
|
|
51507
|
-
|
|
51508
|
-
|
|
51509
|
-
|
|
51510
|
-
|
|
51511
|
-
|
|
51512
|
-
|
|
51513
|
-
|
|
51514
|
-
|
|
51515
|
-
|
|
51516
|
-
|
|
51517
|
-
|
|
51518
|
-
|
|
51519
|
-
|
|
51520
|
-
|
|
51521
|
-
|
|
51522
|
-
|
|
51523
|
-
|
|
51524
|
-
|
|
51525
|
-
|
|
51526
|
-
|
|
51527
|
-
|
|
51623
|
+
if (tick !== void 0) {
|
|
51624
|
+
tickRelay.send(`${orbitalName}:${event}`, { orbitalName, event, payload, tick, sourceTrait });
|
|
51625
|
+
return { effects: [], meta: { ...emptyMeta, success: true } };
|
|
51626
|
+
}
|
|
51627
|
+
return commandPump.enqueue(async () => {
|
|
51628
|
+
if (disposedRef.current) return { effects: [], meta: emptyMeta };
|
|
51629
|
+
try {
|
|
51630
|
+
const result = await transport.sendEvent(orbitalName, event, payload, getTabClientId(), tick, sourceTrait);
|
|
51631
|
+
const effects = [];
|
|
51632
|
+
const responseData = result.data || {};
|
|
51633
|
+
const dataEntities = {};
|
|
51634
|
+
for (const [entityName, records] of Object.entries(responseData)) {
|
|
51635
|
+
dataEntities[entityName] = Array.isArray(records) ? records.length : 0;
|
|
51636
|
+
}
|
|
51637
|
+
const meta = {
|
|
51638
|
+
success: !!result.success,
|
|
51639
|
+
clientEffects: result.clientEffects?.length ?? 0,
|
|
51640
|
+
dataEntities,
|
|
51641
|
+
data: responseData,
|
|
51642
|
+
emittedEvents: result.emittedEvents?.map((e) => e.event) ?? [],
|
|
51643
|
+
error: result.error
|
|
51644
|
+
};
|
|
51645
|
+
if (result.success) {
|
|
51646
|
+
const tagged = result.clientEffectsByTrait;
|
|
51647
|
+
const tuples = tagged ? tagged.map((entry) => ({ effect: entry.effect, traitName: entry.traitName })) : (result.clientEffects ?? []).map((eff) => ({ effect: eff }));
|
|
51648
|
+
for (const { effect, traitName } of tuples) {
|
|
51649
|
+
const effectType = effect[0];
|
|
51650
|
+
if (effectType === "render-ui") {
|
|
51651
|
+
const slot = effect[1];
|
|
51652
|
+
const pattern = effect[2];
|
|
51653
|
+
effects.push({
|
|
51654
|
+
type: "render-ui",
|
|
51655
|
+
slot,
|
|
51656
|
+
pattern: pattern !== null && typeof pattern === "object" ? pattern : void 0,
|
|
51657
|
+
traitName
|
|
51658
|
+
});
|
|
51659
|
+
} else if (effectType === "navigate") {
|
|
51660
|
+
const route = effect[1];
|
|
51661
|
+
const rawParams = effect[2];
|
|
51662
|
+
const rawOptions = effect[3];
|
|
51663
|
+
const optionsObj = rawOptions !== null && rawOptions !== void 0 && typeof rawOptions === "object" && !Array.isArray(rawOptions) ? rawOptions : void 0;
|
|
51664
|
+
const crumb = typeof optionsObj?.crumb === "string" ? optionsObj.crumb : void 0;
|
|
51665
|
+
effects.push({
|
|
51666
|
+
type: "navigate",
|
|
51667
|
+
route,
|
|
51668
|
+
params: rawParams !== null && rawParams !== void 0 && typeof rawParams === "object" && !Array.isArray(rawParams) ? rawParams : void 0,
|
|
51669
|
+
crumb,
|
|
51670
|
+
traitName
|
|
51671
|
+
});
|
|
51672
|
+
} else if (effectType === "navigate-back") {
|
|
51673
|
+
effects.push({ type: "navigate-back", traitName });
|
|
51674
|
+
} else if (effectType === "notify") {
|
|
51675
|
+
const message = effect[1];
|
|
51676
|
+
effects.push({ type: "notify", message: typeof message === "string" ? message : void 0, traitName });
|
|
51677
|
+
}
|
|
51678
|
+
}
|
|
51679
|
+
if (result.emittedEvents) {
|
|
51680
|
+
for (const emitted of result.emittedEvents) {
|
|
51681
|
+
if (emitted.event === event) continue;
|
|
51682
|
+
reEmitServerEvent(
|
|
51683
|
+
eventBus,
|
|
51684
|
+
{ ...emitted, source: { ...emitted.source, dispatched: true } },
|
|
51685
|
+
orbitalName
|
|
51686
|
+
);
|
|
51687
|
+
}
|
|
51528
51688
|
}
|
|
51689
|
+
} else if (result.error) {
|
|
51690
|
+
xOrbitalLog.warn("response:fail", {
|
|
51691
|
+
orbital: orbitalName,
|
|
51692
|
+
event,
|
|
51693
|
+
error: result.error
|
|
51694
|
+
});
|
|
51529
51695
|
}
|
|
51530
|
-
|
|
51531
|
-
|
|
51532
|
-
|
|
51533
|
-
|
|
51534
|
-
|
|
51535
|
-
|
|
51536
|
-
|
|
51537
|
-
|
|
51538
|
-
|
|
51539
|
-
|
|
51540
|
-
|
|
51541
|
-
|
|
51542
|
-
|
|
51543
|
-
|
|
51544
|
-
|
|
51545
|
-
|
|
51546
|
-
}
|
|
51547
|
-
|
|
51548
|
-
xOrbitalLog.error("response:network", {
|
|
51549
|
-
orbital: orbitalName,
|
|
51550
|
-
event,
|
|
51551
|
-
error: msg
|
|
51552
|
-
});
|
|
51696
|
+
return { effects, meta };
|
|
51697
|
+
} catch (err) {
|
|
51698
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
51699
|
+
if (err instanceof TypeError) {
|
|
51700
|
+
xOrbitalLog.warn("response:network", {
|
|
51701
|
+
orbital: orbitalName,
|
|
51702
|
+
event,
|
|
51703
|
+
error: msg,
|
|
51704
|
+
reason: "peer endpoint unreachable (expected in standalone single-orbital mode)"
|
|
51705
|
+
});
|
|
51706
|
+
} else {
|
|
51707
|
+
xOrbitalLog.error("response:network", {
|
|
51708
|
+
orbital: orbitalName,
|
|
51709
|
+
event,
|
|
51710
|
+
error: msg
|
|
51711
|
+
});
|
|
51712
|
+
}
|
|
51713
|
+
return { effects: [], meta: { ...emptyMeta, error: msg } };
|
|
51553
51714
|
}
|
|
51554
|
-
|
|
51555
|
-
|
|
51556
|
-
}, [connected, transport, eventBus]);
|
|
51715
|
+
});
|
|
51716
|
+
}, [connected, transport, eventBus, tickRelay, commandPump]);
|
|
51557
51717
|
useEffect(() => {
|
|
51558
51718
|
if (!schema) return;
|
|
51559
51719
|
let cancelled = false;
|