@almadar/ui 2.29.0 → 2.31.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/components/index.cjs +94 -29
- package/dist/components/index.js +94 -29
- package/dist/providers/EntityStoreProvider.d.ts +2 -0
- package/dist/runtime/ServerBridge.d.ts +2 -0
- package/dist/runtime/createClientEffectHandlers.d.ts +0 -1
- package/dist/runtime/index.cjs +78 -50
- package/dist/runtime/index.d.ts +0 -1
- package/dist/runtime/index.js +81 -52
- package/package.json +1 -1
- package/dist/runtime/enrichFromResponse.d.ts +0 -21
|
@@ -6059,43 +6059,43 @@ function useQuerySingleton(query) {
|
|
|
6059
6059
|
if (!query) {
|
|
6060
6060
|
return null;
|
|
6061
6061
|
}
|
|
6062
|
-
const
|
|
6062
|
+
const store2 = React91.useMemo(() => getOrCreateStore(query), [query]);
|
|
6063
6063
|
React91.useMemo(() => {
|
|
6064
6064
|
const listener = () => forceUpdate({});
|
|
6065
|
-
|
|
6065
|
+
store2.listeners.add(listener);
|
|
6066
6066
|
return () => {
|
|
6067
|
-
|
|
6067
|
+
store2.listeners.delete(listener);
|
|
6068
6068
|
};
|
|
6069
|
-
}, [
|
|
6069
|
+
}, [store2]);
|
|
6070
6070
|
const notifyListeners = React91.useCallback(() => {
|
|
6071
|
-
|
|
6072
|
-
}, [
|
|
6071
|
+
store2.listeners.forEach((listener) => listener());
|
|
6072
|
+
}, [store2]);
|
|
6073
6073
|
const setSearch = React91.useCallback((value) => {
|
|
6074
|
-
|
|
6074
|
+
store2.search = value;
|
|
6075
6075
|
notifyListeners();
|
|
6076
|
-
}, [
|
|
6076
|
+
}, [store2, notifyListeners]);
|
|
6077
6077
|
const setFilter = React91.useCallback((key, value) => {
|
|
6078
|
-
|
|
6078
|
+
store2.filters = { ...store2.filters, [key]: value };
|
|
6079
6079
|
notifyListeners();
|
|
6080
|
-
}, [
|
|
6080
|
+
}, [store2, notifyListeners]);
|
|
6081
6081
|
const clearFilters = React91.useCallback(() => {
|
|
6082
|
-
|
|
6083
|
-
|
|
6082
|
+
store2.filters = {};
|
|
6083
|
+
store2.search = "";
|
|
6084
6084
|
notifyListeners();
|
|
6085
|
-
}, [
|
|
6085
|
+
}, [store2, notifyListeners]);
|
|
6086
6086
|
const setSort = React91.useCallback((field, direction) => {
|
|
6087
|
-
|
|
6088
|
-
|
|
6087
|
+
store2.sortField = field;
|
|
6088
|
+
store2.sortDirection = direction;
|
|
6089
6089
|
notifyListeners();
|
|
6090
|
-
}, [
|
|
6090
|
+
}, [store2, notifyListeners]);
|
|
6091
6091
|
return {
|
|
6092
|
-
search:
|
|
6092
|
+
search: store2.search,
|
|
6093
6093
|
setSearch,
|
|
6094
|
-
filters:
|
|
6094
|
+
filters: store2.filters,
|
|
6095
6095
|
setFilter,
|
|
6096
6096
|
clearFilters,
|
|
6097
|
-
sortField:
|
|
6098
|
-
sortDirection:
|
|
6097
|
+
sortField: store2.sortField,
|
|
6098
|
+
sortDirection: store2.sortDirection,
|
|
6099
6099
|
setSort
|
|
6100
6100
|
};
|
|
6101
6101
|
}
|
|
@@ -27493,7 +27493,7 @@ function SequencerBoard({
|
|
|
27493
27493
|
setPlayState("playing");
|
|
27494
27494
|
setCurrentStep(0);
|
|
27495
27495
|
let step = 0;
|
|
27496
|
-
const
|
|
27496
|
+
const advance2 = () => {
|
|
27497
27497
|
step++;
|
|
27498
27498
|
if (step >= entity.maxSlots) {
|
|
27499
27499
|
const playerSeq = slots.map((s) => s?.id);
|
|
@@ -27524,10 +27524,10 @@ function SequencerBoard({
|
|
|
27524
27524
|
}
|
|
27525
27525
|
} else {
|
|
27526
27526
|
setCurrentStep(step);
|
|
27527
|
-
timerRef.current = setTimeout(
|
|
27527
|
+
timerRef.current = setTimeout(advance2, stepDurationMs);
|
|
27528
27528
|
}
|
|
27529
27529
|
};
|
|
27530
|
-
timerRef.current = setTimeout(
|
|
27530
|
+
timerRef.current = setTimeout(advance2, stepDurationMs);
|
|
27531
27531
|
}, [canPlay, slots, entity.maxSlots, entity.solutions, stepDurationMs, playEvent, completeEvent, emit]);
|
|
27532
27532
|
const machine = {
|
|
27533
27533
|
name: entity.title,
|
|
@@ -29636,6 +29636,55 @@ function calculateDamage(attack, defense, isDefending = false, criticalChance =
|
|
|
29636
29636
|
function generateCombatMessage(event) {
|
|
29637
29637
|
return event.message;
|
|
29638
29638
|
}
|
|
29639
|
+
var store = /* @__PURE__ */ new Map();
|
|
29640
|
+
var storeListeners = /* @__PURE__ */ new Set();
|
|
29641
|
+
var watchCallbacks = /* @__PURE__ */ new Map();
|
|
29642
|
+
function advance(entityType, data) {
|
|
29643
|
+
const prev = store.get(entityType);
|
|
29644
|
+
const oldData = prev?.data ?? [];
|
|
29645
|
+
store.set(entityType, { data, version: (prev?.version ?? 0) + 1 });
|
|
29646
|
+
for (const listener of storeListeners) {
|
|
29647
|
+
listener();
|
|
29648
|
+
}
|
|
29649
|
+
const cbs = watchCallbacks.get(entityType);
|
|
29650
|
+
if (cbs) {
|
|
29651
|
+
for (const cb of cbs) {
|
|
29652
|
+
try {
|
|
29653
|
+
cb(oldData, data);
|
|
29654
|
+
} catch {
|
|
29655
|
+
}
|
|
29656
|
+
}
|
|
29657
|
+
}
|
|
29658
|
+
}
|
|
29659
|
+
function getSnapshot2(entityType) {
|
|
29660
|
+
return store.get(entityType)?.data ?? [];
|
|
29661
|
+
}
|
|
29662
|
+
function getVersion(entityType) {
|
|
29663
|
+
return store.get(entityType)?.version ?? 0;
|
|
29664
|
+
}
|
|
29665
|
+
function subscribeToStore(listener) {
|
|
29666
|
+
storeListeners.add(listener);
|
|
29667
|
+
return () => {
|
|
29668
|
+
storeListeners.delete(listener);
|
|
29669
|
+
};
|
|
29670
|
+
}
|
|
29671
|
+
function useEntityRef(entityType) {
|
|
29672
|
+
const versionRef = React91.useRef(0);
|
|
29673
|
+
const dataRef = React91.useRef([]);
|
|
29674
|
+
const getSnapshotStable = React91__namespace.default.useCallback(() => {
|
|
29675
|
+
const currentVersion = getVersion(entityType);
|
|
29676
|
+
if (currentVersion !== versionRef.current) {
|
|
29677
|
+
versionRef.current = currentVersion;
|
|
29678
|
+
dataRef.current = getSnapshot2(entityType);
|
|
29679
|
+
}
|
|
29680
|
+
return dataRef.current;
|
|
29681
|
+
}, [entityType]);
|
|
29682
|
+
return React91.useSyncExternalStore(subscribeToStore, getSnapshotStable, () => []);
|
|
29683
|
+
}
|
|
29684
|
+
React91.createContext({
|
|
29685
|
+
advance,
|
|
29686
|
+
getSnapshot: getSnapshot2
|
|
29687
|
+
});
|
|
29639
29688
|
var ClientEffectConfigContext = React91.createContext(null);
|
|
29640
29689
|
ClientEffectConfigContext.Provider;
|
|
29641
29690
|
|
|
@@ -35036,6 +35085,9 @@ function SlotContentRenderer({
|
|
|
35036
35085
|
content,
|
|
35037
35086
|
onDismiss
|
|
35038
35087
|
}) {
|
|
35088
|
+
const entityProp = content.props.entity;
|
|
35089
|
+
const entityType = typeof entityProp === "string" ? entityProp : "";
|
|
35090
|
+
const storeData = useEntityRef(entityType);
|
|
35039
35091
|
const PatternComponent = getComponentForPattern(content.pattern);
|
|
35040
35092
|
if (PatternComponent) {
|
|
35041
35093
|
const childrenConfig = content.props.children;
|
|
@@ -35043,13 +35095,26 @@ function SlotContentRenderer({
|
|
|
35043
35095
|
const renderedChildren = hasChildren ? renderPatternChildren(childrenConfig, onDismiss, content.id) : void 0;
|
|
35044
35096
|
const { children: _childrenConfig, ...restProps } = content.props;
|
|
35045
35097
|
const renderedProps = renderPatternProps(restProps, onDismiss);
|
|
35098
|
+
let finalProps;
|
|
35099
|
+
if (entityType) {
|
|
35100
|
+
finalProps = { ...renderedProps, entity: storeData };
|
|
35101
|
+
if (!finalProps.fields && !finalProps.columns && storeData.length > 0) {
|
|
35102
|
+
const sample = storeData[0];
|
|
35103
|
+
if (sample && typeof sample === "object") {
|
|
35104
|
+
const keys = Object.keys(sample).filter((k) => k !== "id" && k !== "_id");
|
|
35105
|
+
finalProps.fields = keys.map((k, i) => ({ name: k, variant: i === 0 ? "h4" : "body" }));
|
|
35106
|
+
}
|
|
35107
|
+
}
|
|
35108
|
+
} else {
|
|
35109
|
+
finalProps = renderedProps;
|
|
35110
|
+
}
|
|
35046
35111
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
35047
35112
|
Box,
|
|
35048
35113
|
{
|
|
35049
35114
|
className: "slot-content",
|
|
35050
35115
|
"data-pattern": content.pattern,
|
|
35051
35116
|
"data-id": content.id,
|
|
35052
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(PatternComponent, { ...
|
|
35117
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(PatternComponent, { ...finalProps, children: renderedChildren })
|
|
35053
35118
|
}
|
|
35054
35119
|
);
|
|
35055
35120
|
}
|
|
@@ -37604,13 +37669,13 @@ function clearEntities() {
|
|
|
37604
37669
|
entities = /* @__PURE__ */ new Map();
|
|
37605
37670
|
notify();
|
|
37606
37671
|
}
|
|
37607
|
-
function
|
|
37672
|
+
function getSnapshot3() {
|
|
37608
37673
|
return entities;
|
|
37609
37674
|
}
|
|
37610
37675
|
|
|
37611
37676
|
// hooks/useEntities.ts
|
|
37612
37677
|
function useEntities() {
|
|
37613
|
-
const entities2 = React91.useSyncExternalStore(subscribe,
|
|
37678
|
+
const entities2 = React91.useSyncExternalStore(subscribe, getSnapshot3, getSnapshot3);
|
|
37614
37679
|
return {
|
|
37615
37680
|
entities: entities2,
|
|
37616
37681
|
getEntity,
|
|
@@ -37625,15 +37690,15 @@ function useEntities() {
|
|
|
37625
37690
|
};
|
|
37626
37691
|
}
|
|
37627
37692
|
function useEntity2(id) {
|
|
37628
|
-
const entities2 = React91.useSyncExternalStore(subscribe,
|
|
37693
|
+
const entities2 = React91.useSyncExternalStore(subscribe, getSnapshot3, getSnapshot3);
|
|
37629
37694
|
return entities2.get(id);
|
|
37630
37695
|
}
|
|
37631
37696
|
function useEntitiesByType(type) {
|
|
37632
|
-
const entities2 = React91.useSyncExternalStore(subscribe,
|
|
37697
|
+
const entities2 = React91.useSyncExternalStore(subscribe, getSnapshot3, getSnapshot3);
|
|
37633
37698
|
return [...entities2.values()].filter((e) => e.type === type);
|
|
37634
37699
|
}
|
|
37635
37700
|
function useSingletonEntity(type) {
|
|
37636
|
-
const entities2 = React91.useSyncExternalStore(subscribe,
|
|
37701
|
+
const entities2 = React91.useSyncExternalStore(subscribe, getSnapshot3, getSnapshot3);
|
|
37637
37702
|
return [...entities2.values()].find((e) => e.type === type);
|
|
37638
37703
|
}
|
|
37639
37704
|
function usePlayer() {
|
package/dist/components/index.js
CHANGED
|
@@ -6029,43 +6029,43 @@ function useQuerySingleton(query) {
|
|
|
6029
6029
|
if (!query) {
|
|
6030
6030
|
return null;
|
|
6031
6031
|
}
|
|
6032
|
-
const
|
|
6032
|
+
const store2 = useMemo(() => getOrCreateStore(query), [query]);
|
|
6033
6033
|
useMemo(() => {
|
|
6034
6034
|
const listener = () => forceUpdate({});
|
|
6035
|
-
|
|
6035
|
+
store2.listeners.add(listener);
|
|
6036
6036
|
return () => {
|
|
6037
|
-
|
|
6037
|
+
store2.listeners.delete(listener);
|
|
6038
6038
|
};
|
|
6039
|
-
}, [
|
|
6039
|
+
}, [store2]);
|
|
6040
6040
|
const notifyListeners = useCallback(() => {
|
|
6041
|
-
|
|
6042
|
-
}, [
|
|
6041
|
+
store2.listeners.forEach((listener) => listener());
|
|
6042
|
+
}, [store2]);
|
|
6043
6043
|
const setSearch = useCallback((value) => {
|
|
6044
|
-
|
|
6044
|
+
store2.search = value;
|
|
6045
6045
|
notifyListeners();
|
|
6046
|
-
}, [
|
|
6046
|
+
}, [store2, notifyListeners]);
|
|
6047
6047
|
const setFilter = useCallback((key, value) => {
|
|
6048
|
-
|
|
6048
|
+
store2.filters = { ...store2.filters, [key]: value };
|
|
6049
6049
|
notifyListeners();
|
|
6050
|
-
}, [
|
|
6050
|
+
}, [store2, notifyListeners]);
|
|
6051
6051
|
const clearFilters = useCallback(() => {
|
|
6052
|
-
|
|
6053
|
-
|
|
6052
|
+
store2.filters = {};
|
|
6053
|
+
store2.search = "";
|
|
6054
6054
|
notifyListeners();
|
|
6055
|
-
}, [
|
|
6055
|
+
}, [store2, notifyListeners]);
|
|
6056
6056
|
const setSort = useCallback((field, direction) => {
|
|
6057
|
-
|
|
6058
|
-
|
|
6057
|
+
store2.sortField = field;
|
|
6058
|
+
store2.sortDirection = direction;
|
|
6059
6059
|
notifyListeners();
|
|
6060
|
-
}, [
|
|
6060
|
+
}, [store2, notifyListeners]);
|
|
6061
6061
|
return {
|
|
6062
|
-
search:
|
|
6062
|
+
search: store2.search,
|
|
6063
6063
|
setSearch,
|
|
6064
|
-
filters:
|
|
6064
|
+
filters: store2.filters,
|
|
6065
6065
|
setFilter,
|
|
6066
6066
|
clearFilters,
|
|
6067
|
-
sortField:
|
|
6068
|
-
sortDirection:
|
|
6067
|
+
sortField: store2.sortField,
|
|
6068
|
+
sortDirection: store2.sortDirection,
|
|
6069
6069
|
setSort
|
|
6070
6070
|
};
|
|
6071
6071
|
}
|
|
@@ -27463,7 +27463,7 @@ function SequencerBoard({
|
|
|
27463
27463
|
setPlayState("playing");
|
|
27464
27464
|
setCurrentStep(0);
|
|
27465
27465
|
let step = 0;
|
|
27466
|
-
const
|
|
27466
|
+
const advance2 = () => {
|
|
27467
27467
|
step++;
|
|
27468
27468
|
if (step >= entity.maxSlots) {
|
|
27469
27469
|
const playerSeq = slots.map((s) => s?.id);
|
|
@@ -27494,10 +27494,10 @@ function SequencerBoard({
|
|
|
27494
27494
|
}
|
|
27495
27495
|
} else {
|
|
27496
27496
|
setCurrentStep(step);
|
|
27497
|
-
timerRef.current = setTimeout(
|
|
27497
|
+
timerRef.current = setTimeout(advance2, stepDurationMs);
|
|
27498
27498
|
}
|
|
27499
27499
|
};
|
|
27500
|
-
timerRef.current = setTimeout(
|
|
27500
|
+
timerRef.current = setTimeout(advance2, stepDurationMs);
|
|
27501
27501
|
}, [canPlay, slots, entity.maxSlots, entity.solutions, stepDurationMs, playEvent, completeEvent, emit]);
|
|
27502
27502
|
const machine = {
|
|
27503
27503
|
name: entity.title,
|
|
@@ -29606,6 +29606,55 @@ function calculateDamage(attack, defense, isDefending = false, criticalChance =
|
|
|
29606
29606
|
function generateCombatMessage(event) {
|
|
29607
29607
|
return event.message;
|
|
29608
29608
|
}
|
|
29609
|
+
var store = /* @__PURE__ */ new Map();
|
|
29610
|
+
var storeListeners = /* @__PURE__ */ new Set();
|
|
29611
|
+
var watchCallbacks = /* @__PURE__ */ new Map();
|
|
29612
|
+
function advance(entityType, data) {
|
|
29613
|
+
const prev = store.get(entityType);
|
|
29614
|
+
const oldData = prev?.data ?? [];
|
|
29615
|
+
store.set(entityType, { data, version: (prev?.version ?? 0) + 1 });
|
|
29616
|
+
for (const listener of storeListeners) {
|
|
29617
|
+
listener();
|
|
29618
|
+
}
|
|
29619
|
+
const cbs = watchCallbacks.get(entityType);
|
|
29620
|
+
if (cbs) {
|
|
29621
|
+
for (const cb of cbs) {
|
|
29622
|
+
try {
|
|
29623
|
+
cb(oldData, data);
|
|
29624
|
+
} catch {
|
|
29625
|
+
}
|
|
29626
|
+
}
|
|
29627
|
+
}
|
|
29628
|
+
}
|
|
29629
|
+
function getSnapshot2(entityType) {
|
|
29630
|
+
return store.get(entityType)?.data ?? [];
|
|
29631
|
+
}
|
|
29632
|
+
function getVersion(entityType) {
|
|
29633
|
+
return store.get(entityType)?.version ?? 0;
|
|
29634
|
+
}
|
|
29635
|
+
function subscribeToStore(listener) {
|
|
29636
|
+
storeListeners.add(listener);
|
|
29637
|
+
return () => {
|
|
29638
|
+
storeListeners.delete(listener);
|
|
29639
|
+
};
|
|
29640
|
+
}
|
|
29641
|
+
function useEntityRef(entityType) {
|
|
29642
|
+
const versionRef = useRef(0);
|
|
29643
|
+
const dataRef = useRef([]);
|
|
29644
|
+
const getSnapshotStable = React91__default.useCallback(() => {
|
|
29645
|
+
const currentVersion = getVersion(entityType);
|
|
29646
|
+
if (currentVersion !== versionRef.current) {
|
|
29647
|
+
versionRef.current = currentVersion;
|
|
29648
|
+
dataRef.current = getSnapshot2(entityType);
|
|
29649
|
+
}
|
|
29650
|
+
return dataRef.current;
|
|
29651
|
+
}, [entityType]);
|
|
29652
|
+
return useSyncExternalStore(subscribeToStore, getSnapshotStable, () => []);
|
|
29653
|
+
}
|
|
29654
|
+
createContext({
|
|
29655
|
+
advance,
|
|
29656
|
+
getSnapshot: getSnapshot2
|
|
29657
|
+
});
|
|
29609
29658
|
var ClientEffectConfigContext = createContext(null);
|
|
29610
29659
|
ClientEffectConfigContext.Provider;
|
|
29611
29660
|
|
|
@@ -35006,6 +35055,9 @@ function SlotContentRenderer({
|
|
|
35006
35055
|
content,
|
|
35007
35056
|
onDismiss
|
|
35008
35057
|
}) {
|
|
35058
|
+
const entityProp = content.props.entity;
|
|
35059
|
+
const entityType = typeof entityProp === "string" ? entityProp : "";
|
|
35060
|
+
const storeData = useEntityRef(entityType);
|
|
35009
35061
|
const PatternComponent = getComponentForPattern(content.pattern);
|
|
35010
35062
|
if (PatternComponent) {
|
|
35011
35063
|
const childrenConfig = content.props.children;
|
|
@@ -35013,13 +35065,26 @@ function SlotContentRenderer({
|
|
|
35013
35065
|
const renderedChildren = hasChildren ? renderPatternChildren(childrenConfig, onDismiss, content.id) : void 0;
|
|
35014
35066
|
const { children: _childrenConfig, ...restProps } = content.props;
|
|
35015
35067
|
const renderedProps = renderPatternProps(restProps, onDismiss);
|
|
35068
|
+
let finalProps;
|
|
35069
|
+
if (entityType) {
|
|
35070
|
+
finalProps = { ...renderedProps, entity: storeData };
|
|
35071
|
+
if (!finalProps.fields && !finalProps.columns && storeData.length > 0) {
|
|
35072
|
+
const sample = storeData[0];
|
|
35073
|
+
if (sample && typeof sample === "object") {
|
|
35074
|
+
const keys = Object.keys(sample).filter((k) => k !== "id" && k !== "_id");
|
|
35075
|
+
finalProps.fields = keys.map((k, i) => ({ name: k, variant: i === 0 ? "h4" : "body" }));
|
|
35076
|
+
}
|
|
35077
|
+
}
|
|
35078
|
+
} else {
|
|
35079
|
+
finalProps = renderedProps;
|
|
35080
|
+
}
|
|
35016
35081
|
return /* @__PURE__ */ jsx(
|
|
35017
35082
|
Box,
|
|
35018
35083
|
{
|
|
35019
35084
|
className: "slot-content",
|
|
35020
35085
|
"data-pattern": content.pattern,
|
|
35021
35086
|
"data-id": content.id,
|
|
35022
|
-
children: /* @__PURE__ */ jsx(PatternComponent, { ...
|
|
35087
|
+
children: /* @__PURE__ */ jsx(PatternComponent, { ...finalProps, children: renderedChildren })
|
|
35023
35088
|
}
|
|
35024
35089
|
);
|
|
35025
35090
|
}
|
|
@@ -37574,13 +37639,13 @@ function clearEntities() {
|
|
|
37574
37639
|
entities = /* @__PURE__ */ new Map();
|
|
37575
37640
|
notify();
|
|
37576
37641
|
}
|
|
37577
|
-
function
|
|
37642
|
+
function getSnapshot3() {
|
|
37578
37643
|
return entities;
|
|
37579
37644
|
}
|
|
37580
37645
|
|
|
37581
37646
|
// hooks/useEntities.ts
|
|
37582
37647
|
function useEntities() {
|
|
37583
|
-
const entities2 = useSyncExternalStore(subscribe,
|
|
37648
|
+
const entities2 = useSyncExternalStore(subscribe, getSnapshot3, getSnapshot3);
|
|
37584
37649
|
return {
|
|
37585
37650
|
entities: entities2,
|
|
37586
37651
|
getEntity,
|
|
@@ -37595,15 +37660,15 @@ function useEntities() {
|
|
|
37595
37660
|
};
|
|
37596
37661
|
}
|
|
37597
37662
|
function useEntity2(id) {
|
|
37598
|
-
const entities2 = useSyncExternalStore(subscribe,
|
|
37663
|
+
const entities2 = useSyncExternalStore(subscribe, getSnapshot3, getSnapshot3);
|
|
37599
37664
|
return entities2.get(id);
|
|
37600
37665
|
}
|
|
37601
37666
|
function useEntitiesByType(type) {
|
|
37602
|
-
const entities2 = useSyncExternalStore(subscribe,
|
|
37667
|
+
const entities2 = useSyncExternalStore(subscribe, getSnapshot3, getSnapshot3);
|
|
37603
37668
|
return [...entities2.values()].filter((e) => e.type === type);
|
|
37604
37669
|
}
|
|
37605
37670
|
function useSingletonEntity(type) {
|
|
37606
|
-
const entities2 = useSyncExternalStore(subscribe,
|
|
37671
|
+
const entities2 = useSyncExternalStore(subscribe, getSnapshot3, getSnapshot3);
|
|
37607
37672
|
return [...entities2.values()].find((e) => e.type === type);
|
|
37608
37673
|
}
|
|
37609
37674
|
function usePlayer() {
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
* @packageDocumentation
|
|
13
13
|
*/
|
|
14
14
|
import React, { type ReactNode } from 'react';
|
|
15
|
+
type StoreListener = () => void;
|
|
15
16
|
type WatchCallback = (oldData: unknown[], newData: unknown[]) => void;
|
|
17
|
+
export declare function subscribeToStore(listener: StoreListener): () => void;
|
|
16
18
|
/**
|
|
17
19
|
* Subscribe to an entity type's data reactively.
|
|
18
20
|
* Re-renders only when the data for this specific entity type changes.
|
|
@@ -12,6 +12,8 @@ export interface ServerResponseMeta {
|
|
|
12
12
|
success: boolean;
|
|
13
13
|
clientEffects: number;
|
|
14
14
|
dataEntities: Record<string, number>;
|
|
15
|
+
/** Raw entity data from server response (for EntityStore advancement) */
|
|
16
|
+
data?: Record<string, unknown[]>;
|
|
15
17
|
emittedEvents: string[];
|
|
16
18
|
error?: string;
|
|
17
19
|
}
|
|
@@ -18,6 +18,5 @@ export interface CreateClientEffectHandlersOptions {
|
|
|
18
18
|
slotSetter: SlotSetter;
|
|
19
19
|
navigate?: (path: string, params?: Record<string, unknown>) => void;
|
|
20
20
|
notify?: (message: string, type: 'success' | 'error' | 'warning' | 'info') => void;
|
|
21
|
-
enrichPattern?: (pattern: unknown) => unknown;
|
|
22
21
|
}
|
|
23
22
|
export declare function createClientEffectHandlers(options: CreateClientEffectHandlersOptions): EffectHandlers;
|
package/dist/runtime/index.cjs
CHANGED
|
@@ -685,7 +685,7 @@ typeof process !== "undefined" && process.env?.VITE_API_URL ? process.env.VITE_A
|
|
|
685
685
|
|
|
686
686
|
// runtime/createClientEffectHandlers.ts
|
|
687
687
|
function createClientEffectHandlers(options) {
|
|
688
|
-
const { eventBus, slotSetter, navigate, notify
|
|
688
|
+
const { eventBus, slotSetter, navigate, notify } = options;
|
|
689
689
|
return {
|
|
690
690
|
emit: (event, payload) => {
|
|
691
691
|
const prefixedEvent = event.startsWith("UI:") ? event : `UI:${event}`;
|
|
@@ -706,8 +706,7 @@ function createClientEffectHandlers(options) {
|
|
|
706
706
|
slotSetter.clearSlot(slot);
|
|
707
707
|
return;
|
|
708
708
|
}
|
|
709
|
-
|
|
710
|
-
slotSetter.addPattern(slot, enriched, props);
|
|
709
|
+
slotSetter.addPattern(slot, pattern, props);
|
|
711
710
|
},
|
|
712
711
|
navigate: navigate ?? ((path) => {
|
|
713
712
|
console.warn("[ClientEffectHandlers] No navigate handler, ignoring:", path);
|
|
@@ -2119,10 +2118,35 @@ function advance(entityType, data) {
|
|
|
2119
2118
|
function getSnapshot3(entityType) {
|
|
2120
2119
|
return store.get(entityType)?.data ?? [];
|
|
2121
2120
|
}
|
|
2121
|
+
function getVersion(entityType) {
|
|
2122
|
+
return store.get(entityType)?.version ?? 0;
|
|
2123
|
+
}
|
|
2124
|
+
function subscribeToStore(listener) {
|
|
2125
|
+
storeListeners.add(listener);
|
|
2126
|
+
return () => {
|
|
2127
|
+
storeListeners.delete(listener);
|
|
2128
|
+
};
|
|
2129
|
+
}
|
|
2130
|
+
function useEntityRef(entityType) {
|
|
2131
|
+
const versionRef = React118.useRef(0);
|
|
2132
|
+
const dataRef = React118.useRef([]);
|
|
2133
|
+
const getSnapshotStable = React118__namespace.default.useCallback(() => {
|
|
2134
|
+
const currentVersion = getVersion(entityType);
|
|
2135
|
+
if (currentVersion !== versionRef.current) {
|
|
2136
|
+
versionRef.current = currentVersion;
|
|
2137
|
+
dataRef.current = getSnapshot3(entityType);
|
|
2138
|
+
}
|
|
2139
|
+
return dataRef.current;
|
|
2140
|
+
}, [entityType]);
|
|
2141
|
+
return React118.useSyncExternalStore(subscribeToStore, getSnapshotStable, () => []);
|
|
2142
|
+
}
|
|
2122
2143
|
var EntityStoreContext = React118.createContext({
|
|
2123
2144
|
advance,
|
|
2124
2145
|
getSnapshot: getSnapshot3
|
|
2125
2146
|
});
|
|
2147
|
+
function useEntityStore() {
|
|
2148
|
+
return React118.useContext(EntityStoreContext);
|
|
2149
|
+
}
|
|
2126
2150
|
function EntityStoreProvider({ children }) {
|
|
2127
2151
|
return /* @__PURE__ */ jsxRuntime.jsx(EntityStoreContext.Provider, { value: { advance, getSnapshot: getSnapshot3 }, children });
|
|
2128
2152
|
}
|
|
@@ -32324,6 +32348,9 @@ function SlotContentRenderer({
|
|
|
32324
32348
|
content,
|
|
32325
32349
|
onDismiss
|
|
32326
32350
|
}) {
|
|
32351
|
+
const entityProp = content.props.entity;
|
|
32352
|
+
const entityType = typeof entityProp === "string" ? entityProp : "";
|
|
32353
|
+
const storeData = useEntityRef(entityType);
|
|
32327
32354
|
const PatternComponent = getComponentForPattern(content.pattern);
|
|
32328
32355
|
if (PatternComponent) {
|
|
32329
32356
|
const childrenConfig = content.props.children;
|
|
@@ -32331,13 +32358,26 @@ function SlotContentRenderer({
|
|
|
32331
32358
|
const renderedChildren = hasChildren ? renderPatternChildren(childrenConfig, onDismiss, content.id) : void 0;
|
|
32332
32359
|
const { children: _childrenConfig, ...restProps } = content.props;
|
|
32333
32360
|
const renderedProps = renderPatternProps(restProps, onDismiss);
|
|
32361
|
+
let finalProps;
|
|
32362
|
+
if (entityType) {
|
|
32363
|
+
finalProps = { ...renderedProps, entity: storeData };
|
|
32364
|
+
if (!finalProps.fields && !finalProps.columns && storeData.length > 0) {
|
|
32365
|
+
const sample = storeData[0];
|
|
32366
|
+
if (sample && typeof sample === "object") {
|
|
32367
|
+
const keys = Object.keys(sample).filter((k) => k !== "id" && k !== "_id");
|
|
32368
|
+
finalProps.fields = keys.map((k, i) => ({ name: k, variant: i === 0 ? "h4" : "body" }));
|
|
32369
|
+
}
|
|
32370
|
+
}
|
|
32371
|
+
} else {
|
|
32372
|
+
finalProps = renderedProps;
|
|
32373
|
+
}
|
|
32334
32374
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
32335
32375
|
Box,
|
|
32336
32376
|
{
|
|
32337
32377
|
className: "slot-content",
|
|
32338
32378
|
"data-pattern": content.pattern,
|
|
32339
32379
|
"data-id": content.id,
|
|
32340
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(PatternComponent, { ...
|
|
32380
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(PatternComponent, { ...finalProps, children: renderedChildren })
|
|
32341
32381
|
}
|
|
32342
32382
|
);
|
|
32343
32383
|
}
|
|
@@ -32620,41 +32660,6 @@ function OrbitalProvider({
|
|
|
32620
32660
|
);
|
|
32621
32661
|
}
|
|
32622
32662
|
OrbitalProvider.displayName = "OrbitalProvider";
|
|
32623
|
-
function enrichFromResponse(node, data) {
|
|
32624
|
-
if (!node || typeof node !== "object") return node ?? {};
|
|
32625
|
-
let enriched = node;
|
|
32626
|
-
if (Array.isArray(enriched.children)) {
|
|
32627
|
-
enriched = {
|
|
32628
|
-
...enriched,
|
|
32629
|
-
children: enriched.children.map(
|
|
32630
|
-
(child) => {
|
|
32631
|
-
if (!child || typeof child !== "object") return child;
|
|
32632
|
-
return enrichFromResponse(child, data);
|
|
32633
|
-
}
|
|
32634
|
-
)
|
|
32635
|
-
};
|
|
32636
|
-
}
|
|
32637
|
-
const nodeType = enriched.type;
|
|
32638
|
-
if (nodeType && patterns.isEntityAwarePattern(nodeType) && typeof enriched.entity === "string") {
|
|
32639
|
-
const entityName = enriched.entity;
|
|
32640
|
-
const records = data[entityName];
|
|
32641
|
-
if (records && records.length > 0) {
|
|
32642
|
-
enriched = { ...enriched, entity: records };
|
|
32643
|
-
if (!enriched.fields && !enriched.columns) {
|
|
32644
|
-
const sample = records[0];
|
|
32645
|
-
if (sample && typeof sample === "object") {
|
|
32646
|
-
const keys = Object.keys(sample).filter((k) => k !== "id" && k !== "_id");
|
|
32647
|
-
enriched = {
|
|
32648
|
-
...enriched,
|
|
32649
|
-
fields: keys.map((k, i) => ({ name: k, variant: i === 0 ? "h4" : "body" })),
|
|
32650
|
-
children: void 0
|
|
32651
|
-
};
|
|
32652
|
-
}
|
|
32653
|
-
}
|
|
32654
|
-
}
|
|
32655
|
-
}
|
|
32656
|
-
return enriched;
|
|
32657
|
-
}
|
|
32658
32663
|
var ServerBridgeContext = React118.createContext(null);
|
|
32659
32664
|
function useServerBridge() {
|
|
32660
32665
|
const ctx = React118.useContext(ServerBridgeContext);
|
|
@@ -32711,6 +32716,7 @@ function ServerBridgeProvider({
|
|
|
32711
32716
|
success: !!result.success,
|
|
32712
32717
|
clientEffects: result.clientEffects?.length ?? 0,
|
|
32713
32718
|
dataEntities,
|
|
32719
|
+
data: responseData,
|
|
32714
32720
|
emittedEvents: result.emittedEvents?.map((e) => e.event) ?? [],
|
|
32715
32721
|
error: result.error
|
|
32716
32722
|
};
|
|
@@ -32722,8 +32728,7 @@ function ServerBridgeProvider({
|
|
|
32722
32728
|
if (effectType === "render-ui") {
|
|
32723
32729
|
const slot = arr[1];
|
|
32724
32730
|
const pattern = arr[2];
|
|
32725
|
-
|
|
32726
|
-
effects.push({ type: "render-ui", slot, pattern: enriched });
|
|
32731
|
+
effects.push({ type: "render-ui", slot, pattern: pattern ?? void 0 });
|
|
32727
32732
|
} else if (effectType === "navigate") {
|
|
32728
32733
|
effects.push({ type: "navigate", route: arr[1], params: arr[2] });
|
|
32729
32734
|
} else if (effectType === "notify") {
|
|
@@ -32768,7 +32773,7 @@ function normalizeChild(child) {
|
|
|
32768
32773
|
props: { ...rest, ...normalizedChildren !== void 0 ? { children: normalizedChildren } : {} }
|
|
32769
32774
|
};
|
|
32770
32775
|
}
|
|
32771
|
-
function SlotBridge(
|
|
32776
|
+
function SlotBridge() {
|
|
32772
32777
|
const slots = useSlots();
|
|
32773
32778
|
const { render, clear } = context.useUISlots();
|
|
32774
32779
|
React118.useEffect(() => {
|
|
@@ -32778,10 +32783,7 @@ function SlotBridge({ mockData }) {
|
|
|
32778
32783
|
continue;
|
|
32779
32784
|
}
|
|
32780
32785
|
const entry = slotState.patterns[slotState.patterns.length - 1];
|
|
32781
|
-
|
|
32782
|
-
if (mockData && Object.keys(mockData).length > 0) {
|
|
32783
|
-
patternRecord = enrichFromResponse(patternRecord, mockData);
|
|
32784
|
-
}
|
|
32786
|
+
const patternRecord = entry.pattern;
|
|
32785
32787
|
const { type: patternType, children, ...inlineProps } = patternRecord;
|
|
32786
32788
|
const normalizedChildren = Array.isArray(children) ? children.map((c) => normalizeChild(c)) : children;
|
|
32787
32789
|
render({
|
|
@@ -32795,17 +32797,26 @@ function SlotBridge({ mockData }) {
|
|
|
32795
32797
|
sourceTrait: slotState.source?.trait
|
|
32796
32798
|
});
|
|
32797
32799
|
}
|
|
32798
|
-
}, [slots, render, clear
|
|
32800
|
+
}, [slots, render, clear]);
|
|
32799
32801
|
return null;
|
|
32800
32802
|
}
|
|
32801
32803
|
function TraitInitializer({ traits: traits2, orbitalNames, onNavigate }) {
|
|
32802
32804
|
const slotsActions = useSlotsActions();
|
|
32803
32805
|
const bridge = useServerBridge();
|
|
32806
|
+
const entityStore = useEntityStore();
|
|
32804
32807
|
const onEventProcessed = React118.useCallback(async (event, payload) => {
|
|
32805
32808
|
if (!bridge.connected || !orbitalNames?.length) return;
|
|
32806
32809
|
for (const name of orbitalNames) {
|
|
32807
32810
|
const { effects, meta } = await bridge.sendEvent(name, event, payload);
|
|
32808
32811
|
recordServerResponse(name, event, meta);
|
|
32812
|
+
const responseData = meta?.data;
|
|
32813
|
+
if (responseData) {
|
|
32814
|
+
for (const [entityType, records] of Object.entries(responseData)) {
|
|
32815
|
+
if (Array.isArray(records)) {
|
|
32816
|
+
entityStore.advance(entityType, records);
|
|
32817
|
+
}
|
|
32818
|
+
}
|
|
32819
|
+
}
|
|
32809
32820
|
for (const eff of effects) {
|
|
32810
32821
|
if (eff.type === "render-ui" && eff.slot && eff.pattern) {
|
|
32811
32822
|
slotsActions.setSlotPatterns(
|
|
@@ -32818,7 +32829,7 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate }) {
|
|
|
32818
32829
|
}
|
|
32819
32830
|
}
|
|
32820
32831
|
}
|
|
32821
|
-
}, [bridge.connected, bridge.sendEvent, orbitalNames, slotsActions, onNavigate]);
|
|
32832
|
+
}, [bridge.connected, bridge.sendEvent, orbitalNames, slotsActions, onNavigate, entityStore]);
|
|
32822
32833
|
const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate } : { navigate: onNavigate };
|
|
32823
32834
|
const { sendEvent } = useTraitStateMachine(traits2, slotsActions, opts);
|
|
32824
32835
|
const initSentRef = React118.useRef(false);
|
|
@@ -32857,6 +32868,14 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate }) {
|
|
|
32857
32868
|
effects: effectTraces,
|
|
32858
32869
|
timestamp: Date.now()
|
|
32859
32870
|
});
|
|
32871
|
+
const initResponseData = meta?.data;
|
|
32872
|
+
if (initResponseData) {
|
|
32873
|
+
for (const [entityType, records] of Object.entries(initResponseData)) {
|
|
32874
|
+
if (Array.isArray(records)) {
|
|
32875
|
+
entityStore.advance(entityType, records);
|
|
32876
|
+
}
|
|
32877
|
+
}
|
|
32878
|
+
}
|
|
32860
32879
|
for (const eff of effects) {
|
|
32861
32880
|
if (eff.type === "render-ui" && eff.slot && eff.pattern) {
|
|
32862
32881
|
slotsActions.setSlotPatterns(
|
|
@@ -32897,9 +32916,19 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate }) {
|
|
|
32897
32916
|
if (!orbitals) return [];
|
|
32898
32917
|
return orbitals.filter((o) => typeof o.name === "string").map((o) => o.name);
|
|
32899
32918
|
}, [schema]);
|
|
32919
|
+
const entityStore = useEntityStore();
|
|
32920
|
+
React118.useEffect(() => {
|
|
32921
|
+
if (!serverUrl && mockData) {
|
|
32922
|
+
for (const [entityType, records] of Object.entries(mockData)) {
|
|
32923
|
+
if (Array.isArray(records)) {
|
|
32924
|
+
entityStore.advance(entityType, records);
|
|
32925
|
+
}
|
|
32926
|
+
}
|
|
32927
|
+
}
|
|
32928
|
+
}, [mockData, serverUrl, entityStore]);
|
|
32900
32929
|
const inner = /* @__PURE__ */ jsxRuntime.jsx(VerificationProvider, { enabled: true, children: /* @__PURE__ */ jsxRuntime.jsx(SlotsProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(EntitySchemaProvider, { entities: Array.from(allEntities.values()), children: [
|
|
32901
32930
|
/* @__PURE__ */ jsxRuntime.jsx(TraitInitializer, { traits: allPageTraits, orbitalNames: serverUrl ? orbitalNames : void 0, onNavigate }),
|
|
32902
|
-
/* @__PURE__ */ jsxRuntime.jsx(SlotBridge, {
|
|
32931
|
+
/* @__PURE__ */ jsxRuntime.jsx(SlotBridge, {}),
|
|
32903
32932
|
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "min-h-full p-4", children: /* @__PURE__ */ jsxRuntime.jsx(UISlotRenderer, { includeHud: true, hudMode: "inline", includeFloating: true }) })
|
|
32904
32933
|
] }) }) });
|
|
32905
32934
|
if (serverUrl) {
|
|
@@ -32982,7 +33011,6 @@ exports.TraitContext = TraitContext;
|
|
|
32982
33011
|
exports.TraitProvider = TraitProvider;
|
|
32983
33012
|
exports.clearSchemaCache = clearSchemaCache;
|
|
32984
33013
|
exports.createClientEffectHandlers = createClientEffectHandlers;
|
|
32985
|
-
exports.enrichFromResponse = enrichFromResponse;
|
|
32986
33014
|
exports.useEntityDefinition = useEntityDefinition;
|
|
32987
33015
|
exports.useEntitySchema = useEntitySchema;
|
|
32988
33016
|
exports.useResolvedSchema = useResolvedSchema;
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -14,5 +14,4 @@ export { SlotsProvider, useSlots, useSlotContent, useSlotsActions, type SlotsSta
|
|
|
14
14
|
export { createClientEffectHandlers, type ClientEventBus, type SlotSetter, type CreateClientEffectHandlersOptions, } from './createClientEffectHandlers';
|
|
15
15
|
export { OrbPreview, type OrbPreviewProps } from './OrbPreview';
|
|
16
16
|
export { ServerBridgeProvider, useServerBridge, type ServerBridgeContextValue, type ServerClientEffect } from './ServerBridge';
|
|
17
|
-
export { enrichFromResponse } from './enrichFromResponse';
|
|
18
17
|
export type { ResolvedTraitBinding, ResolvedTrait, ResolvedEntity, ResolvedPage, ResolvedIR, } from './types';
|
package/dist/runtime/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React118 from 'react';
|
|
2
|
-
import React118__default, { createContext, useCallback, useState, useRef, useEffect, useLayoutEffect, lazy, useContext, useMemo, Suspense, useId } from 'react';
|
|
2
|
+
import React118__default, { createContext, useCallback, useState, useRef, useEffect, useLayoutEffect, lazy, useContext, useMemo, Suspense, useSyncExternalStore, useId } from 'react';
|
|
3
3
|
import { EventBusContext } from '@almadar/ui/providers';
|
|
4
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
import '@tanstack/react-query';
|
|
@@ -12,7 +12,7 @@ import { UISlotProvider, useUISlots } from '@almadar/ui/context';
|
|
|
12
12
|
import * as LucideIcons from 'lucide-react';
|
|
13
13
|
import { Loader2, ChevronDown, X, ArrowRight, TrendingDown, TrendingUp, Check, Copy, AlertCircle, AlertTriangle, Info, CheckCircle, ChevronLeft, ChevronRight, FileWarning, Upload, Circle, Clock, CheckCircle2, Sun, Moon, ArrowUp, ArrowDown, MoreVertical, Minus, Star, XCircle, Play, RotateCcw, Pause, SkipForward, Eraser, Search, HelpCircle, ChevronUp, ArrowLeft, Plus, Image as Image$1, ZoomIn, Package, Menu as Menu$1, ZoomOut, Filter, FileQuestion, Inbox, FileText, Download, Printer, Bug, Send, MoreHorizontal, Settings, Bell, LogOut, Trash2, Zap, Sword, Move, Heart, Shield, Code, WrapText, Wrench, List, Calendar, Pencil, Eye, User, Tag, DollarSign } from 'lucide-react';
|
|
14
14
|
import { evaluate, createMinimalContext } from '@almadar/evaluator';
|
|
15
|
-
import {
|
|
15
|
+
import { getComponentForPattern as getComponentForPattern$1 } from '@almadar/patterns';
|
|
16
16
|
import { MapContainer, TileLayer, Marker, Popup, useMap } from 'react-leaflet';
|
|
17
17
|
import L from 'leaflet';
|
|
18
18
|
import 'leaflet/dist/leaflet.css';
|
|
@@ -655,7 +655,7 @@ typeof process !== "undefined" && process.env?.VITE_API_URL ? process.env.VITE_A
|
|
|
655
655
|
|
|
656
656
|
// runtime/createClientEffectHandlers.ts
|
|
657
657
|
function createClientEffectHandlers(options) {
|
|
658
|
-
const { eventBus, slotSetter, navigate, notify
|
|
658
|
+
const { eventBus, slotSetter, navigate, notify } = options;
|
|
659
659
|
return {
|
|
660
660
|
emit: (event, payload) => {
|
|
661
661
|
const prefixedEvent = event.startsWith("UI:") ? event : `UI:${event}`;
|
|
@@ -676,8 +676,7 @@ function createClientEffectHandlers(options) {
|
|
|
676
676
|
slotSetter.clearSlot(slot);
|
|
677
677
|
return;
|
|
678
678
|
}
|
|
679
|
-
|
|
680
|
-
slotSetter.addPattern(slot, enriched, props);
|
|
679
|
+
slotSetter.addPattern(slot, pattern, props);
|
|
681
680
|
},
|
|
682
681
|
navigate: navigate ?? ((path) => {
|
|
683
682
|
console.warn("[ClientEffectHandlers] No navigate handler, ignoring:", path);
|
|
@@ -2089,10 +2088,35 @@ function advance(entityType, data) {
|
|
|
2089
2088
|
function getSnapshot3(entityType) {
|
|
2090
2089
|
return store.get(entityType)?.data ?? [];
|
|
2091
2090
|
}
|
|
2091
|
+
function getVersion(entityType) {
|
|
2092
|
+
return store.get(entityType)?.version ?? 0;
|
|
2093
|
+
}
|
|
2094
|
+
function subscribeToStore(listener) {
|
|
2095
|
+
storeListeners.add(listener);
|
|
2096
|
+
return () => {
|
|
2097
|
+
storeListeners.delete(listener);
|
|
2098
|
+
};
|
|
2099
|
+
}
|
|
2100
|
+
function useEntityRef(entityType) {
|
|
2101
|
+
const versionRef = useRef(0);
|
|
2102
|
+
const dataRef = useRef([]);
|
|
2103
|
+
const getSnapshotStable = React118__default.useCallback(() => {
|
|
2104
|
+
const currentVersion = getVersion(entityType);
|
|
2105
|
+
if (currentVersion !== versionRef.current) {
|
|
2106
|
+
versionRef.current = currentVersion;
|
|
2107
|
+
dataRef.current = getSnapshot3(entityType);
|
|
2108
|
+
}
|
|
2109
|
+
return dataRef.current;
|
|
2110
|
+
}, [entityType]);
|
|
2111
|
+
return useSyncExternalStore(subscribeToStore, getSnapshotStable, () => []);
|
|
2112
|
+
}
|
|
2092
2113
|
var EntityStoreContext = createContext({
|
|
2093
2114
|
advance,
|
|
2094
2115
|
getSnapshot: getSnapshot3
|
|
2095
2116
|
});
|
|
2117
|
+
function useEntityStore() {
|
|
2118
|
+
return useContext(EntityStoreContext);
|
|
2119
|
+
}
|
|
2096
2120
|
function EntityStoreProvider({ children }) {
|
|
2097
2121
|
return /* @__PURE__ */ jsx(EntityStoreContext.Provider, { value: { advance, getSnapshot: getSnapshot3 }, children });
|
|
2098
2122
|
}
|
|
@@ -32294,6 +32318,9 @@ function SlotContentRenderer({
|
|
|
32294
32318
|
content,
|
|
32295
32319
|
onDismiss
|
|
32296
32320
|
}) {
|
|
32321
|
+
const entityProp = content.props.entity;
|
|
32322
|
+
const entityType = typeof entityProp === "string" ? entityProp : "";
|
|
32323
|
+
const storeData = useEntityRef(entityType);
|
|
32297
32324
|
const PatternComponent = getComponentForPattern(content.pattern);
|
|
32298
32325
|
if (PatternComponent) {
|
|
32299
32326
|
const childrenConfig = content.props.children;
|
|
@@ -32301,13 +32328,26 @@ function SlotContentRenderer({
|
|
|
32301
32328
|
const renderedChildren = hasChildren ? renderPatternChildren(childrenConfig, onDismiss, content.id) : void 0;
|
|
32302
32329
|
const { children: _childrenConfig, ...restProps } = content.props;
|
|
32303
32330
|
const renderedProps = renderPatternProps(restProps, onDismiss);
|
|
32331
|
+
let finalProps;
|
|
32332
|
+
if (entityType) {
|
|
32333
|
+
finalProps = { ...renderedProps, entity: storeData };
|
|
32334
|
+
if (!finalProps.fields && !finalProps.columns && storeData.length > 0) {
|
|
32335
|
+
const sample = storeData[0];
|
|
32336
|
+
if (sample && typeof sample === "object") {
|
|
32337
|
+
const keys = Object.keys(sample).filter((k) => k !== "id" && k !== "_id");
|
|
32338
|
+
finalProps.fields = keys.map((k, i) => ({ name: k, variant: i === 0 ? "h4" : "body" }));
|
|
32339
|
+
}
|
|
32340
|
+
}
|
|
32341
|
+
} else {
|
|
32342
|
+
finalProps = renderedProps;
|
|
32343
|
+
}
|
|
32304
32344
|
return /* @__PURE__ */ jsx(
|
|
32305
32345
|
Box,
|
|
32306
32346
|
{
|
|
32307
32347
|
className: "slot-content",
|
|
32308
32348
|
"data-pattern": content.pattern,
|
|
32309
32349
|
"data-id": content.id,
|
|
32310
|
-
children: /* @__PURE__ */ jsx(PatternComponent, { ...
|
|
32350
|
+
children: /* @__PURE__ */ jsx(PatternComponent, { ...finalProps, children: renderedChildren })
|
|
32311
32351
|
}
|
|
32312
32352
|
);
|
|
32313
32353
|
}
|
|
@@ -32590,41 +32630,6 @@ function OrbitalProvider({
|
|
|
32590
32630
|
);
|
|
32591
32631
|
}
|
|
32592
32632
|
OrbitalProvider.displayName = "OrbitalProvider";
|
|
32593
|
-
function enrichFromResponse(node, data) {
|
|
32594
|
-
if (!node || typeof node !== "object") return node ?? {};
|
|
32595
|
-
let enriched = node;
|
|
32596
|
-
if (Array.isArray(enriched.children)) {
|
|
32597
|
-
enriched = {
|
|
32598
|
-
...enriched,
|
|
32599
|
-
children: enriched.children.map(
|
|
32600
|
-
(child) => {
|
|
32601
|
-
if (!child || typeof child !== "object") return child;
|
|
32602
|
-
return enrichFromResponse(child, data);
|
|
32603
|
-
}
|
|
32604
|
-
)
|
|
32605
|
-
};
|
|
32606
|
-
}
|
|
32607
|
-
const nodeType = enriched.type;
|
|
32608
|
-
if (nodeType && isEntityAwarePattern(nodeType) && typeof enriched.entity === "string") {
|
|
32609
|
-
const entityName = enriched.entity;
|
|
32610
|
-
const records = data[entityName];
|
|
32611
|
-
if (records && records.length > 0) {
|
|
32612
|
-
enriched = { ...enriched, entity: records };
|
|
32613
|
-
if (!enriched.fields && !enriched.columns) {
|
|
32614
|
-
const sample = records[0];
|
|
32615
|
-
if (sample && typeof sample === "object") {
|
|
32616
|
-
const keys = Object.keys(sample).filter((k) => k !== "id" && k !== "_id");
|
|
32617
|
-
enriched = {
|
|
32618
|
-
...enriched,
|
|
32619
|
-
fields: keys.map((k, i) => ({ name: k, variant: i === 0 ? "h4" : "body" })),
|
|
32620
|
-
children: void 0
|
|
32621
|
-
};
|
|
32622
|
-
}
|
|
32623
|
-
}
|
|
32624
|
-
}
|
|
32625
|
-
}
|
|
32626
|
-
return enriched;
|
|
32627
|
-
}
|
|
32628
32633
|
var ServerBridgeContext = createContext(null);
|
|
32629
32634
|
function useServerBridge() {
|
|
32630
32635
|
const ctx = useContext(ServerBridgeContext);
|
|
@@ -32681,6 +32686,7 @@ function ServerBridgeProvider({
|
|
|
32681
32686
|
success: !!result.success,
|
|
32682
32687
|
clientEffects: result.clientEffects?.length ?? 0,
|
|
32683
32688
|
dataEntities,
|
|
32689
|
+
data: responseData,
|
|
32684
32690
|
emittedEvents: result.emittedEvents?.map((e) => e.event) ?? [],
|
|
32685
32691
|
error: result.error
|
|
32686
32692
|
};
|
|
@@ -32692,8 +32698,7 @@ function ServerBridgeProvider({
|
|
|
32692
32698
|
if (effectType === "render-ui") {
|
|
32693
32699
|
const slot = arr[1];
|
|
32694
32700
|
const pattern = arr[2];
|
|
32695
|
-
|
|
32696
|
-
effects.push({ type: "render-ui", slot, pattern: enriched });
|
|
32701
|
+
effects.push({ type: "render-ui", slot, pattern: pattern ?? void 0 });
|
|
32697
32702
|
} else if (effectType === "navigate") {
|
|
32698
32703
|
effects.push({ type: "navigate", route: arr[1], params: arr[2] });
|
|
32699
32704
|
} else if (effectType === "notify") {
|
|
@@ -32738,7 +32743,7 @@ function normalizeChild(child) {
|
|
|
32738
32743
|
props: { ...rest, ...normalizedChildren !== void 0 ? { children: normalizedChildren } : {} }
|
|
32739
32744
|
};
|
|
32740
32745
|
}
|
|
32741
|
-
function SlotBridge(
|
|
32746
|
+
function SlotBridge() {
|
|
32742
32747
|
const slots = useSlots();
|
|
32743
32748
|
const { render, clear } = useUISlots();
|
|
32744
32749
|
useEffect(() => {
|
|
@@ -32748,10 +32753,7 @@ function SlotBridge({ mockData }) {
|
|
|
32748
32753
|
continue;
|
|
32749
32754
|
}
|
|
32750
32755
|
const entry = slotState.patterns[slotState.patterns.length - 1];
|
|
32751
|
-
|
|
32752
|
-
if (mockData && Object.keys(mockData).length > 0) {
|
|
32753
|
-
patternRecord = enrichFromResponse(patternRecord, mockData);
|
|
32754
|
-
}
|
|
32756
|
+
const patternRecord = entry.pattern;
|
|
32755
32757
|
const { type: patternType, children, ...inlineProps } = patternRecord;
|
|
32756
32758
|
const normalizedChildren = Array.isArray(children) ? children.map((c) => normalizeChild(c)) : children;
|
|
32757
32759
|
render({
|
|
@@ -32765,17 +32767,26 @@ function SlotBridge({ mockData }) {
|
|
|
32765
32767
|
sourceTrait: slotState.source?.trait
|
|
32766
32768
|
});
|
|
32767
32769
|
}
|
|
32768
|
-
}, [slots, render, clear
|
|
32770
|
+
}, [slots, render, clear]);
|
|
32769
32771
|
return null;
|
|
32770
32772
|
}
|
|
32771
32773
|
function TraitInitializer({ traits: traits2, orbitalNames, onNavigate }) {
|
|
32772
32774
|
const slotsActions = useSlotsActions();
|
|
32773
32775
|
const bridge = useServerBridge();
|
|
32776
|
+
const entityStore = useEntityStore();
|
|
32774
32777
|
const onEventProcessed = useCallback(async (event, payload) => {
|
|
32775
32778
|
if (!bridge.connected || !orbitalNames?.length) return;
|
|
32776
32779
|
for (const name of orbitalNames) {
|
|
32777
32780
|
const { effects, meta } = await bridge.sendEvent(name, event, payload);
|
|
32778
32781
|
recordServerResponse(name, event, meta);
|
|
32782
|
+
const responseData = meta?.data;
|
|
32783
|
+
if (responseData) {
|
|
32784
|
+
for (const [entityType, records] of Object.entries(responseData)) {
|
|
32785
|
+
if (Array.isArray(records)) {
|
|
32786
|
+
entityStore.advance(entityType, records);
|
|
32787
|
+
}
|
|
32788
|
+
}
|
|
32789
|
+
}
|
|
32779
32790
|
for (const eff of effects) {
|
|
32780
32791
|
if (eff.type === "render-ui" && eff.slot && eff.pattern) {
|
|
32781
32792
|
slotsActions.setSlotPatterns(
|
|
@@ -32788,7 +32799,7 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate }) {
|
|
|
32788
32799
|
}
|
|
32789
32800
|
}
|
|
32790
32801
|
}
|
|
32791
|
-
}, [bridge.connected, bridge.sendEvent, orbitalNames, slotsActions, onNavigate]);
|
|
32802
|
+
}, [bridge.connected, bridge.sendEvent, orbitalNames, slotsActions, onNavigate, entityStore]);
|
|
32792
32803
|
const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate } : { navigate: onNavigate };
|
|
32793
32804
|
const { sendEvent } = useTraitStateMachine(traits2, slotsActions, opts);
|
|
32794
32805
|
const initSentRef = useRef(false);
|
|
@@ -32827,6 +32838,14 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate }) {
|
|
|
32827
32838
|
effects: effectTraces,
|
|
32828
32839
|
timestamp: Date.now()
|
|
32829
32840
|
});
|
|
32841
|
+
const initResponseData = meta?.data;
|
|
32842
|
+
if (initResponseData) {
|
|
32843
|
+
for (const [entityType, records] of Object.entries(initResponseData)) {
|
|
32844
|
+
if (Array.isArray(records)) {
|
|
32845
|
+
entityStore.advance(entityType, records);
|
|
32846
|
+
}
|
|
32847
|
+
}
|
|
32848
|
+
}
|
|
32830
32849
|
for (const eff of effects) {
|
|
32831
32850
|
if (eff.type === "render-ui" && eff.slot && eff.pattern) {
|
|
32832
32851
|
slotsActions.setSlotPatterns(
|
|
@@ -32867,9 +32886,19 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate }) {
|
|
|
32867
32886
|
if (!orbitals) return [];
|
|
32868
32887
|
return orbitals.filter((o) => typeof o.name === "string").map((o) => o.name);
|
|
32869
32888
|
}, [schema]);
|
|
32889
|
+
const entityStore = useEntityStore();
|
|
32890
|
+
useEffect(() => {
|
|
32891
|
+
if (!serverUrl && mockData) {
|
|
32892
|
+
for (const [entityType, records] of Object.entries(mockData)) {
|
|
32893
|
+
if (Array.isArray(records)) {
|
|
32894
|
+
entityStore.advance(entityType, records);
|
|
32895
|
+
}
|
|
32896
|
+
}
|
|
32897
|
+
}
|
|
32898
|
+
}, [mockData, serverUrl, entityStore]);
|
|
32870
32899
|
const inner = /* @__PURE__ */ jsx(VerificationProvider, { enabled: true, children: /* @__PURE__ */ jsx(SlotsProvider, { children: /* @__PURE__ */ jsxs(EntitySchemaProvider, { entities: Array.from(allEntities.values()), children: [
|
|
32871
32900
|
/* @__PURE__ */ jsx(TraitInitializer, { traits: allPageTraits, orbitalNames: serverUrl ? orbitalNames : void 0, onNavigate }),
|
|
32872
|
-
/* @__PURE__ */ jsx(SlotBridge, {
|
|
32901
|
+
/* @__PURE__ */ jsx(SlotBridge, {}),
|
|
32873
32902
|
/* @__PURE__ */ jsx(Box, { className: "min-h-full p-4", children: /* @__PURE__ */ jsx(UISlotRenderer, { includeHud: true, hudMode: "inline", includeFloating: true }) })
|
|
32874
32903
|
] }) }) });
|
|
32875
32904
|
if (serverUrl) {
|
|
@@ -32944,4 +32973,4 @@ function OrbPreview({
|
|
|
32944
32973
|
}
|
|
32945
32974
|
OrbPreview.displayName = "OrbPreview";
|
|
32946
32975
|
|
|
32947
|
-
export { EntitySchemaProvider, OrbPreview, ServerBridgeProvider, SlotsProvider, TraitContext, TraitProvider, clearSchemaCache, createClientEffectHandlers,
|
|
32976
|
+
export { EntitySchemaProvider, OrbPreview, ServerBridgeProvider, SlotsProvider, TraitContext, TraitProvider, clearSchemaCache, createClientEffectHandlers, useEntityDefinition, useEntitySchema, useResolvedSchema, useServerBridge, useSlotContent, useSlots, useSlotsActions, useTrait, useTraitContext, useTraitStateMachine };
|
package/package.json
CHANGED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* enrichFromResponse
|
|
3
|
-
*
|
|
4
|
-
* Walks a pattern tree from a server response and injects entity data
|
|
5
|
-
* into entity-aware patterns. Uses isEntityAwarePattern() from
|
|
6
|
-
* @almadar/patterns (registry-driven, not a hardcoded list).
|
|
7
|
-
*
|
|
8
|
-
* This is the single place where entity data meets UI patterns.
|
|
9
|
-
* Called by ServerBridge/ServerBridgeProvider when processing
|
|
10
|
-
* clientEffects from the server response.
|
|
11
|
-
*
|
|
12
|
-
* @packageDocumentation
|
|
13
|
-
*/
|
|
14
|
-
/**
|
|
15
|
-
* Enrich a pattern tree with entity data from a server response.
|
|
16
|
-
*
|
|
17
|
-
* @param node - Pattern config node (from server clientEffects)
|
|
18
|
-
* @param data - Entity records keyed by entity name (from server response.data)
|
|
19
|
-
* @returns Enriched pattern with entity arrays injected
|
|
20
|
-
*/
|
|
21
|
-
export declare function enrichFromResponse(node: Record<string, unknown> | null | undefined, data: Record<string, unknown[]>): Record<string, unknown>;
|