@almadar/ui 5.51.0 → 5.52.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 +21 -14
- package/dist/avl/index.js +21 -14
- package/dist/runtime/createClientEffectHandlers.d.ts +12 -1
- package/dist/runtime/index.cjs +21 -14
- package/dist/runtime/index.js +21 -14
- package/package.json +1 -1
package/dist/avl/index.cjs
CHANGED
|
@@ -57351,7 +57351,7 @@ function convertFnFormLambdasInProps(props) {
|
|
|
57351
57351
|
}
|
|
57352
57352
|
var log10 = logger.createLogger("almadar:ui:effects:client-handlers");
|
|
57353
57353
|
function createClientEffectHandlers(options) {
|
|
57354
|
-
const { eventBus, slotSetter, navigate, notify, callService } = options;
|
|
57354
|
+
const { eventBus, slotSetter, navigate, notify, callService, liveEntity } = options;
|
|
57355
57355
|
return {
|
|
57356
57356
|
emit: (event, payload) => {
|
|
57357
57357
|
const prefixedEvent = event.startsWith("UI:") ? event : `UI:${event}`;
|
|
@@ -57360,8 +57360,12 @@ function createClientEffectHandlers(options) {
|
|
|
57360
57360
|
persist: async () => {
|
|
57361
57361
|
log10.warn("persist is server-side only, ignored on client");
|
|
57362
57362
|
},
|
|
57363
|
-
set: () => {
|
|
57364
|
-
|
|
57363
|
+
set: (_entityId, field, value) => {
|
|
57364
|
+
if (!liveEntity) {
|
|
57365
|
+
log10.warn("set is server-side only, ignored on client (no live entity)");
|
|
57366
|
+
return;
|
|
57367
|
+
}
|
|
57368
|
+
liveEntity[field] = value;
|
|
57365
57369
|
},
|
|
57366
57370
|
callService: async (service, action, params) => {
|
|
57367
57371
|
if (callService) return callService(service, action, params);
|
|
@@ -57629,6 +57633,11 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
57629
57633
|
const traitName = binding.trait.name;
|
|
57630
57634
|
const linkedEntity = binding.linkedEntity || "";
|
|
57631
57635
|
const entityId = payload?.entityId;
|
|
57636
|
+
let liveEntity = traitFieldStatesRef.current.get(traitName);
|
|
57637
|
+
if (!liveEntity) {
|
|
57638
|
+
liveEntity = {};
|
|
57639
|
+
traitFieldStatesRef.current.set(traitName, liveEntity);
|
|
57640
|
+
}
|
|
57632
57641
|
const effects = syncOnly ? params.effects.filter(
|
|
57633
57642
|
(e) => Array.isArray(e) && SYNC_TICK_OPERATORS.has(String(e[0]))
|
|
57634
57643
|
) : params.effects;
|
|
@@ -57651,7 +57660,12 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
57651
57660
|
},
|
|
57652
57661
|
navigate: optionsRef.current?.navigate,
|
|
57653
57662
|
notify: optionsRef.current?.notify,
|
|
57654
|
-
callService: optionsRef.current?.callService
|
|
57663
|
+
callService: optionsRef.current?.callService,
|
|
57664
|
+
// The canonical client `set` writes `(set @entity.X)` straight into
|
|
57665
|
+
// the trait's one live store — the same object bound below. This is
|
|
57666
|
+
// what makes a [runtime] entity's set (from ticks AND events) reach
|
|
57667
|
+
// the render-ui + next tick + guards.
|
|
57668
|
+
liveEntity
|
|
57655
57669
|
});
|
|
57656
57670
|
const persistence = syncOnly ? void 0 : optionsRef.current?.persistence;
|
|
57657
57671
|
let handlers = clientHandlers;
|
|
@@ -57662,7 +57676,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
57662
57676
|
// uses below. `@payload.*` resolves from `payload` separately,
|
|
57663
57677
|
// so dropping the prior `payload as EntityRow` cast loses
|
|
57664
57678
|
// nothing — it just stops mislabelling the payload as an entity.
|
|
57665
|
-
entity:
|
|
57679
|
+
entity: liveEntity,
|
|
57666
57680
|
payload: payload || {},
|
|
57667
57681
|
state: previousState
|
|
57668
57682
|
};
|
|
@@ -57702,24 +57716,17 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
57702
57716
|
handlers = {
|
|
57703
57717
|
...handlers,
|
|
57704
57718
|
set: async (targetId, field, value) => {
|
|
57705
|
-
|
|
57706
|
-
if (!fieldState) {
|
|
57707
|
-
fieldState = {};
|
|
57708
|
-
traitFieldStatesRef.current.set(traitName, fieldState);
|
|
57709
|
-
}
|
|
57710
|
-
fieldState[field] = value;
|
|
57719
|
+
if (baseSet) await baseSet(targetId, field, value);
|
|
57711
57720
|
log15.debug("set:write", {
|
|
57712
57721
|
traitName,
|
|
57713
57722
|
field,
|
|
57714
57723
|
value: JSON.stringify(value),
|
|
57715
57724
|
transition: `${previousState}->${newState}`
|
|
57716
57725
|
});
|
|
57717
|
-
if (baseSet) await baseSet(targetId, field, value);
|
|
57718
57726
|
}
|
|
57719
57727
|
};
|
|
57720
|
-
const entityForBinding = traitFieldStatesRef.current.get(traitName) ?? {};
|
|
57721
57728
|
const bindingCtx = {
|
|
57722
|
-
entity:
|
|
57729
|
+
entity: liveEntity,
|
|
57723
57730
|
payload: payload || {},
|
|
57724
57731
|
state: previousState
|
|
57725
57732
|
};
|
package/dist/avl/index.js
CHANGED
|
@@ -57304,7 +57304,7 @@ function convertFnFormLambdasInProps(props) {
|
|
|
57304
57304
|
}
|
|
57305
57305
|
var log10 = createLogger("almadar:ui:effects:client-handlers");
|
|
57306
57306
|
function createClientEffectHandlers(options) {
|
|
57307
|
-
const { eventBus, slotSetter, navigate, notify, callService } = options;
|
|
57307
|
+
const { eventBus, slotSetter, navigate, notify, callService, liveEntity } = options;
|
|
57308
57308
|
return {
|
|
57309
57309
|
emit: (event, payload) => {
|
|
57310
57310
|
const prefixedEvent = event.startsWith("UI:") ? event : `UI:${event}`;
|
|
@@ -57313,8 +57313,12 @@ function createClientEffectHandlers(options) {
|
|
|
57313
57313
|
persist: async () => {
|
|
57314
57314
|
log10.warn("persist is server-side only, ignored on client");
|
|
57315
57315
|
},
|
|
57316
|
-
set: () => {
|
|
57317
|
-
|
|
57316
|
+
set: (_entityId, field, value) => {
|
|
57317
|
+
if (!liveEntity) {
|
|
57318
|
+
log10.warn("set is server-side only, ignored on client (no live entity)");
|
|
57319
|
+
return;
|
|
57320
|
+
}
|
|
57321
|
+
liveEntity[field] = value;
|
|
57318
57322
|
},
|
|
57319
57323
|
callService: async (service, action, params) => {
|
|
57320
57324
|
if (callService) return callService(service, action, params);
|
|
@@ -57582,6 +57586,11 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
57582
57586
|
const traitName = binding.trait.name;
|
|
57583
57587
|
const linkedEntity = binding.linkedEntity || "";
|
|
57584
57588
|
const entityId = payload?.entityId;
|
|
57589
|
+
let liveEntity = traitFieldStatesRef.current.get(traitName);
|
|
57590
|
+
if (!liveEntity) {
|
|
57591
|
+
liveEntity = {};
|
|
57592
|
+
traitFieldStatesRef.current.set(traitName, liveEntity);
|
|
57593
|
+
}
|
|
57585
57594
|
const effects = syncOnly ? params.effects.filter(
|
|
57586
57595
|
(e) => Array.isArray(e) && SYNC_TICK_OPERATORS.has(String(e[0]))
|
|
57587
57596
|
) : params.effects;
|
|
@@ -57604,7 +57613,12 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
57604
57613
|
},
|
|
57605
57614
|
navigate: optionsRef.current?.navigate,
|
|
57606
57615
|
notify: optionsRef.current?.notify,
|
|
57607
|
-
callService: optionsRef.current?.callService
|
|
57616
|
+
callService: optionsRef.current?.callService,
|
|
57617
|
+
// The canonical client `set` writes `(set @entity.X)` straight into
|
|
57618
|
+
// the trait's one live store — the same object bound below. This is
|
|
57619
|
+
// what makes a [runtime] entity's set (from ticks AND events) reach
|
|
57620
|
+
// the render-ui + next tick + guards.
|
|
57621
|
+
liveEntity
|
|
57608
57622
|
});
|
|
57609
57623
|
const persistence = syncOnly ? void 0 : optionsRef.current?.persistence;
|
|
57610
57624
|
let handlers = clientHandlers;
|
|
@@ -57615,7 +57629,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
57615
57629
|
// uses below. `@payload.*` resolves from `payload` separately,
|
|
57616
57630
|
// so dropping the prior `payload as EntityRow` cast loses
|
|
57617
57631
|
// nothing — it just stops mislabelling the payload as an entity.
|
|
57618
|
-
entity:
|
|
57632
|
+
entity: liveEntity,
|
|
57619
57633
|
payload: payload || {},
|
|
57620
57634
|
state: previousState
|
|
57621
57635
|
};
|
|
@@ -57655,24 +57669,17 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
57655
57669
|
handlers = {
|
|
57656
57670
|
...handlers,
|
|
57657
57671
|
set: async (targetId, field, value) => {
|
|
57658
|
-
|
|
57659
|
-
if (!fieldState) {
|
|
57660
|
-
fieldState = {};
|
|
57661
|
-
traitFieldStatesRef.current.set(traitName, fieldState);
|
|
57662
|
-
}
|
|
57663
|
-
fieldState[field] = value;
|
|
57672
|
+
if (baseSet) await baseSet(targetId, field, value);
|
|
57664
57673
|
log15.debug("set:write", {
|
|
57665
57674
|
traitName,
|
|
57666
57675
|
field,
|
|
57667
57676
|
value: JSON.stringify(value),
|
|
57668
57677
|
transition: `${previousState}->${newState}`
|
|
57669
57678
|
});
|
|
57670
|
-
if (baseSet) await baseSet(targetId, field, value);
|
|
57671
57679
|
}
|
|
57672
57680
|
};
|
|
57673
|
-
const entityForBinding = traitFieldStatesRef.current.get(traitName) ?? {};
|
|
57674
57681
|
const bindingCtx = {
|
|
57675
|
-
entity:
|
|
57682
|
+
entity: liveEntity,
|
|
57676
57683
|
payload: payload || {},
|
|
57677
57684
|
state: previousState
|
|
57678
57685
|
};
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* @packageDocumentation
|
|
7
7
|
*/
|
|
8
|
-
import type { EventPayload, ServiceParams } from '@almadar/core';
|
|
8
|
+
import type { EventPayload, EntityRow, ServiceParams } from '@almadar/core';
|
|
9
9
|
import type { EffectHandlers } from '@almadar/runtime';
|
|
10
10
|
export interface ClientEventBus {
|
|
11
11
|
emit: (type: string, payload?: EventPayload) => void;
|
|
@@ -19,6 +19,17 @@ export interface CreateClientEffectHandlersOptions {
|
|
|
19
19
|
slotSetter: SlotSetter;
|
|
20
20
|
navigate?: (path: string, params?: Record<string, unknown>) => void;
|
|
21
21
|
notify?: (message: string, type: 'success' | 'error' | 'warning' | 'info') => void;
|
|
22
|
+
/**
|
|
23
|
+
* Live client-entity write target for `[runtime]` entities. `(set
|
|
24
|
+
* @entity.<field> value)` runs entirely in the browser for in-memory
|
|
25
|
+
* entities (game boards, wizards): there is no server row to persist to,
|
|
26
|
+
* so the canonical client `set` must mutate THIS object — the same object
|
|
27
|
+
* `EffectExecutor` reads `@entity.*` from for the current `executeAll` and
|
|
28
|
+
* the next tick seeds from. When omitted, `set` is a no-op (bridge mode:
|
|
29
|
+
* the server owns persistence). One store, read live by render-ui, guards,
|
|
30
|
+
* and ticks — no guard-vs-render split.
|
|
31
|
+
*/
|
|
32
|
+
liveEntity?: EntityRow;
|
|
22
33
|
/**
|
|
23
34
|
* Optional consumer-supplied call-service handler. When set, it runs
|
|
24
35
|
* instead of the default mock fallback — use to wire the playground
|
package/dist/runtime/index.cjs
CHANGED
|
@@ -51279,7 +51279,7 @@ var init_UISlotRenderer = __esm({
|
|
|
51279
51279
|
});
|
|
51280
51280
|
var log = logger.createLogger("almadar:ui:effects:client-handlers");
|
|
51281
51281
|
function createClientEffectHandlers(options) {
|
|
51282
|
-
const { eventBus, slotSetter, navigate, notify, callService } = options;
|
|
51282
|
+
const { eventBus, slotSetter, navigate, notify, callService, liveEntity } = options;
|
|
51283
51283
|
return {
|
|
51284
51284
|
emit: (event, payload) => {
|
|
51285
51285
|
const prefixedEvent = event.startsWith("UI:") ? event : `UI:${event}`;
|
|
@@ -51288,8 +51288,12 @@ function createClientEffectHandlers(options) {
|
|
|
51288
51288
|
persist: async () => {
|
|
51289
51289
|
log.warn("persist is server-side only, ignored on client");
|
|
51290
51290
|
},
|
|
51291
|
-
set: () => {
|
|
51292
|
-
|
|
51291
|
+
set: (_entityId, field, value) => {
|
|
51292
|
+
if (!liveEntity) {
|
|
51293
|
+
log.warn("set is server-side only, ignored on client (no live entity)");
|
|
51294
|
+
return;
|
|
51295
|
+
}
|
|
51296
|
+
liveEntity[field] = value;
|
|
51293
51297
|
},
|
|
51294
51298
|
callService: async (service, action, params) => {
|
|
51295
51299
|
if (callService) return callService(service, action, params);
|
|
@@ -51683,6 +51687,11 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
51683
51687
|
const traitName = binding.trait.name;
|
|
51684
51688
|
const linkedEntity = binding.linkedEntity || "";
|
|
51685
51689
|
const entityId = payload?.entityId;
|
|
51690
|
+
let liveEntity = traitFieldStatesRef.current.get(traitName);
|
|
51691
|
+
if (!liveEntity) {
|
|
51692
|
+
liveEntity = {};
|
|
51693
|
+
traitFieldStatesRef.current.set(traitName, liveEntity);
|
|
51694
|
+
}
|
|
51686
51695
|
const effects = syncOnly ? params.effects.filter(
|
|
51687
51696
|
(e) => Array.isArray(e) && SYNC_TICK_OPERATORS.has(String(e[0]))
|
|
51688
51697
|
) : params.effects;
|
|
@@ -51705,7 +51714,12 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
51705
51714
|
},
|
|
51706
51715
|
navigate: optionsRef.current?.navigate,
|
|
51707
51716
|
notify: optionsRef.current?.notify,
|
|
51708
|
-
callService: optionsRef.current?.callService
|
|
51717
|
+
callService: optionsRef.current?.callService,
|
|
51718
|
+
// The canonical client `set` writes `(set @entity.X)` straight into
|
|
51719
|
+
// the trait's one live store — the same object bound below. This is
|
|
51720
|
+
// what makes a [runtime] entity's set (from ticks AND events) reach
|
|
51721
|
+
// the render-ui + next tick + guards.
|
|
51722
|
+
liveEntity
|
|
51709
51723
|
});
|
|
51710
51724
|
const persistence = syncOnly ? void 0 : optionsRef.current?.persistence;
|
|
51711
51725
|
let handlers = clientHandlers;
|
|
@@ -51716,7 +51730,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
51716
51730
|
// uses below. `@payload.*` resolves from `payload` separately,
|
|
51717
51731
|
// so dropping the prior `payload as EntityRow` cast loses
|
|
51718
51732
|
// nothing — it just stops mislabelling the payload as an entity.
|
|
51719
|
-
entity:
|
|
51733
|
+
entity: liveEntity,
|
|
51720
51734
|
payload: payload || {},
|
|
51721
51735
|
state: previousState
|
|
51722
51736
|
};
|
|
@@ -51756,24 +51770,17 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
51756
51770
|
handlers = {
|
|
51757
51771
|
...handlers,
|
|
51758
51772
|
set: async (targetId, field, value) => {
|
|
51759
|
-
|
|
51760
|
-
if (!fieldState) {
|
|
51761
|
-
fieldState = {};
|
|
51762
|
-
traitFieldStatesRef.current.set(traitName, fieldState);
|
|
51763
|
-
}
|
|
51764
|
-
fieldState[field] = value;
|
|
51773
|
+
if (baseSet) await baseSet(targetId, field, value);
|
|
51765
51774
|
log14.debug("set:write", {
|
|
51766
51775
|
traitName,
|
|
51767
51776
|
field,
|
|
51768
51777
|
value: JSON.stringify(value),
|
|
51769
51778
|
transition: `${previousState}->${newState}`
|
|
51770
51779
|
});
|
|
51771
|
-
if (baseSet) await baseSet(targetId, field, value);
|
|
51772
51780
|
}
|
|
51773
51781
|
};
|
|
51774
|
-
const entityForBinding = traitFieldStatesRef.current.get(traitName) ?? {};
|
|
51775
51782
|
const bindingCtx = {
|
|
51776
|
-
entity:
|
|
51783
|
+
entity: liveEntity,
|
|
51777
51784
|
payload: payload || {},
|
|
51778
51785
|
state: previousState
|
|
51779
51786
|
};
|
package/dist/runtime/index.js
CHANGED
|
@@ -51232,7 +51232,7 @@ var init_UISlotRenderer = __esm({
|
|
|
51232
51232
|
});
|
|
51233
51233
|
var log = createLogger("almadar:ui:effects:client-handlers");
|
|
51234
51234
|
function createClientEffectHandlers(options) {
|
|
51235
|
-
const { eventBus, slotSetter, navigate, notify, callService } = options;
|
|
51235
|
+
const { eventBus, slotSetter, navigate, notify, callService, liveEntity } = options;
|
|
51236
51236
|
return {
|
|
51237
51237
|
emit: (event, payload) => {
|
|
51238
51238
|
const prefixedEvent = event.startsWith("UI:") ? event : `UI:${event}`;
|
|
@@ -51241,8 +51241,12 @@ function createClientEffectHandlers(options) {
|
|
|
51241
51241
|
persist: async () => {
|
|
51242
51242
|
log.warn("persist is server-side only, ignored on client");
|
|
51243
51243
|
},
|
|
51244
|
-
set: () => {
|
|
51245
|
-
|
|
51244
|
+
set: (_entityId, field, value) => {
|
|
51245
|
+
if (!liveEntity) {
|
|
51246
|
+
log.warn("set is server-side only, ignored on client (no live entity)");
|
|
51247
|
+
return;
|
|
51248
|
+
}
|
|
51249
|
+
liveEntity[field] = value;
|
|
51246
51250
|
},
|
|
51247
51251
|
callService: async (service, action, params) => {
|
|
51248
51252
|
if (callService) return callService(service, action, params);
|
|
@@ -51636,6 +51640,11 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
51636
51640
|
const traitName = binding.trait.name;
|
|
51637
51641
|
const linkedEntity = binding.linkedEntity || "";
|
|
51638
51642
|
const entityId = payload?.entityId;
|
|
51643
|
+
let liveEntity = traitFieldStatesRef.current.get(traitName);
|
|
51644
|
+
if (!liveEntity) {
|
|
51645
|
+
liveEntity = {};
|
|
51646
|
+
traitFieldStatesRef.current.set(traitName, liveEntity);
|
|
51647
|
+
}
|
|
51639
51648
|
const effects = syncOnly ? params.effects.filter(
|
|
51640
51649
|
(e) => Array.isArray(e) && SYNC_TICK_OPERATORS.has(String(e[0]))
|
|
51641
51650
|
) : params.effects;
|
|
@@ -51658,7 +51667,12 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
51658
51667
|
},
|
|
51659
51668
|
navigate: optionsRef.current?.navigate,
|
|
51660
51669
|
notify: optionsRef.current?.notify,
|
|
51661
|
-
callService: optionsRef.current?.callService
|
|
51670
|
+
callService: optionsRef.current?.callService,
|
|
51671
|
+
// The canonical client `set` writes `(set @entity.X)` straight into
|
|
51672
|
+
// the trait's one live store — the same object bound below. This is
|
|
51673
|
+
// what makes a [runtime] entity's set (from ticks AND events) reach
|
|
51674
|
+
// the render-ui + next tick + guards.
|
|
51675
|
+
liveEntity
|
|
51662
51676
|
});
|
|
51663
51677
|
const persistence = syncOnly ? void 0 : optionsRef.current?.persistence;
|
|
51664
51678
|
let handlers = clientHandlers;
|
|
@@ -51669,7 +51683,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
51669
51683
|
// uses below. `@payload.*` resolves from `payload` separately,
|
|
51670
51684
|
// so dropping the prior `payload as EntityRow` cast loses
|
|
51671
51685
|
// nothing — it just stops mislabelling the payload as an entity.
|
|
51672
|
-
entity:
|
|
51686
|
+
entity: liveEntity,
|
|
51673
51687
|
payload: payload || {},
|
|
51674
51688
|
state: previousState
|
|
51675
51689
|
};
|
|
@@ -51709,24 +51723,17 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
51709
51723
|
handlers = {
|
|
51710
51724
|
...handlers,
|
|
51711
51725
|
set: async (targetId, field, value) => {
|
|
51712
|
-
|
|
51713
|
-
if (!fieldState) {
|
|
51714
|
-
fieldState = {};
|
|
51715
|
-
traitFieldStatesRef.current.set(traitName, fieldState);
|
|
51716
|
-
}
|
|
51717
|
-
fieldState[field] = value;
|
|
51726
|
+
if (baseSet) await baseSet(targetId, field, value);
|
|
51718
51727
|
log14.debug("set:write", {
|
|
51719
51728
|
traitName,
|
|
51720
51729
|
field,
|
|
51721
51730
|
value: JSON.stringify(value),
|
|
51722
51731
|
transition: `${previousState}->${newState}`
|
|
51723
51732
|
});
|
|
51724
|
-
if (baseSet) await baseSet(targetId, field, value);
|
|
51725
51733
|
}
|
|
51726
51734
|
};
|
|
51727
|
-
const entityForBinding = traitFieldStatesRef.current.get(traitName) ?? {};
|
|
51728
51735
|
const bindingCtx = {
|
|
51729
|
-
entity:
|
|
51736
|
+
entity: liveEntity,
|
|
51730
51737
|
payload: payload || {},
|
|
51731
51738
|
state: previousState
|
|
51732
51739
|
};
|