@almadar/ui 5.156.0 → 5.158.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-Bn3ePJQC.d.cts} +6 -2
- package/dist/{EntityBindingContext-BfZGeDfX.d.ts → EntityBindingContext-Bn3ePJQC.d.ts} +6 -2
- package/dist/avl/index.cjs +283 -43
- package/dist/avl/index.js +283 -43
- package/dist/components/index.cjs +249 -33
- package/dist/components/index.d.cts +46 -6
- package/dist/components/index.d.ts +46 -6
- package/dist/components/index.js +250 -34
- package/dist/providers/index.cjs +251 -35
- package/dist/providers/index.d.cts +1 -1
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.js +251 -35
- package/dist/runtime/index.cjs +283 -43
- package/dist/runtime/index.d.cts +12 -3
- package/dist/runtime/index.d.ts +12 -3
- package/dist/runtime/index.js +283 -43
- package/package.json +4 -4
package/dist/runtime/index.cjs
CHANGED
|
@@ -884,11 +884,32 @@ function isPlainObject(value) {
|
|
|
884
884
|
if (typeof value === "function") return false;
|
|
885
885
|
return true;
|
|
886
886
|
}
|
|
887
|
+
function subtreeHasMarker(value) {
|
|
888
|
+
const cached = markerPresenceCache.get(value);
|
|
889
|
+
if (cached !== void 0) return cached;
|
|
890
|
+
let found = false;
|
|
891
|
+
const children = Array.isArray(value) ? value : Object.values(value);
|
|
892
|
+
for (const child of children) {
|
|
893
|
+
if (core.isRenderBindingMarker(child)) {
|
|
894
|
+
found = true;
|
|
895
|
+
break;
|
|
896
|
+
}
|
|
897
|
+
if (Array.isArray(child) || isPlainObject(child)) {
|
|
898
|
+
if (subtreeHasMarker(child)) {
|
|
899
|
+
found = true;
|
|
900
|
+
break;
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
markerPresenceCache.set(value, found);
|
|
905
|
+
return found;
|
|
906
|
+
}
|
|
887
907
|
function walkValue(value, scopeTrait, entity, config, state) {
|
|
888
908
|
if (core.isRenderBindingMarker(value)) {
|
|
889
909
|
return { resolved: resolveMarkerExpression(value.expression, entity, config, state), changed: true };
|
|
890
910
|
}
|
|
891
911
|
if (Array.isArray(value)) {
|
|
912
|
+
if (!subtreeHasMarker(value)) return { resolved: value, changed: false };
|
|
892
913
|
const out = [];
|
|
893
914
|
let changed = false;
|
|
894
915
|
for (const item of value) {
|
|
@@ -906,6 +927,7 @@ function walkValue(value, scopeTrait, entity, config, state) {
|
|
|
906
927
|
return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
|
|
907
928
|
}
|
|
908
929
|
if (isPlainObject(value)) {
|
|
930
|
+
if (!subtreeHasMarker(value)) return { resolved: value, changed: false };
|
|
909
931
|
const sourceTrait = value._sourceTrait;
|
|
910
932
|
if (typeof sourceTrait === "string" && sourceTrait !== scopeTrait) {
|
|
911
933
|
return { resolved: value, changed: false };
|
|
@@ -931,9 +953,11 @@ function resolveRenderBindingMarkers(props, scopeTrait, entity, config, state) {
|
|
|
931
953
|
}
|
|
932
954
|
return changed ? out : props;
|
|
933
955
|
}
|
|
956
|
+
var markerPresenceCache;
|
|
934
957
|
var init_resolve_render_bindings = __esm({
|
|
935
958
|
"lib/resolve-render-bindings.ts"() {
|
|
936
959
|
"use client";
|
|
960
|
+
markerPresenceCache = /* @__PURE__ */ new WeakMap();
|
|
937
961
|
}
|
|
938
962
|
});
|
|
939
963
|
function cn(...inputs) {
|
|
@@ -12103,6 +12127,8 @@ function drawShape(ctx, shape, width, height, allShapes) {
|
|
|
12103
12127
|
case "path": {
|
|
12104
12128
|
if (!shape.path) break;
|
|
12105
12129
|
const p = new Path2D(shape.path);
|
|
12130
|
+
ctx.lineJoin = "round";
|
|
12131
|
+
ctx.lineCap = "round";
|
|
12106
12132
|
if (fill) {
|
|
12107
12133
|
ctx.fillStyle = fill;
|
|
12108
12134
|
ctx.fill(p);
|
|
@@ -12311,7 +12337,7 @@ var init_LearningCanvas = __esm({
|
|
|
12311
12337
|
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
12312
12338
|
ctx.clearRect(0, 0, width, height);
|
|
12313
12339
|
if (backgroundColor) {
|
|
12314
|
-
ctx.fillStyle = backgroundColor;
|
|
12340
|
+
ctx.fillStyle = resolveColor2(backgroundColor, ctx, backgroundColor);
|
|
12315
12341
|
ctx.fillRect(0, 0, width, height);
|
|
12316
12342
|
}
|
|
12317
12343
|
for (const shape of derivedShapes) {
|
|
@@ -26993,7 +27019,7 @@ function fileIcon(name) {
|
|
|
26993
27019
|
return "file";
|
|
26994
27020
|
}
|
|
26995
27021
|
}
|
|
26996
|
-
var TreeNodeItem, FileTree;
|
|
27022
|
+
var TreeNodeItem, FlatTreeNodeItem, FileTree;
|
|
26997
27023
|
var init_FileTree = __esm({
|
|
26998
27024
|
"components/core/molecules/FileTree.tsx"() {
|
|
26999
27025
|
"use client";
|
|
@@ -27078,14 +27104,101 @@ var init_FileTree = __esm({
|
|
|
27078
27104
|
)) })
|
|
27079
27105
|
] });
|
|
27080
27106
|
};
|
|
27107
|
+
FlatTreeNodeItem = ({
|
|
27108
|
+
item,
|
|
27109
|
+
depth,
|
|
27110
|
+
indent,
|
|
27111
|
+
childrenByParent,
|
|
27112
|
+
onNodeSelect,
|
|
27113
|
+
defaultExpanded = false
|
|
27114
|
+
}) => {
|
|
27115
|
+
const [expanded, setExpanded] = React85.useState(defaultExpanded || depth < 1);
|
|
27116
|
+
const children = childrenByParent.get(item.id);
|
|
27117
|
+
const hasChildren = !!children && children.length > 0;
|
|
27118
|
+
const handleClick = React85.useCallback(() => {
|
|
27119
|
+
if (hasChildren) setExpanded((prev) => !prev);
|
|
27120
|
+
onNodeSelect?.(item.id);
|
|
27121
|
+
}, [hasChildren, item.id, onNodeSelect]);
|
|
27122
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
27123
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
27124
|
+
Box,
|
|
27125
|
+
{
|
|
27126
|
+
className: "flex items-center gap-1.5 py-0.5 px-2 cursor-pointer rounded-sm transition-colors hover:bg-muted",
|
|
27127
|
+
style: { paddingLeft: depth * indent + 8 },
|
|
27128
|
+
onClick: handleClick,
|
|
27129
|
+
role: "treeitem",
|
|
27130
|
+
"aria-expanded": hasChildren ? expanded : void 0,
|
|
27131
|
+
children: [
|
|
27132
|
+
hasChildren ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
27133
|
+
Icon,
|
|
27134
|
+
{
|
|
27135
|
+
name: expanded ? "chevron-down" : "chevron-right",
|
|
27136
|
+
size: "xs",
|
|
27137
|
+
className: "text-[var(--color-muted-foreground)] flex-shrink-0"
|
|
27138
|
+
}
|
|
27139
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(Box, { style: { width: 12, flexShrink: 0 } }),
|
|
27140
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
27141
|
+
Icon,
|
|
27142
|
+
{
|
|
27143
|
+
name: item.icon ?? (hasChildren ? expanded ? "folder-open" : "folder" : "file"),
|
|
27144
|
+
size: "xs",
|
|
27145
|
+
className: hasChildren ? "text-[var(--color-warning)]" : "text-[var(--color-muted-foreground)]"
|
|
27146
|
+
}
|
|
27147
|
+
),
|
|
27148
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "truncate font-mono text-xs", children: item.label })
|
|
27149
|
+
]
|
|
27150
|
+
}
|
|
27151
|
+
),
|
|
27152
|
+
hasChildren && expanded && /* @__PURE__ */ jsxRuntime.jsx(Box, { role: "group", children: children.map((child) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
27153
|
+
FlatTreeNodeItem,
|
|
27154
|
+
{
|
|
27155
|
+
item: child,
|
|
27156
|
+
depth: depth + 1,
|
|
27157
|
+
indent,
|
|
27158
|
+
childrenByParent,
|
|
27159
|
+
onNodeSelect
|
|
27160
|
+
},
|
|
27161
|
+
child.id
|
|
27162
|
+
)) })
|
|
27163
|
+
] });
|
|
27164
|
+
};
|
|
27081
27165
|
FileTree = ({
|
|
27082
27166
|
tree,
|
|
27167
|
+
items,
|
|
27083
27168
|
selectedPath,
|
|
27084
27169
|
onFileSelect,
|
|
27170
|
+
onNodeSelect,
|
|
27085
27171
|
className,
|
|
27086
27172
|
indent = 16
|
|
27087
27173
|
}) => {
|
|
27088
|
-
if (
|
|
27174
|
+
if (items) {
|
|
27175
|
+
if (items.length === 0) return null;
|
|
27176
|
+
const ids = new Set(items.map((node) => node.id));
|
|
27177
|
+
const childrenByParent = /* @__PURE__ */ new Map();
|
|
27178
|
+
const roots = [];
|
|
27179
|
+
for (const item of items) {
|
|
27180
|
+
if (item.parentId && ids.has(item.parentId)) {
|
|
27181
|
+
const siblings = childrenByParent.get(item.parentId);
|
|
27182
|
+
if (siblings) siblings.push(item);
|
|
27183
|
+
else childrenByParent.set(item.parentId, [item]);
|
|
27184
|
+
} else {
|
|
27185
|
+
roots.push(item);
|
|
27186
|
+
}
|
|
27187
|
+
}
|
|
27188
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: `py-1 overflow-y-auto ${className ?? ""}`, role: "tree", children: roots.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
27189
|
+
FlatTreeNodeItem,
|
|
27190
|
+
{
|
|
27191
|
+
item,
|
|
27192
|
+
depth: 0,
|
|
27193
|
+
indent,
|
|
27194
|
+
childrenByParent,
|
|
27195
|
+
onNodeSelect,
|
|
27196
|
+
defaultExpanded: true
|
|
27197
|
+
},
|
|
27198
|
+
item.id
|
|
27199
|
+
)) });
|
|
27200
|
+
}
|
|
27201
|
+
if (!tree || tree.length === 0) return null;
|
|
27089
27202
|
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: `py-1 overflow-y-auto ${className ?? ""}`, role: "tree", children: tree.map((node) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
27090
27203
|
TreeNodeItem,
|
|
27091
27204
|
{
|
|
@@ -28416,7 +28529,7 @@ var init_debug = __esm({
|
|
|
28416
28529
|
logger.createLogger("almadar:ui:debug:game-state");
|
|
28417
28530
|
}
|
|
28418
28531
|
});
|
|
28419
|
-
var isRelationsDebugEnabled, RelationSelect;
|
|
28532
|
+
var isRelationsDebugEnabled, MANY_CARDINALITIES, RelationSelect;
|
|
28420
28533
|
var init_RelationSelect = __esm({
|
|
28421
28534
|
"components/core/molecules/RelationSelect.tsx"() {
|
|
28422
28535
|
"use client";
|
|
@@ -28430,6 +28543,11 @@ var init_RelationSelect = __esm({
|
|
|
28430
28543
|
init_Typography();
|
|
28431
28544
|
init_debug();
|
|
28432
28545
|
isRelationsDebugEnabled = () => isDebugEnabled();
|
|
28546
|
+
MANY_CARDINALITIES = [
|
|
28547
|
+
"many",
|
|
28548
|
+
"one-to-many",
|
|
28549
|
+
"many-to-many"
|
|
28550
|
+
];
|
|
28433
28551
|
RelationSelect = ({
|
|
28434
28552
|
value,
|
|
28435
28553
|
onChange,
|
|
@@ -30069,6 +30187,9 @@ var init_MathCanvas = __esm({
|
|
|
30069
30187
|
showAxes = true,
|
|
30070
30188
|
showGrid = true,
|
|
30071
30189
|
gridStep = 1,
|
|
30190
|
+
backgroundColor,
|
|
30191
|
+
gridColor = "var(--color-border, #9ca3af)",
|
|
30192
|
+
axisColor = "var(--color-muted-foreground, #374151)",
|
|
30072
30193
|
showTickLabels = false,
|
|
30073
30194
|
showCurveLabels = false,
|
|
30074
30195
|
curves = [],
|
|
@@ -30091,17 +30212,21 @@ var init_MathCanvas = __esm({
|
|
|
30091
30212
|
error
|
|
30092
30213
|
}) => {
|
|
30093
30214
|
const eventBus = useEventBus();
|
|
30215
|
+
const keyMapKey = keyMap ? JSON.stringify(keyMap) : null;
|
|
30216
|
+
const keyUpMapKey = keyUpMap ? JSON.stringify(keyUpMap) : null;
|
|
30217
|
+
const stableKeyMap = React85.useMemo(() => keyMap, [keyMapKey]);
|
|
30218
|
+
const stableKeyUpMap = React85.useMemo(() => keyUpMap, [keyUpMapKey]);
|
|
30094
30219
|
React85.useEffect(() => {
|
|
30095
|
-
if (!
|
|
30220
|
+
if (!stableKeyMap && !stableKeyUpMap) return;
|
|
30096
30221
|
const onDown = (e) => {
|
|
30097
|
-
const ev =
|
|
30222
|
+
const ev = stableKeyMap?.[e.code];
|
|
30098
30223
|
if (ev) {
|
|
30099
30224
|
eventBus.emit(`UI:${ev}`, {});
|
|
30100
30225
|
e.preventDefault();
|
|
30101
30226
|
}
|
|
30102
30227
|
};
|
|
30103
30228
|
const onUp = (e) => {
|
|
30104
|
-
const ev =
|
|
30229
|
+
const ev = stableKeyUpMap?.[e.code];
|
|
30105
30230
|
if (ev) eventBus.emit(`UI:${ev}`, {});
|
|
30106
30231
|
};
|
|
30107
30232
|
window.addEventListener("keydown", onDown);
|
|
@@ -30110,7 +30235,7 @@ var init_MathCanvas = __esm({
|
|
|
30110
30235
|
window.removeEventListener("keydown", onDown);
|
|
30111
30236
|
window.removeEventListener("keyup", onUp);
|
|
30112
30237
|
};
|
|
30113
|
-
}, [
|
|
30238
|
+
}, [stableKeyMap, stableKeyUpMap, eventBus]);
|
|
30114
30239
|
const derivedShapes = React85.useMemo(() => {
|
|
30115
30240
|
const out = [];
|
|
30116
30241
|
const margin = 24;
|
|
@@ -30123,11 +30248,11 @@ var init_MathCanvas = __esm({
|
|
|
30123
30248
|
if (showGrid) {
|
|
30124
30249
|
for (let x = Math.ceil(xMin / gridStep) * gridStep; x <= xMax; x += gridStep) {
|
|
30125
30250
|
const px = mapX(x);
|
|
30126
|
-
out.push({ type: "line", x1: px, y1: margin, x2: px, y2: height - margin, color:
|
|
30251
|
+
out.push({ type: "line", x1: px, y1: margin, x2: px, y2: height - margin, color: gridColor, opacity: 0.35, lineWidth: 1 });
|
|
30127
30252
|
}
|
|
30128
30253
|
for (let y = Math.ceil(yMin / gridStep) * gridStep; y <= yMax; y += gridStep) {
|
|
30129
30254
|
const py = mapY(y);
|
|
30130
|
-
out.push({ type: "line", x1: margin, y1: py, x2: width - margin, y2: py, color:
|
|
30255
|
+
out.push({ type: "line", x1: margin, y1: py, x2: width - margin, y2: py, color: gridColor, opacity: 0.35, lineWidth: 1 });
|
|
30131
30256
|
}
|
|
30132
30257
|
}
|
|
30133
30258
|
if (showTickLabels) {
|
|
@@ -30198,8 +30323,8 @@ var init_MathCanvas = __esm({
|
|
|
30198
30323
|
});
|
|
30199
30324
|
}
|
|
30200
30325
|
if (showAxes) {
|
|
30201
|
-
out.push({ type: "line", x1: margin, y1: xAxisY, x2: width - margin, y2: xAxisY, color:
|
|
30202
|
-
out.push({ type: "line", x1: yAxisX, y1: margin, x2: yAxisX, y2: height - margin, color:
|
|
30326
|
+
out.push({ type: "line", x1: margin, y1: xAxisY, x2: width - margin, y2: xAxisY, color: axisColor, lineWidth: 2 });
|
|
30327
|
+
out.push({ type: "line", x1: yAxisX, y1: margin, x2: yAxisX, y2: height - margin, color: axisColor, lineWidth: 2 });
|
|
30203
30328
|
}
|
|
30204
30329
|
for (const guide of guides) {
|
|
30205
30330
|
const color = guide.color ?? "#9ca3af";
|
|
@@ -30222,23 +30347,36 @@ var init_MathCanvas = __esm({
|
|
|
30222
30347
|
}
|
|
30223
30348
|
for (const curve of curves) {
|
|
30224
30349
|
if (!curve.samples || curve.samples.length < 2) continue;
|
|
30350
|
+
let d = "";
|
|
30351
|
+
let penDown = false;
|
|
30225
30352
|
let lastInRange;
|
|
30226
30353
|
for (let i = 1; i < curve.samples.length; i++) {
|
|
30227
30354
|
const a = curve.samples[i - 1];
|
|
30228
30355
|
const b = curve.samples[i];
|
|
30229
|
-
if (a.x < xMin
|
|
30230
|
-
|
|
30231
|
-
|
|
30232
|
-
|
|
30233
|
-
|
|
30234
|
-
|
|
30235
|
-
|
|
30236
|
-
|
|
30237
|
-
|
|
30238
|
-
|
|
30239
|
-
|
|
30240
|
-
|
|
30241
|
-
|
|
30356
|
+
if (a.x < xMin && b.x < xMin || a.x > xMax && b.x > xMax) {
|
|
30357
|
+
penDown = false;
|
|
30358
|
+
continue;
|
|
30359
|
+
}
|
|
30360
|
+
const clip = (p, q, xLim) => {
|
|
30361
|
+
const t = q.x === p.x ? 0 : (xLim - p.x) / (q.x - p.x);
|
|
30362
|
+
return { x: xLim, y: p.y + t * (q.y - p.y) };
|
|
30363
|
+
};
|
|
30364
|
+
const ca = a.x < xMin ? clip(a, b, xMin) : a.x > xMax ? clip(a, b, xMax) : a;
|
|
30365
|
+
const cb = b.x < xMin ? clip(a, b, xMin) : b.x > xMax ? clip(a, b, xMax) : b;
|
|
30366
|
+
const pax = mapX(ca.x);
|
|
30367
|
+
const pay = mapY(ca.y);
|
|
30368
|
+
d += `${penDown ? "L" : "M"} ${pax} ${pay} L ${mapX(cb.x)} ${mapY(cb.y)} `;
|
|
30369
|
+
penDown = true;
|
|
30370
|
+
if (b.x >= xMin && b.x <= xMax) lastInRange = b;
|
|
30371
|
+
}
|
|
30372
|
+
if (!d) continue;
|
|
30373
|
+
out.push({
|
|
30374
|
+
type: "path",
|
|
30375
|
+
path: d,
|
|
30376
|
+
color: curve.color ?? "#2563eb",
|
|
30377
|
+
lineWidth: 2,
|
|
30378
|
+
dash: curve.dash
|
|
30379
|
+
});
|
|
30242
30380
|
if (showCurveLabels && curve.label && lastInRange) {
|
|
30243
30381
|
out.push({
|
|
30244
30382
|
type: "text",
|
|
@@ -30353,6 +30491,8 @@ var init_MathCanvas = __esm({
|
|
|
30353
30491
|
showAxes,
|
|
30354
30492
|
showGrid,
|
|
30355
30493
|
gridStep,
|
|
30494
|
+
gridColor,
|
|
30495
|
+
axisColor,
|
|
30356
30496
|
showTickLabels,
|
|
30357
30497
|
showCurveLabels,
|
|
30358
30498
|
curves,
|
|
@@ -30372,6 +30512,7 @@ var init_MathCanvas = __esm({
|
|
|
30372
30512
|
{
|
|
30373
30513
|
width,
|
|
30374
30514
|
height,
|
|
30515
|
+
backgroundColor,
|
|
30375
30516
|
shapes: derivedShapes,
|
|
30376
30517
|
readouts,
|
|
30377
30518
|
traces,
|
|
@@ -42393,6 +42534,9 @@ function determineInputType(field) {
|
|
|
42393
42534
|
if (field.type === "relation" || field.relation) {
|
|
42394
42535
|
return "relation";
|
|
42395
42536
|
}
|
|
42537
|
+
if (field.type === "array") {
|
|
42538
|
+
return "array";
|
|
42539
|
+
}
|
|
42396
42540
|
if (field.type === "enum" || field.values || getEnumOptions(field).length > 0) {
|
|
42397
42541
|
return "select";
|
|
42398
42542
|
}
|
|
@@ -42468,6 +42612,7 @@ var init_Form = __esm({
|
|
|
42468
42612
|
init_Typography();
|
|
42469
42613
|
init_Icon();
|
|
42470
42614
|
init_RelationSelect();
|
|
42615
|
+
init_TagInput();
|
|
42471
42616
|
init_UploadDropZone();
|
|
42472
42617
|
init_Alert();
|
|
42473
42618
|
init_useEventBus();
|
|
@@ -42547,7 +42692,7 @@ var init_Form = __esm({
|
|
|
42547
42692
|
values: "values" in f3 ? f3.values : void 0,
|
|
42548
42693
|
min: f3.min,
|
|
42549
42694
|
max: f3.max,
|
|
42550
|
-
relation: "relation" in f3 ? { entity: f3.relation.entity } : void 0
|
|
42695
|
+
relation: "relation" in f3 ? { entity: f3.relation.entity, cardinality: f3.relation.cardinality } : void 0
|
|
42551
42696
|
})
|
|
42552
42697
|
);
|
|
42553
42698
|
}, [entity, fields]);
|
|
@@ -42782,7 +42927,7 @@ var init_Form = __esm({
|
|
|
42782
42927
|
values: "values" in entityField ? entityField.values : void 0,
|
|
42783
42928
|
min: entityField.min,
|
|
42784
42929
|
max: entityField.max,
|
|
42785
|
-
relation: "relation" in entityField ? { entity: entityField.relation.entity } : void 0
|
|
42930
|
+
relation: "relation" in entityField ? { entity: entityField.relation.entity, cardinality: entityField.relation.cardinality } : void 0
|
|
42786
42931
|
};
|
|
42787
42932
|
}
|
|
42788
42933
|
return { name: field, type: "string" };
|
|
@@ -42894,6 +43039,22 @@ var init_Form = __esm({
|
|
|
42894
43039
|
case "relation": {
|
|
42895
43040
|
const relationOptions = relationsData[fieldName] || [];
|
|
42896
43041
|
const relationLoading = relationsLoading[fieldName] || false;
|
|
43042
|
+
if (field.relation?.cardinality !== void 0 && MANY_CARDINALITIES.includes(field.relation.cardinality)) {
|
|
43043
|
+
const selectedValues = Array.isArray(currentValue) ? currentValue.map((v) => String(v)) : [];
|
|
43044
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
43045
|
+
Select,
|
|
43046
|
+
{
|
|
43047
|
+
...commonProps,
|
|
43048
|
+
multiple: true,
|
|
43049
|
+
searchable: true,
|
|
43050
|
+
clearable: true,
|
|
43051
|
+
options: [...relationOptions],
|
|
43052
|
+
value: selectedValues,
|
|
43053
|
+
onValueChange: (value) => handleChange(fieldName, Array.isArray(value) ? value : [value]),
|
|
43054
|
+
placeholder: field.placeholder || `Select ${label}...`
|
|
43055
|
+
}
|
|
43056
|
+
);
|
|
43057
|
+
}
|
|
42897
43058
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
42898
43059
|
RelationSelect,
|
|
42899
43060
|
{
|
|
@@ -42908,6 +43069,18 @@ var init_Form = __esm({
|
|
|
42908
43069
|
}
|
|
42909
43070
|
);
|
|
42910
43071
|
}
|
|
43072
|
+
case "array": {
|
|
43073
|
+
const arrayValue = Array.isArray(currentValue) ? currentValue.map((v) => String(v)) : currentValue != null && currentValue !== "" ? [String(currentValue)] : [];
|
|
43074
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
43075
|
+
TagInput,
|
|
43076
|
+
{
|
|
43077
|
+
placeholder: field.placeholder,
|
|
43078
|
+
disabled: isLoading,
|
|
43079
|
+
value: arrayValue,
|
|
43080
|
+
onChange: (next) => handleChange(fieldName, [...next])
|
|
43081
|
+
}
|
|
43082
|
+
);
|
|
43083
|
+
}
|
|
42911
43084
|
case "number":
|
|
42912
43085
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
42913
43086
|
Input,
|
|
@@ -48476,7 +48649,10 @@ function enrichFormFields(fields, entityDef) {
|
|
|
48476
48649
|
enriched.values = entityField.enumValues;
|
|
48477
48650
|
}
|
|
48478
48651
|
if (entityField.relation) {
|
|
48479
|
-
enriched.relation =
|
|
48652
|
+
enriched.relation = {
|
|
48653
|
+
entity: entityField.relation.entity,
|
|
48654
|
+
cardinality: entityField.relation.cardinality
|
|
48655
|
+
};
|
|
48480
48656
|
}
|
|
48481
48657
|
return enriched;
|
|
48482
48658
|
}
|
|
@@ -48504,7 +48680,10 @@ function enrichFormFields(fields, entityDef) {
|
|
|
48504
48680
|
}
|
|
48505
48681
|
}
|
|
48506
48682
|
if (!obj.relation && entityField.relation) {
|
|
48507
|
-
enriched.relation =
|
|
48683
|
+
enriched.relation = {
|
|
48684
|
+
entity: entityField.relation.entity,
|
|
48685
|
+
cardinality: entityField.relation.cardinality
|
|
48686
|
+
};
|
|
48508
48687
|
}
|
|
48509
48688
|
return enriched;
|
|
48510
48689
|
}
|
|
@@ -48519,7 +48698,12 @@ function enrichDetailFields(fields, entityDef) {
|
|
|
48519
48698
|
const meta = { type: entityField.type };
|
|
48520
48699
|
const values = entityField.values ?? entityField.enumValues;
|
|
48521
48700
|
if (values && values.length > 0) meta.values = values;
|
|
48522
|
-
if (entityField.relation)
|
|
48701
|
+
if (entityField.relation) {
|
|
48702
|
+
meta.relation = {
|
|
48703
|
+
entity: entityField.relation.entity,
|
|
48704
|
+
cardinality: entityField.relation.cardinality
|
|
48705
|
+
};
|
|
48706
|
+
}
|
|
48523
48707
|
return meta;
|
|
48524
48708
|
};
|
|
48525
48709
|
return fields.map((field) => {
|
|
@@ -49073,6 +49257,32 @@ function isPlainConfigObject(value) {
|
|
|
49073
49257
|
const proto = Object.getPrototypeOf(value);
|
|
49074
49258
|
return proto === Object.prototype || proto === null;
|
|
49075
49259
|
}
|
|
49260
|
+
function subtreeHasTraitRef(value) {
|
|
49261
|
+
const cached = traitRefPresenceCache.get(value);
|
|
49262
|
+
if (cached !== void 0) return cached;
|
|
49263
|
+
let found = false;
|
|
49264
|
+
const children = Array.isArray(value) ? value : Object.values(value);
|
|
49265
|
+
for (const child of children) {
|
|
49266
|
+
if (typeof child === "string" && TRAIT_BINDING_RE.test(child)) {
|
|
49267
|
+
found = true;
|
|
49268
|
+
break;
|
|
49269
|
+
}
|
|
49270
|
+
if (core.isRenderBindingMarker(child)) continue;
|
|
49271
|
+
if (Array.isArray(child)) {
|
|
49272
|
+
if (subtreeHasTraitRef(child)) {
|
|
49273
|
+
found = true;
|
|
49274
|
+
break;
|
|
49275
|
+
}
|
|
49276
|
+
} else if (child !== null && typeof child === "object" && isPlainConfigObject(child)) {
|
|
49277
|
+
if (subtreeHasTraitRef(child)) {
|
|
49278
|
+
found = true;
|
|
49279
|
+
break;
|
|
49280
|
+
}
|
|
49281
|
+
}
|
|
49282
|
+
}
|
|
49283
|
+
traitRefPresenceCache.set(value, found);
|
|
49284
|
+
return found;
|
|
49285
|
+
}
|
|
49076
49286
|
function substituteTraitRefsDeep(value, pathKey) {
|
|
49077
49287
|
if (core.isRenderBindingMarker(value)) return value;
|
|
49078
49288
|
if (typeof value === "string") {
|
|
@@ -49087,11 +49297,13 @@ function substituteTraitRefsDeep(value, pathKey) {
|
|
|
49087
49297
|
return value;
|
|
49088
49298
|
}
|
|
49089
49299
|
if (Array.isArray(value)) {
|
|
49300
|
+
if (!subtreeHasTraitRef(value)) return value;
|
|
49090
49301
|
return value.map(
|
|
49091
49302
|
(item, i) => substituteTraitRefsDeep(item, `${pathKey}[${i}]`)
|
|
49092
49303
|
);
|
|
49093
49304
|
}
|
|
49094
49305
|
if (typeof value === "object" && isPlainConfigObject(value)) {
|
|
49306
|
+
if (!subtreeHasTraitRef(value)) return value;
|
|
49095
49307
|
const out = {};
|
|
49096
49308
|
for (const [k, v] of Object.entries(value)) {
|
|
49097
49309
|
out[k] = substituteTraitRefsDeep(v, `${pathKey}.${k}`);
|
|
@@ -49380,7 +49592,7 @@ function UISlotRenderer({
|
|
|
49380
49592
|
}
|
|
49381
49593
|
return wrapped;
|
|
49382
49594
|
}
|
|
49383
|
-
var scopeWrapLog, TRAIT_BINDING_RE, SuspenseConfigContext, SlotContainedContext, SLOT_SKELETON_MAP, SELF_OVERLAY_PATTERNS, CONTENT_NODE_SLOTS, PATTERNS_WITH_CHILDREN;
|
|
49595
|
+
var scopeWrapLog, TRAIT_BINDING_RE, SuspenseConfigContext, SlotContainedContext, SLOT_SKELETON_MAP, SELF_OVERLAY_PATTERNS, CONTENT_NODE_SLOTS, PATTERNS_WITH_CHILDREN, traitRefPresenceCache;
|
|
49384
49596
|
var init_UISlotRenderer = __esm({
|
|
49385
49597
|
"components/core/organisms/UISlotRenderer.tsx"() {
|
|
49386
49598
|
"use client";
|
|
@@ -49454,6 +49666,7 @@ var init_UISlotRenderer = __esm({
|
|
|
49454
49666
|
"alert",
|
|
49455
49667
|
"dialog"
|
|
49456
49668
|
]);
|
|
49669
|
+
traitRefPresenceCache = /* @__PURE__ */ new WeakMap();
|
|
49457
49670
|
UISlotRenderer.displayName = "UISlotRenderer";
|
|
49458
49671
|
}
|
|
49459
49672
|
});
|
|
@@ -49581,6 +49794,20 @@ function createClientEffectHandlers(options) {
|
|
|
49581
49794
|
})
|
|
49582
49795
|
};
|
|
49583
49796
|
}
|
|
49797
|
+
|
|
49798
|
+
// lib/event-queue-coalesce.ts
|
|
49799
|
+
function enqueueEvent(queue, entry) {
|
|
49800
|
+
if (entry.tick !== void 0) {
|
|
49801
|
+
const pending = queue.find(
|
|
49802
|
+
(e) => e.tick !== void 0 && e.eventKey === entry.eventKey && e.targetTrait === entry.targetTrait
|
|
49803
|
+
);
|
|
49804
|
+
if (pending !== void 0) {
|
|
49805
|
+
pending.payload = entry.payload;
|
|
49806
|
+
return;
|
|
49807
|
+
}
|
|
49808
|
+
}
|
|
49809
|
+
queue.push(entry);
|
|
49810
|
+
}
|
|
49584
49811
|
var lambdaLog = logger.createLogger("almadar:ui:fn-form-lambda");
|
|
49585
49812
|
function isOperatorCall(value) {
|
|
49586
49813
|
const first = value[0];
|
|
@@ -50326,12 +50553,13 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
50326
50553
|
entityId
|
|
50327
50554
|
};
|
|
50328
50555
|
const emittedDuringExec = [];
|
|
50556
|
+
const tickName = flushEvent.startsWith("tick:") ? flushEvent.slice(5) : void 0;
|
|
50329
50557
|
const baseEmit = handlers.emit;
|
|
50330
50558
|
const trackingHandlers = {
|
|
50331
50559
|
...handlers,
|
|
50332
50560
|
emit: (event, eventPayload, source) => {
|
|
50333
50561
|
emittedDuringExec.push(event);
|
|
50334
|
-
baseEmit(event, eventPayload, source);
|
|
50562
|
+
baseEmit(event, eventPayload, tickName !== void 0 ? { ...source, tick: tickName } : source);
|
|
50335
50563
|
}
|
|
50336
50564
|
};
|
|
50337
50565
|
if (traitName === "Hero") {
|
|
@@ -50490,7 +50718,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
50490
50718
|
}
|
|
50491
50719
|
return () => scheduler.stopAll();
|
|
50492
50720
|
}, [traitBindings, runTickEffects, sharedGroups, sharedEntityStore, emitFromSharedWriter]);
|
|
50493
|
-
const processEventQueued = React85.useCallback(async (eventKey, payload, targetTrait) => {
|
|
50721
|
+
const processEventQueued = React85.useCallback(async (eventKey, payload, targetTrait, tick, sourceTrait) => {
|
|
50494
50722
|
const normalizedEvent = normalizeEventKey(eventKey);
|
|
50495
50723
|
const bindings = traitBindingsRef.current;
|
|
50496
50724
|
const currentManager = managerRef.current;
|
|
@@ -50679,7 +50907,11 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
50679
50907
|
if (orbital) dispatchedOrbitals.add(orbital);
|
|
50680
50908
|
}
|
|
50681
50909
|
const relayPayload = targetTrait !== void 0 ? { ...payload ?? {}, _targetTrait: targetTrait } : payload;
|
|
50682
|
-
|
|
50910
|
+
if (tick !== void 0) {
|
|
50911
|
+
void onEventProcessed(normalizedEvent, relayPayload, dispatchedOrbitals, tick, sourceTrait);
|
|
50912
|
+
} else {
|
|
50913
|
+
await onEventProcessed(normalizedEvent, relayPayload, dispatchedOrbitals);
|
|
50914
|
+
}
|
|
50683
50915
|
}
|
|
50684
50916
|
}, [entities, eventBus, sharedEntityStore]);
|
|
50685
50917
|
const drainEventQueue = React85.useCallback(async () => {
|
|
@@ -50688,14 +50920,14 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
50688
50920
|
try {
|
|
50689
50921
|
while (eventQueueRef.current.length > 0) {
|
|
50690
50922
|
const entry = eventQueueRef.current.shift();
|
|
50691
|
-
await processEventQueued(entry.eventKey, entry.payload, entry.targetTrait);
|
|
50923
|
+
await processEventQueued(entry.eventKey, entry.payload, entry.targetTrait, entry.tick, entry.sourceTrait);
|
|
50692
50924
|
}
|
|
50693
50925
|
} finally {
|
|
50694
50926
|
processingRef.current = false;
|
|
50695
50927
|
}
|
|
50696
50928
|
}, [processEventQueued]);
|
|
50697
|
-
const enqueueAndDrain = React85.useCallback((eventKey, payload, targetTrait) => {
|
|
50698
|
-
eventQueueRef.current
|
|
50929
|
+
const enqueueAndDrain = React85.useCallback((eventKey, payload, targetTrait, tick, sourceTrait) => {
|
|
50930
|
+
enqueueEvent(eventQueueRef.current, { eventKey, payload, targetTrait, tick, sourceTrait });
|
|
50699
50931
|
void drainEventQueue();
|
|
50700
50932
|
}, [drainEventQueue]);
|
|
50701
50933
|
React85.useCallback((eventKey, payload) => {
|
|
@@ -50748,7 +50980,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
50748
50980
|
crossTraitLog.debug("self:fire-server-cascade", { traitName, busKey: selfBusKey, eventKey });
|
|
50749
50981
|
}
|
|
50750
50982
|
crossTraitLog.debug("self:fire", { traitName, busKey: selfBusKey, eventKey });
|
|
50751
|
-
enqueueAndDrain(eventKey, event.payload, traitName);
|
|
50983
|
+
enqueueAndDrain(eventKey, event.payload, traitName, event.source?.tick, event.source?.trait);
|
|
50752
50984
|
});
|
|
50753
50985
|
unsubscribes.push(() => {
|
|
50754
50986
|
crossTraitLog.debug("self:unsubscribe", { traitName, busKey: selfBusKey, eventKey });
|
|
@@ -50766,7 +50998,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
50766
50998
|
const bareKey = `UI:${eventKey}`;
|
|
50767
50999
|
const unsub = eventBus.on(bareKey, (event) => {
|
|
50768
51000
|
crossTraitLog.debug("bare-cascade:fire", { bareKey, eventKey });
|
|
50769
|
-
enqueueAndDrain(eventKey, event.payload);
|
|
51001
|
+
enqueueAndDrain(eventKey, event.payload, void 0, event.source?.tick, event.source?.trait);
|
|
50770
51002
|
});
|
|
50771
51003
|
unsubscribes.push(() => {
|
|
50772
51004
|
crossTraitLog.debug("bare-cascade:unsubscribe", { bareKey, eventKey });
|
|
@@ -50800,7 +51032,9 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
50800
51032
|
enqueueAndDrain(
|
|
50801
51033
|
listen.triggers,
|
|
50802
51034
|
core.applyListenPayloadMapping(listen.payloadMapping, event.payload, evaluator.evaluateListenPayloadExpr),
|
|
50803
|
-
binding.trait.name
|
|
51035
|
+
binding.trait.name,
|
|
51036
|
+
event.source?.tick,
|
|
51037
|
+
event.source?.trait
|
|
50804
51038
|
);
|
|
50805
51039
|
});
|
|
50806
51040
|
unsubscribes.push(() => {
|
|
@@ -51095,7 +51329,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
|
|
|
51095
51329
|
[serverActiveTraits]
|
|
51096
51330
|
);
|
|
51097
51331
|
const uiSlots = context.useUISlots();
|
|
51098
|
-
const onEventProcessed = React85.useCallback(async (event, payload, dispatchedOrbitals) => {
|
|
51332
|
+
const onEventProcessed = React85.useCallback(async (event, payload, dispatchedOrbitals, tick, sourceTrait) => {
|
|
51099
51333
|
if (!bridge.connected || !orbitalNames?.length) return;
|
|
51100
51334
|
const targets = dispatchedOrbitals && dispatchedOrbitals.size > 0 ? orbitalNames.filter((n) => dispatchedOrbitals.has(n)) : orbitalNames;
|
|
51101
51335
|
xOrbitalLog.debug("TraitInitializer:fanout", () => ({
|
|
@@ -51105,6 +51339,10 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
|
|
|
51105
51339
|
dispatchedOrbitalsSize: dispatchedOrbitals?.size ?? 0
|
|
51106
51340
|
}));
|
|
51107
51341
|
for (const name of targets) {
|
|
51342
|
+
if (tick !== void 0) {
|
|
51343
|
+
void bridge.sendEvent(name, event, withActiveTraits(payload), tick, sourceTrait);
|
|
51344
|
+
continue;
|
|
51345
|
+
}
|
|
51108
51346
|
const { effects, meta } = await bridge.sendEvent(name, event, withActiveTraits(payload));
|
|
51109
51347
|
recordServerResponse(name, event, meta);
|
|
51110
51348
|
applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits, activeTraitNames, onNavigateBack);
|
|
@@ -51580,11 +51818,13 @@ function BrowserPlayground({
|
|
|
51580
51818
|
unregister: async () => {
|
|
51581
51819
|
runtime.unregisterAll();
|
|
51582
51820
|
},
|
|
51583
|
-
sendEvent: async (orbitalName, event, payload) => {
|
|
51821
|
+
sendEvent: async (orbitalName, event, payload, _clientId, tick, sourceTrait) => {
|
|
51584
51822
|
await registrationReady;
|
|
51585
51823
|
return runtime.processOrbitalEvent(orbitalName, {
|
|
51586
51824
|
event,
|
|
51587
|
-
payload
|
|
51825
|
+
payload,
|
|
51826
|
+
tick,
|
|
51827
|
+
sourceTrait
|
|
51588
51828
|
// @almadar/runtime OrbitalEventResponse.clientEffects uses a wider ClientEffectTuple than
|
|
51589
51829
|
// ServerBridge's local definition — cast at this boundary (upstream fix queued).
|
|
51590
51830
|
});
|
package/dist/runtime/index.d.cts
CHANGED
|
@@ -5,8 +5,8 @@ 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 { a as EntityBindingSource, h as ServerBridgeTransport } from '../EntityBindingContext-
|
|
9
|
-
export { b as EntitySchemaContextValue, c as EntitySchemaProvider, d as EntitySchemaProviderProps, e as ServerBridgeContextValue, f as ServerBridgeProvider, i as ServerClientEffect, T as TraitContext, k as TraitContextValue, l as TraitInstance, m as TraitProvider, n as TraitProviderProps, o as useEntitySchema, p as useEntitySchemaOptional, q as useServerBridge, r as useTrait, s as useTraitContext } from '../EntityBindingContext-
|
|
8
|
+
import { a as EntityBindingSource, h as ServerBridgeTransport } from '../EntityBindingContext-Bn3ePJQC.cjs';
|
|
9
|
+
export { b as EntitySchemaContextValue, c as EntitySchemaProvider, d as EntitySchemaProviderProps, e as ServerBridgeContextValue, f as ServerBridgeProvider, i as ServerClientEffect, T as TraitContext, k as TraitContextValue, l as TraitInstance, m as TraitProvider, n as TraitProviderProps, o as useEntitySchema, p as useEntitySchemaOptional, q as useServerBridge, r as useTrait, s as useTraitContext } from '../EntityBindingContext-Bn3ePJQC.cjs';
|
|
10
10
|
import { PerfEntry } from '@almadar/runtime/ui';
|
|
11
11
|
export { PERF_NAMESPACE, PerfEntry, PreparedPreviewSchema, adjustSchemaForMockData, buildMockData, clearPerf, perfEnd, perfStart, perfTime, prepareSchemaForPreview, wrapCallbackForEvent } from '@almadar/runtime/ui';
|
|
12
12
|
import React__default, { ProfilerOnRenderCallback } from 'react';
|
|
@@ -39,7 +39,16 @@ interface UseTraitStateMachineOptions {
|
|
|
39
39
|
* set means no local transition matched — leave the legacy fallback to
|
|
40
40
|
* the consumer.
|
|
41
41
|
*/
|
|
42
|
-
onEventProcessed?: (eventKey: string, payload?: EventPayload, dispatchedOrbitals?: Set<string
|
|
42
|
+
onEventProcessed?: (eventKey: string, payload?: EventPayload, dispatchedOrbitals?: Set<string>,
|
|
43
|
+
/**
|
|
44
|
+
* Broadcast-class marker (T6): when set, the entry is a tick's
|
|
45
|
+
* latest-state broadcast — the drain does NOT await the server
|
|
46
|
+
* fan-out, and the bridge discards the response (nobody reads a
|
|
47
|
+
* broadcast response; applying a stale one would clobber newer
|
|
48
|
+
* local state). `sourceTrait` is the emitting trait, for the
|
|
49
|
+
* server relay's BusEventSource.
|
|
50
|
+
*/
|
|
51
|
+
tick?: string, sourceTrait?: string) => void | Promise<void>;
|
|
43
52
|
/** Router navigate function for navigate effects. `crumb` labels the
|
|
44
53
|
* target page's navigation-stack entry (from the effect's options). */
|
|
45
54
|
navigate?: (path: string, params?: Record<string, string>, crumb?: string) => void;
|