@almadar/ui 4.23.0 → 4.25.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/avl/index.cjs +102 -16
- package/dist/avl/index.js +102 -16
- package/dist/components/index.cjs +48 -6
- package/dist/components/index.js +48 -6
- package/dist/context/UISlotContext.d.ts +2 -2
- package/dist/hooks/useUISlots.d.ts +65 -7
- package/dist/providers/index.cjs +48 -6
- package/dist/providers/index.js +48 -6
- package/dist/runtime/fn-form-lambda.d.ts +4 -3
- package/dist/runtime/index.cjs +102 -16
- package/dist/runtime/index.js +102 -16
- package/package.json +2 -2
package/dist/runtime/index.js
CHANGED
|
@@ -37837,7 +37837,8 @@ function renderPatternChildren(children, onDismiss, parentId = "root", parentPat
|
|
|
37837
37837
|
if (!child || typeof child !== "object") return null;
|
|
37838
37838
|
const childId = `${parentId}-${index}`;
|
|
37839
37839
|
const childPath = parentPath === "root" ? `root.children.${index}` : `${parentPath}.children.${index}`;
|
|
37840
|
-
const
|
|
37840
|
+
const childAsRecord = child;
|
|
37841
|
+
const { type: _childType, props: nestedProps, _id: _childNodeId, children: _childChildren, ...flatProps } = childAsRecord;
|
|
37841
37842
|
const resolvedProps = nestedProps !== void 0 ? nestedProps : flatProps;
|
|
37842
37843
|
if (_childChildren !== void 0 && nestedProps === void 0) {
|
|
37843
37844
|
resolvedProps.children = _childChildren;
|
|
@@ -37865,7 +37866,46 @@ function renderPatternChildren(children, onDismiss, parentId = "root", parentPat
|
|
|
37865
37866
|
});
|
|
37866
37867
|
}
|
|
37867
37868
|
function isPatternConfig(value) {
|
|
37868
|
-
|
|
37869
|
+
if (value === null || value === void 0) return false;
|
|
37870
|
+
if (typeof value !== "object") return false;
|
|
37871
|
+
if (Array.isArray(value)) return false;
|
|
37872
|
+
if (React113__default.isValidElement(value)) return false;
|
|
37873
|
+
if (value instanceof Date) return false;
|
|
37874
|
+
if (typeof value === "function") return false;
|
|
37875
|
+
const record = value;
|
|
37876
|
+
return "type" in record && typeof record.type === "string";
|
|
37877
|
+
}
|
|
37878
|
+
function isPlainConfigObject(value) {
|
|
37879
|
+
if (React113__default.isValidElement(value)) return false;
|
|
37880
|
+
if (value instanceof Date) return false;
|
|
37881
|
+
const proto = Object.getPrototypeOf(value);
|
|
37882
|
+
return proto === Object.prototype || proto === null;
|
|
37883
|
+
}
|
|
37884
|
+
function substituteTraitRefsDeep(value, pathKey) {
|
|
37885
|
+
if (typeof value === "string") {
|
|
37886
|
+
const match = TRAIT_BINDING_RE.exec(value);
|
|
37887
|
+
if (match) {
|
|
37888
|
+
const traitName = match[1];
|
|
37889
|
+
return /* @__PURE__ */ jsx(TraitFrame, { traitName }, `${pathKey}:${traitName}`);
|
|
37890
|
+
}
|
|
37891
|
+
return value;
|
|
37892
|
+
}
|
|
37893
|
+
if (typeof value === "number" || typeof value === "boolean" || value === null || value === void 0 || typeof value === "function") {
|
|
37894
|
+
return value;
|
|
37895
|
+
}
|
|
37896
|
+
if (Array.isArray(value)) {
|
|
37897
|
+
return value.map(
|
|
37898
|
+
(item, i) => substituteTraitRefsDeep(item, `${pathKey}[${i}]`)
|
|
37899
|
+
);
|
|
37900
|
+
}
|
|
37901
|
+
if (typeof value === "object" && isPlainConfigObject(value)) {
|
|
37902
|
+
const out = {};
|
|
37903
|
+
for (const [k, v] of Object.entries(value)) {
|
|
37904
|
+
out[k] = substituteTraitRefsDeep(v, `${pathKey}.${k}`);
|
|
37905
|
+
}
|
|
37906
|
+
return out;
|
|
37907
|
+
}
|
|
37908
|
+
return value;
|
|
37869
37909
|
}
|
|
37870
37910
|
function renderPatternProps(props, onDismiss) {
|
|
37871
37911
|
const rendered = {};
|
|
@@ -37873,17 +37913,19 @@ function renderPatternProps(props, onDismiss) {
|
|
|
37873
37913
|
if (key === "children") {
|
|
37874
37914
|
rendered[key] = value;
|
|
37875
37915
|
} else if (isPatternConfig(value)) {
|
|
37916
|
+
const nestedProps = {};
|
|
37917
|
+
for (const [k, v] of Object.entries(value)) {
|
|
37918
|
+
if (k !== "type") nestedProps[k] = v;
|
|
37919
|
+
}
|
|
37876
37920
|
const childContent = {
|
|
37877
37921
|
id: `prop-${key}`,
|
|
37878
37922
|
pattern: value.type,
|
|
37879
|
-
props:
|
|
37880
|
-
Object.entries(value).filter(([k]) => k !== "type")
|
|
37881
|
-
),
|
|
37923
|
+
props: nestedProps,
|
|
37882
37924
|
priority: 0
|
|
37883
37925
|
};
|
|
37884
37926
|
rendered[key] = /* @__PURE__ */ jsx(SlotContentRenderer, { content: childContent, onDismiss });
|
|
37885
37927
|
} else {
|
|
37886
|
-
rendered[key] = value;
|
|
37928
|
+
rendered[key] = substituteTraitRefsDeep(value, `prop:${key}`);
|
|
37887
37929
|
}
|
|
37888
37930
|
}
|
|
37889
37931
|
return rendered;
|
|
@@ -38226,7 +38268,7 @@ function resolveLambdaBindings(body, argName, arg) {
|
|
|
38226
38268
|
let cur = arg;
|
|
38227
38269
|
for (const seg of path.split(".")) {
|
|
38228
38270
|
if (cur === null || cur === void 0) return void 0;
|
|
38229
|
-
if (typeof cur !== "object") return void 0;
|
|
38271
|
+
if (typeof cur !== "object" || Array.isArray(cur)) return void 0;
|
|
38230
38272
|
cur = cur[seg];
|
|
38231
38273
|
}
|
|
38232
38274
|
return cur;
|
|
@@ -38242,7 +38284,7 @@ function resolveLambdaBindings(body, argName, arg) {
|
|
|
38242
38284
|
if (Array.isArray(body)) {
|
|
38243
38285
|
return body.map((b) => resolveLambdaBindings(b, argName, arg));
|
|
38244
38286
|
}
|
|
38245
|
-
if (body !== null && typeof body === "object") {
|
|
38287
|
+
if (body !== null && typeof body === "object" && !React113__default.isValidElement(body) && !(body instanceof Date) && typeof body !== "function") {
|
|
38246
38288
|
const out = {};
|
|
38247
38289
|
for (const [k, v] of Object.entries(body)) {
|
|
38248
38290
|
out[k] = resolveLambdaBindings(v, argName, arg);
|
|
@@ -38261,7 +38303,7 @@ function getSlotContentRenderer2() {
|
|
|
38261
38303
|
function makeLambdaFn(argName, lambdaBody, callerKey) {
|
|
38262
38304
|
return (item, index) => {
|
|
38263
38305
|
const resolvedBody = resolveLambdaBindings(lambdaBody, argName, item);
|
|
38264
|
-
if (resolvedBody === null || typeof resolvedBody !== "object" || Array.isArray(resolvedBody)) {
|
|
38306
|
+
if (resolvedBody === null || typeof resolvedBody !== "object" || Array.isArray(resolvedBody) || typeof resolvedBody === "function" || React113__default.isValidElement(resolvedBody) || resolvedBody instanceof Date) {
|
|
38265
38307
|
return null;
|
|
38266
38308
|
}
|
|
38267
38309
|
const record = resolvedBody;
|
|
@@ -38269,12 +38311,14 @@ function makeLambdaFn(argName, lambdaBody, callerKey) {
|
|
|
38269
38311
|
return null;
|
|
38270
38312
|
}
|
|
38271
38313
|
const SlotContentRenderer2 = getSlotContentRenderer2();
|
|
38314
|
+
const childProps = {};
|
|
38315
|
+
for (const [k, v] of Object.entries(record)) {
|
|
38316
|
+
if (k !== "type") childProps[k] = v;
|
|
38317
|
+
}
|
|
38272
38318
|
const childContent = {
|
|
38273
38319
|
id: `lambda-${callerKey}-${index}`,
|
|
38274
38320
|
pattern: record.type,
|
|
38275
|
-
props:
|
|
38276
|
-
Object.entries(record).filter(([k]) => k !== "type")
|
|
38277
|
-
),
|
|
38321
|
+
props: childProps,
|
|
38278
38322
|
priority: 0
|
|
38279
38323
|
};
|
|
38280
38324
|
return React113__default.createElement(SlotContentRenderer2, { content: childContent });
|
|
@@ -38287,15 +38331,16 @@ function convertNode(node, callerKey) {
|
|
|
38287
38331
|
const [, argName, body] = node;
|
|
38288
38332
|
return makeLambdaFn(argName, body, callerKey);
|
|
38289
38333
|
}
|
|
38334
|
+
const arr = node;
|
|
38290
38335
|
let anyChanged = false;
|
|
38291
|
-
const mapped =
|
|
38336
|
+
const mapped = arr.map((item, i) => {
|
|
38292
38337
|
const next = convertNode(item, `${callerKey}[${i}]`);
|
|
38293
38338
|
if (next !== item) anyChanged = true;
|
|
38294
38339
|
return next;
|
|
38295
38340
|
});
|
|
38296
38341
|
return anyChanged ? mapped : node;
|
|
38297
38342
|
}
|
|
38298
|
-
if (typeof node === "object") {
|
|
38343
|
+
if (typeof node === "object" && !React113__default.isValidElement(node) && !(node instanceof Date)) {
|
|
38299
38344
|
return convertObjectProps(node);
|
|
38300
38345
|
}
|
|
38301
38346
|
return node;
|
|
@@ -39486,6 +39531,7 @@ function prepareSchemaForPreview(input) {
|
|
|
39486
39531
|
// runtime/OrbPreview.tsx
|
|
39487
39532
|
init_logger();
|
|
39488
39533
|
var xOrbitalLog2 = createLogger("almadar:runtime:cross-orbital");
|
|
39534
|
+
var navLog = createLogger("almadar:runtime:navigation");
|
|
39489
39535
|
function normalizeChild(child) {
|
|
39490
39536
|
if (typeof child === "string") return child;
|
|
39491
39537
|
if (child === null || typeof child !== "object" || Array.isArray(child)) {
|
|
@@ -39561,6 +39607,19 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
|
|
|
39561
39607
|
}, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, embeddedTraits]);
|
|
39562
39608
|
const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, traitConfigsByName, orbitalsByTrait, embeddedTraits } : { navigate: onNavigate, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits };
|
|
39563
39609
|
const { sendEvent } = useTraitStateMachine(traits2, uiSlots, opts);
|
|
39610
|
+
const prevTraitNamesRef = useRef("");
|
|
39611
|
+
useEffect(() => {
|
|
39612
|
+
const traitNames = traits2.map((b) => b.trait?.name ?? "").filter(Boolean).sort().join(",");
|
|
39613
|
+
if (prevTraitNamesRef.current && prevTraitNamesRef.current !== traitNames) {
|
|
39614
|
+
navLog.info("page:trait-set-changed", {
|
|
39615
|
+
from: prevTraitNamesRef.current,
|
|
39616
|
+
to: traitNames,
|
|
39617
|
+
action: "clearAll-slots"
|
|
39618
|
+
});
|
|
39619
|
+
uiSlots.clearAll();
|
|
39620
|
+
}
|
|
39621
|
+
prevTraitNamesRef.current = traitNames;
|
|
39622
|
+
}, [traits2, uiSlots]);
|
|
39564
39623
|
const initSentRef = useRef(false);
|
|
39565
39624
|
useEffect(() => {
|
|
39566
39625
|
if (!orbitalNames?.length) {
|
|
@@ -39575,6 +39634,10 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
|
|
|
39575
39634
|
}, 5e3);
|
|
39576
39635
|
return () => clearTimeout(fallback);
|
|
39577
39636
|
}, [traits2, orbitalNames, sendEvent, onLocalFallback]);
|
|
39637
|
+
const orbitalsKey = (orbitalNames ?? []).slice().sort().join(",");
|
|
39638
|
+
useEffect(() => {
|
|
39639
|
+
initSentRef.current = false;
|
|
39640
|
+
}, [orbitalsKey]);
|
|
39578
39641
|
useEffect(() => {
|
|
39579
39642
|
if (!bridge.connected || !orbitalNames?.length || initSentRef.current) return;
|
|
39580
39643
|
initSentRef.current = true;
|
|
@@ -39815,8 +39878,19 @@ function OrbPreview({
|
|
|
39815
39878
|
}, [initialPageName, currentPage]);
|
|
39816
39879
|
const handleNavigate = useCallback((path) => {
|
|
39817
39880
|
const match = pages.find(({ page }) => page.path === path);
|
|
39881
|
+
navLog.info("handleNavigate", {
|
|
39882
|
+
path,
|
|
39883
|
+
matched: match?.page.name ?? null,
|
|
39884
|
+
availablePaths: pages.map((p2) => p2.page.path)
|
|
39885
|
+
});
|
|
39818
39886
|
if (match) {
|
|
39819
39887
|
setCurrentPage(match.page.name);
|
|
39888
|
+
if (typeof window !== "undefined") {
|
|
39889
|
+
const url = new URL(window.location.href);
|
|
39890
|
+
url.searchParams.set("page", path);
|
|
39891
|
+
window.history.pushState({}, "", url.toString());
|
|
39892
|
+
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
39893
|
+
}
|
|
39820
39894
|
}
|
|
39821
39895
|
}, [pages]);
|
|
39822
39896
|
if (!parseResult.ok) {
|
|
@@ -39828,18 +39902,30 @@ function OrbPreview({
|
|
|
39828
39902
|
const containerRef = useRef(null);
|
|
39829
39903
|
useEffect(() => {
|
|
39830
39904
|
const el = containerRef.current;
|
|
39831
|
-
if (!el
|
|
39905
|
+
if (!el) return;
|
|
39906
|
+
if (pages.length <= 1) {
|
|
39907
|
+
navLog.info("interceptor:skipped", { reason: "single-page schema", pageCount: pages.length });
|
|
39908
|
+
return;
|
|
39909
|
+
}
|
|
39832
39910
|
const handler = (e) => {
|
|
39833
39911
|
const anchor = e.target.closest("a");
|
|
39834
39912
|
if (!anchor) return;
|
|
39835
39913
|
const href = anchor.getAttribute("href") ?? anchor.getAttribute("to") ?? "";
|
|
39836
|
-
|
|
39914
|
+
navLog.info("click:intercepted", {
|
|
39915
|
+
href,
|
|
39916
|
+
anchorText: anchor.textContent?.trim().slice(0, 40)
|
|
39917
|
+
});
|
|
39918
|
+
if (!href || href.startsWith("http") || href.startsWith("mailto:") || href.startsWith("#")) {
|
|
39919
|
+
navLog.info("click:skipped", { href, reason: "external/empty/hash" });
|
|
39920
|
+
return;
|
|
39921
|
+
}
|
|
39837
39922
|
e.preventDefault();
|
|
39838
39923
|
e.stopPropagation();
|
|
39839
39924
|
e.stopImmediatePropagation();
|
|
39840
39925
|
handleNavigate(href);
|
|
39841
39926
|
};
|
|
39842
39927
|
el.addEventListener("click", handler, true);
|
|
39928
|
+
navLog.info("interceptor:installed", { pageCount: pages.length, paths: pages.map((p2) => p2.page.path) });
|
|
39843
39929
|
return () => el.removeEventListener("click", handler, true);
|
|
39844
39930
|
}, [pages, handleNavigate]);
|
|
39845
39931
|
return /* @__PURE__ */ jsxs(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@almadar/ui",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.25.0",
|
|
4
4
|
"description": "React UI components, hooks, and providers for Almadar",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/components/index.js",
|
|
@@ -118,7 +118,7 @@
|
|
|
118
118
|
"access": "public"
|
|
119
119
|
},
|
|
120
120
|
"dependencies": {
|
|
121
|
-
"@almadar/core": "
|
|
121
|
+
"@almadar/core": ">=7.12.0",
|
|
122
122
|
"@almadar/evaluator": ">=2.9.2",
|
|
123
123
|
"@almadar/patterns": "^2.20.2",
|
|
124
124
|
"@almadar/runtime": "^6.0.0",
|