@almadar/ui 4.16.3 → 4.17.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.
@@ -51769,16 +51769,8 @@ init_EntitySchemaContext();
51769
51769
  init_traitRegistry();
51770
51770
  init_verificationRegistry();
51771
51771
  var crossTraitLog = createLogger("almadar:ui:cross-trait");
51772
- var reducerMirrorLog = createLogger("almadar:ui:reducer-mirror");
51773
51772
  var flushLog = createLogger("almadar:ui:slot-flush");
51774
51773
  var stateLog = createLogger("almadar:ui:state-transitions");
51775
- function readPayloadRows(payload) {
51776
- const data = payload?.["data"];
51777
- if (!Array.isArray(data)) return null;
51778
- return data.filter(
51779
- (v) => v !== null && typeof v === "object" && !Array.isArray(v) && !(v instanceof Date)
51780
- );
51781
- }
51782
51774
  function toTraitDefinition(binding) {
51783
51775
  return {
51784
51776
  name: binding.trait.name,
@@ -51886,6 +51878,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51886
51878
  traitStatesRef.current = traitStates;
51887
51879
  }, [traitStates]);
51888
51880
  const traitSnapshotDataRef = React127.useRef(/* @__PURE__ */ new Map());
51881
+ const traitFieldStatesRef = React127.useRef(/* @__PURE__ */ new Map());
51889
51882
  React127.useEffect(() => {
51890
51883
  const mgr = managerRef.current;
51891
51884
  const bindings = traitBindingsRef.current;
@@ -52171,73 +52164,20 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
52171
52164
  notify: clientHandlers.notify
52172
52165
  };
52173
52166
  }
52174
- const writeFetchResultToSnap = (fetchedEntityType, fetchResult) => {
52175
- if (!fetchResult) {
52176
- reducerMirrorLog.info("write:skip-null", { traitName, fetchedEntityType });
52177
- return;
52178
- }
52179
- const snapNow = traitSnapshotDataRef.current.get(traitName);
52180
- if (!snapNow) {
52181
- reducerMirrorLog.info("write:skip-no-snap", { traitName, fetchedEntityType });
52182
- return;
52183
- }
52184
- const rows = Array.isArray(fetchResult.rows) ? fetchResult.rows : [fetchResult.rows];
52185
- snapNow.data[fetchedEntityType] = rows;
52186
- reducerMirrorLog.info("write:ok", {
52187
- traitName,
52188
- fetchedEntityType,
52189
- rowCount: rows.length,
52190
- firstRowKeys: rows.length > 0 ? Object.keys(rows[0]).join(",") : "",
52191
- firstRowJson: rows.length > 0 ? JSON.stringify(rows[0]).slice(0, 200) : ""
52192
- });
52193
- };
52194
- const baseFetch = handlers.fetch;
52195
- const baseRef = handlers.ref;
52196
- const baseDeref = handlers.deref;
52167
+ const baseSet = handlers.set;
52197
52168
  handlers = {
52198
52169
  ...handlers,
52199
- ...baseFetch ? {
52200
- fetch: async (entityType, options2) => {
52201
- const r2 = await baseFetch(entityType, options2);
52202
- writeFetchResultToSnap(entityType, r2);
52203
- return r2;
52204
- }
52205
- } : {},
52206
- ...baseRef ? {
52207
- ref: async (entityType, options2) => {
52208
- const r2 = await baseRef(entityType, options2);
52209
- writeFetchResultToSnap(entityType, r2);
52210
- return r2;
52211
- }
52212
- } : {},
52213
- ...baseDeref ? {
52214
- deref: async (entityType, options2) => {
52215
- const r2 = await baseDeref(entityType, options2);
52216
- writeFetchResultToSnap(entityType, r2);
52217
- return r2;
52170
+ set: async (targetId, field, value) => {
52171
+ let fieldState = traitFieldStatesRef.current.get(traitName);
52172
+ if (!fieldState) {
52173
+ fieldState = {};
52174
+ traitFieldStatesRef.current.set(traitName, fieldState);
52218
52175
  }
52219
- } : {}
52176
+ fieldState[field] = value;
52177
+ if (baseSet) await baseSet(targetId, field, value);
52178
+ }
52220
52179
  };
52221
- const entityFromPayload = payload ?? {};
52222
- const reducerSnap = traitSnapshotDataRef.current.get(traitName);
52223
- const persistedRows = linkedEntity ? reducerSnap?.data[linkedEntity] : void 0;
52224
- let entityForBinding = entityFromPayload;
52225
- if (persistedRows && persistedRows.length > 0) {
52226
- const hybrid = Object.assign(
52227
- [...persistedRows],
52228
- persistedRows[0]
52229
- );
52230
- entityForBinding = hybrid;
52231
- }
52232
- reducerMirrorLog.info("read:bindingCtx", {
52233
- traitName,
52234
- linkedEntity,
52235
- eventKey: normalizedEvent,
52236
- snapDataKeys: reducerSnap ? Object.keys(reducerSnap.data).join(",") : "<no-snap>",
52237
- persistedRowCount: persistedRows?.length ?? 0,
52238
- source: persistedRows && persistedRows.length > 0 ? "reducer-mirror" : "payload",
52239
- entityJson: JSON.stringify(entityForBinding).slice(0, 200)
52240
- });
52180
+ const entityForBinding = traitFieldStatesRef.current.get(traitName) ?? {};
52241
52181
  const bindingCtx = {
52242
52182
  entity: entityForBinding,
52243
52183
  payload: payload || {},
@@ -52429,12 +52369,6 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
52429
52369
  for (const transition of binding.trait.transitions) {
52430
52370
  allEvents.add(transition.event);
52431
52371
  }
52432
- reducerMirrorLog.info("binding:transitions", {
52433
- traitName: binding.trait.name,
52434
- linkedEntity: binding.linkedEntity,
52435
- transitions: binding.trait.transitions.map((t) => `${t.from}->${t.to}/${t.event}`).join(","),
52436
- events: binding.trait.events.map((e) => e.key).join(",")
52437
- });
52438
52372
  }
52439
52373
  console.log("[TraitStateMachine] Subscribing to events:", Array.from(allEvents));
52440
52374
  const unsubscribes = [];
@@ -52449,27 +52383,11 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
52449
52383
  }
52450
52384
  const selfBusKey = `UI:${orbitalName}.${traitName}.${eventKey}`;
52451
52385
  crossTraitLog.debug("self:subscribe", { traitName, busKey: selfBusKey, eventKey });
52452
- const selfLinkedEntity = binding.linkedEntity;
52453
52386
  const unsub = eventBus.on(selfBusKey, (event) => {
52454
52387
  if (event.source && event.source.fromBridge) {
52455
52388
  crossTraitLog.debug("self:fire-skipped-bridge-echo", { traitName, busKey: selfBusKey, eventKey });
52456
52389
  return;
52457
52390
  }
52458
- if (selfLinkedEntity) {
52459
- const rowsFromPayload = readPayloadRows(event.payload);
52460
- if (rowsFromPayload !== null) {
52461
- const snapNow = traitSnapshotDataRef.current.get(traitName);
52462
- if (snapNow) {
52463
- snapNow.data[selfLinkedEntity] = rowsFromPayload;
52464
- reducerMirrorLog.info("write:self-emit", {
52465
- traitName,
52466
- eventKey,
52467
- linkedEntity: selfLinkedEntity,
52468
- rowCount: rowsFromPayload.length
52469
- });
52470
- }
52471
- }
52472
- }
52473
52391
  crossTraitLog.info("self:fire", { traitName, busKey: selfBusKey, eventKey });
52474
52392
  enqueueAndDrain(eventKey, event.payload);
52475
52393
  });
package/dist/avl/index.js CHANGED
@@ -51723,16 +51723,8 @@ init_EntitySchemaContext();
51723
51723
  init_traitRegistry();
51724
51724
  init_verificationRegistry();
51725
51725
  var crossTraitLog = createLogger("almadar:ui:cross-trait");
51726
- var reducerMirrorLog = createLogger("almadar:ui:reducer-mirror");
51727
51726
  var flushLog = createLogger("almadar:ui:slot-flush");
51728
51727
  var stateLog = createLogger("almadar:ui:state-transitions");
51729
- function readPayloadRows(payload) {
51730
- const data = payload?.["data"];
51731
- if (!Array.isArray(data)) return null;
51732
- return data.filter(
51733
- (v) => v !== null && typeof v === "object" && !Array.isArray(v) && !(v instanceof Date)
51734
- );
51735
- }
51736
51728
  function toTraitDefinition(binding) {
51737
51729
  return {
51738
51730
  name: binding.trait.name,
@@ -51840,6 +51832,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51840
51832
  traitStatesRef.current = traitStates;
51841
51833
  }, [traitStates]);
51842
51834
  const traitSnapshotDataRef = useRef(/* @__PURE__ */ new Map());
51835
+ const traitFieldStatesRef = useRef(/* @__PURE__ */ new Map());
51843
51836
  useEffect(() => {
51844
51837
  const mgr = managerRef.current;
51845
51838
  const bindings = traitBindingsRef.current;
@@ -52125,73 +52118,20 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
52125
52118
  notify: clientHandlers.notify
52126
52119
  };
52127
52120
  }
52128
- const writeFetchResultToSnap = (fetchedEntityType, fetchResult) => {
52129
- if (!fetchResult) {
52130
- reducerMirrorLog.info("write:skip-null", { traitName, fetchedEntityType });
52131
- return;
52132
- }
52133
- const snapNow = traitSnapshotDataRef.current.get(traitName);
52134
- if (!snapNow) {
52135
- reducerMirrorLog.info("write:skip-no-snap", { traitName, fetchedEntityType });
52136
- return;
52137
- }
52138
- const rows = Array.isArray(fetchResult.rows) ? fetchResult.rows : [fetchResult.rows];
52139
- snapNow.data[fetchedEntityType] = rows;
52140
- reducerMirrorLog.info("write:ok", {
52141
- traitName,
52142
- fetchedEntityType,
52143
- rowCount: rows.length,
52144
- firstRowKeys: rows.length > 0 ? Object.keys(rows[0]).join(",") : "",
52145
- firstRowJson: rows.length > 0 ? JSON.stringify(rows[0]).slice(0, 200) : ""
52146
- });
52147
- };
52148
- const baseFetch = handlers.fetch;
52149
- const baseRef = handlers.ref;
52150
- const baseDeref = handlers.deref;
52121
+ const baseSet = handlers.set;
52151
52122
  handlers = {
52152
52123
  ...handlers,
52153
- ...baseFetch ? {
52154
- fetch: async (entityType, options2) => {
52155
- const r2 = await baseFetch(entityType, options2);
52156
- writeFetchResultToSnap(entityType, r2);
52157
- return r2;
52158
- }
52159
- } : {},
52160
- ...baseRef ? {
52161
- ref: async (entityType, options2) => {
52162
- const r2 = await baseRef(entityType, options2);
52163
- writeFetchResultToSnap(entityType, r2);
52164
- return r2;
52165
- }
52166
- } : {},
52167
- ...baseDeref ? {
52168
- deref: async (entityType, options2) => {
52169
- const r2 = await baseDeref(entityType, options2);
52170
- writeFetchResultToSnap(entityType, r2);
52171
- return r2;
52124
+ set: async (targetId, field, value) => {
52125
+ let fieldState = traitFieldStatesRef.current.get(traitName);
52126
+ if (!fieldState) {
52127
+ fieldState = {};
52128
+ traitFieldStatesRef.current.set(traitName, fieldState);
52172
52129
  }
52173
- } : {}
52130
+ fieldState[field] = value;
52131
+ if (baseSet) await baseSet(targetId, field, value);
52132
+ }
52174
52133
  };
52175
- const entityFromPayload = payload ?? {};
52176
- const reducerSnap = traitSnapshotDataRef.current.get(traitName);
52177
- const persistedRows = linkedEntity ? reducerSnap?.data[linkedEntity] : void 0;
52178
- let entityForBinding = entityFromPayload;
52179
- if (persistedRows && persistedRows.length > 0) {
52180
- const hybrid = Object.assign(
52181
- [...persistedRows],
52182
- persistedRows[0]
52183
- );
52184
- entityForBinding = hybrid;
52185
- }
52186
- reducerMirrorLog.info("read:bindingCtx", {
52187
- traitName,
52188
- linkedEntity,
52189
- eventKey: normalizedEvent,
52190
- snapDataKeys: reducerSnap ? Object.keys(reducerSnap.data).join(",") : "<no-snap>",
52191
- persistedRowCount: persistedRows?.length ?? 0,
52192
- source: persistedRows && persistedRows.length > 0 ? "reducer-mirror" : "payload",
52193
- entityJson: JSON.stringify(entityForBinding).slice(0, 200)
52194
- });
52134
+ const entityForBinding = traitFieldStatesRef.current.get(traitName) ?? {};
52195
52135
  const bindingCtx = {
52196
52136
  entity: entityForBinding,
52197
52137
  payload: payload || {},
@@ -52383,12 +52323,6 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
52383
52323
  for (const transition of binding.trait.transitions) {
52384
52324
  allEvents.add(transition.event);
52385
52325
  }
52386
- reducerMirrorLog.info("binding:transitions", {
52387
- traitName: binding.trait.name,
52388
- linkedEntity: binding.linkedEntity,
52389
- transitions: binding.trait.transitions.map((t) => `${t.from}->${t.to}/${t.event}`).join(","),
52390
- events: binding.trait.events.map((e) => e.key).join(",")
52391
- });
52392
52326
  }
52393
52327
  console.log("[TraitStateMachine] Subscribing to events:", Array.from(allEvents));
52394
52328
  const unsubscribes = [];
@@ -52403,27 +52337,11 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
52403
52337
  }
52404
52338
  const selfBusKey = `UI:${orbitalName}.${traitName}.${eventKey}`;
52405
52339
  crossTraitLog.debug("self:subscribe", { traitName, busKey: selfBusKey, eventKey });
52406
- const selfLinkedEntity = binding.linkedEntity;
52407
52340
  const unsub = eventBus.on(selfBusKey, (event) => {
52408
52341
  if (event.source && event.source.fromBridge) {
52409
52342
  crossTraitLog.debug("self:fire-skipped-bridge-echo", { traitName, busKey: selfBusKey, eventKey });
52410
52343
  return;
52411
52344
  }
52412
- if (selfLinkedEntity) {
52413
- const rowsFromPayload = readPayloadRows(event.payload);
52414
- if (rowsFromPayload !== null) {
52415
- const snapNow = traitSnapshotDataRef.current.get(traitName);
52416
- if (snapNow) {
52417
- snapNow.data[selfLinkedEntity] = rowsFromPayload;
52418
- reducerMirrorLog.info("write:self-emit", {
52419
- traitName,
52420
- eventKey,
52421
- linkedEntity: selfLinkedEntity,
52422
- rowCount: rowsFromPayload.length
52423
- });
52424
- }
52425
- }
52426
- }
52427
52345
  crossTraitLog.info("self:fire", { traitName, busKey: selfBusKey, eventKey });
52428
52346
  enqueueAndDrain(eventKey, event.payload);
52429
52347
  });
@@ -38296,16 +38296,8 @@ init_EntitySchemaContext();
38296
38296
  init_traitRegistry();
38297
38297
  init_verificationRegistry();
38298
38298
  var crossTraitLog = createLogger("almadar:ui:cross-trait");
38299
- var reducerMirrorLog = createLogger("almadar:ui:reducer-mirror");
38300
38299
  var flushLog = createLogger("almadar:ui:slot-flush");
38301
38300
  var stateLog = createLogger("almadar:ui:state-transitions");
38302
- function readPayloadRows(payload) {
38303
- const data = payload?.["data"];
38304
- if (!Array.isArray(data)) return null;
38305
- return data.filter(
38306
- (v) => v !== null && typeof v === "object" && !Array.isArray(v) && !(v instanceof Date)
38307
- );
38308
- }
38309
38301
  function toTraitDefinition(binding) {
38310
38302
  return {
38311
38303
  name: binding.trait.name,
@@ -38413,6 +38405,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
38413
38405
  traitStatesRef.current = traitStates;
38414
38406
  }, [traitStates]);
38415
38407
  const traitSnapshotDataRef = React113.useRef(/* @__PURE__ */ new Map());
38408
+ const traitFieldStatesRef = React113.useRef(/* @__PURE__ */ new Map());
38416
38409
  React113.useEffect(() => {
38417
38410
  const mgr = managerRef.current;
38418
38411
  const bindings = traitBindingsRef.current;
@@ -38698,73 +38691,20 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
38698
38691
  notify: clientHandlers.notify
38699
38692
  };
38700
38693
  }
38701
- const writeFetchResultToSnap = (fetchedEntityType, fetchResult) => {
38702
- if (!fetchResult) {
38703
- reducerMirrorLog.info("write:skip-null", { traitName, fetchedEntityType });
38704
- return;
38705
- }
38706
- const snapNow = traitSnapshotDataRef.current.get(traitName);
38707
- if (!snapNow) {
38708
- reducerMirrorLog.info("write:skip-no-snap", { traitName, fetchedEntityType });
38709
- return;
38710
- }
38711
- const rows = Array.isArray(fetchResult.rows) ? fetchResult.rows : [fetchResult.rows];
38712
- snapNow.data[fetchedEntityType] = rows;
38713
- reducerMirrorLog.info("write:ok", {
38714
- traitName,
38715
- fetchedEntityType,
38716
- rowCount: rows.length,
38717
- firstRowKeys: rows.length > 0 ? Object.keys(rows[0]).join(",") : "",
38718
- firstRowJson: rows.length > 0 ? JSON.stringify(rows[0]).slice(0, 200) : ""
38719
- });
38720
- };
38721
- const baseFetch = handlers.fetch;
38722
- const baseRef = handlers.ref;
38723
- const baseDeref = handlers.deref;
38694
+ const baseSet = handlers.set;
38724
38695
  handlers = {
38725
38696
  ...handlers,
38726
- ...baseFetch ? {
38727
- fetch: async (entityType, options2) => {
38728
- const r = await baseFetch(entityType, options2);
38729
- writeFetchResultToSnap(entityType, r);
38730
- return r;
38731
- }
38732
- } : {},
38733
- ...baseRef ? {
38734
- ref: async (entityType, options2) => {
38735
- const r = await baseRef(entityType, options2);
38736
- writeFetchResultToSnap(entityType, r);
38737
- return r;
38738
- }
38739
- } : {},
38740
- ...baseDeref ? {
38741
- deref: async (entityType, options2) => {
38742
- const r = await baseDeref(entityType, options2);
38743
- writeFetchResultToSnap(entityType, r);
38744
- return r;
38697
+ set: async (targetId, field, value) => {
38698
+ let fieldState = traitFieldStatesRef.current.get(traitName);
38699
+ if (!fieldState) {
38700
+ fieldState = {};
38701
+ traitFieldStatesRef.current.set(traitName, fieldState);
38745
38702
  }
38746
- } : {}
38703
+ fieldState[field] = value;
38704
+ if (baseSet) await baseSet(targetId, field, value);
38705
+ }
38747
38706
  };
38748
- const entityFromPayload = payload ?? {};
38749
- const reducerSnap = traitSnapshotDataRef.current.get(traitName);
38750
- const persistedRows = linkedEntity ? reducerSnap?.data[linkedEntity] : void 0;
38751
- let entityForBinding = entityFromPayload;
38752
- if (persistedRows && persistedRows.length > 0) {
38753
- const hybrid = Object.assign(
38754
- [...persistedRows],
38755
- persistedRows[0]
38756
- );
38757
- entityForBinding = hybrid;
38758
- }
38759
- reducerMirrorLog.info("read:bindingCtx", {
38760
- traitName,
38761
- linkedEntity,
38762
- eventKey: normalizedEvent,
38763
- snapDataKeys: reducerSnap ? Object.keys(reducerSnap.data).join(",") : "<no-snap>",
38764
- persistedRowCount: persistedRows?.length ?? 0,
38765
- source: persistedRows && persistedRows.length > 0 ? "reducer-mirror" : "payload",
38766
- entityJson: JSON.stringify(entityForBinding).slice(0, 200)
38767
- });
38707
+ const entityForBinding = traitFieldStatesRef.current.get(traitName) ?? {};
38768
38708
  const bindingCtx = {
38769
38709
  entity: entityForBinding,
38770
38710
  payload: payload || {},
@@ -38956,12 +38896,6 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
38956
38896
  for (const transition of binding.trait.transitions) {
38957
38897
  allEvents.add(transition.event);
38958
38898
  }
38959
- reducerMirrorLog.info("binding:transitions", {
38960
- traitName: binding.trait.name,
38961
- linkedEntity: binding.linkedEntity,
38962
- transitions: binding.trait.transitions.map((t) => `${t.from}->${t.to}/${t.event}`).join(","),
38963
- events: binding.trait.events.map((e) => e.key).join(",")
38964
- });
38965
38899
  }
38966
38900
  console.log("[TraitStateMachine] Subscribing to events:", Array.from(allEvents));
38967
38901
  const unsubscribes = [];
@@ -38976,27 +38910,11 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
38976
38910
  }
38977
38911
  const selfBusKey = `UI:${orbitalName}.${traitName}.${eventKey}`;
38978
38912
  crossTraitLog.debug("self:subscribe", { traitName, busKey: selfBusKey, eventKey });
38979
- const selfLinkedEntity = binding.linkedEntity;
38980
38913
  const unsub = eventBus.on(selfBusKey, (event) => {
38981
38914
  if (event.source && event.source.fromBridge) {
38982
38915
  crossTraitLog.debug("self:fire-skipped-bridge-echo", { traitName, busKey: selfBusKey, eventKey });
38983
38916
  return;
38984
38917
  }
38985
- if (selfLinkedEntity) {
38986
- const rowsFromPayload = readPayloadRows(event.payload);
38987
- if (rowsFromPayload !== null) {
38988
- const snapNow = traitSnapshotDataRef.current.get(traitName);
38989
- if (snapNow) {
38990
- snapNow.data[selfLinkedEntity] = rowsFromPayload;
38991
- reducerMirrorLog.info("write:self-emit", {
38992
- traitName,
38993
- eventKey,
38994
- linkedEntity: selfLinkedEntity,
38995
- rowCount: rowsFromPayload.length
38996
- });
38997
- }
38998
- }
38999
- }
39000
38918
  crossTraitLog.info("self:fire", { traitName, busKey: selfBusKey, eventKey });
39001
38919
  enqueueAndDrain(eventKey, event.payload);
39002
38920
  });
@@ -38251,16 +38251,8 @@ init_EntitySchemaContext();
38251
38251
  init_traitRegistry();
38252
38252
  init_verificationRegistry();
38253
38253
  var crossTraitLog = createLogger("almadar:ui:cross-trait");
38254
- var reducerMirrorLog = createLogger("almadar:ui:reducer-mirror");
38255
38254
  var flushLog = createLogger("almadar:ui:slot-flush");
38256
38255
  var stateLog = createLogger("almadar:ui:state-transitions");
38257
- function readPayloadRows(payload) {
38258
- const data = payload?.["data"];
38259
- if (!Array.isArray(data)) return null;
38260
- return data.filter(
38261
- (v) => v !== null && typeof v === "object" && !Array.isArray(v) && !(v instanceof Date)
38262
- );
38263
- }
38264
38256
  function toTraitDefinition(binding) {
38265
38257
  return {
38266
38258
  name: binding.trait.name,
@@ -38368,6 +38360,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
38368
38360
  traitStatesRef.current = traitStates;
38369
38361
  }, [traitStates]);
38370
38362
  const traitSnapshotDataRef = useRef(/* @__PURE__ */ new Map());
38363
+ const traitFieldStatesRef = useRef(/* @__PURE__ */ new Map());
38371
38364
  useEffect(() => {
38372
38365
  const mgr = managerRef.current;
38373
38366
  const bindings = traitBindingsRef.current;
@@ -38653,73 +38646,20 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
38653
38646
  notify: clientHandlers.notify
38654
38647
  };
38655
38648
  }
38656
- const writeFetchResultToSnap = (fetchedEntityType, fetchResult) => {
38657
- if (!fetchResult) {
38658
- reducerMirrorLog.info("write:skip-null", { traitName, fetchedEntityType });
38659
- return;
38660
- }
38661
- const snapNow = traitSnapshotDataRef.current.get(traitName);
38662
- if (!snapNow) {
38663
- reducerMirrorLog.info("write:skip-no-snap", { traitName, fetchedEntityType });
38664
- return;
38665
- }
38666
- const rows = Array.isArray(fetchResult.rows) ? fetchResult.rows : [fetchResult.rows];
38667
- snapNow.data[fetchedEntityType] = rows;
38668
- reducerMirrorLog.info("write:ok", {
38669
- traitName,
38670
- fetchedEntityType,
38671
- rowCount: rows.length,
38672
- firstRowKeys: rows.length > 0 ? Object.keys(rows[0]).join(",") : "",
38673
- firstRowJson: rows.length > 0 ? JSON.stringify(rows[0]).slice(0, 200) : ""
38674
- });
38675
- };
38676
- const baseFetch = handlers.fetch;
38677
- const baseRef = handlers.ref;
38678
- const baseDeref = handlers.deref;
38649
+ const baseSet = handlers.set;
38679
38650
  handlers = {
38680
38651
  ...handlers,
38681
- ...baseFetch ? {
38682
- fetch: async (entityType, options2) => {
38683
- const r = await baseFetch(entityType, options2);
38684
- writeFetchResultToSnap(entityType, r);
38685
- return r;
38686
- }
38687
- } : {},
38688
- ...baseRef ? {
38689
- ref: async (entityType, options2) => {
38690
- const r = await baseRef(entityType, options2);
38691
- writeFetchResultToSnap(entityType, r);
38692
- return r;
38693
- }
38694
- } : {},
38695
- ...baseDeref ? {
38696
- deref: async (entityType, options2) => {
38697
- const r = await baseDeref(entityType, options2);
38698
- writeFetchResultToSnap(entityType, r);
38699
- return r;
38652
+ set: async (targetId, field, value) => {
38653
+ let fieldState = traitFieldStatesRef.current.get(traitName);
38654
+ if (!fieldState) {
38655
+ fieldState = {};
38656
+ traitFieldStatesRef.current.set(traitName, fieldState);
38700
38657
  }
38701
- } : {}
38658
+ fieldState[field] = value;
38659
+ if (baseSet) await baseSet(targetId, field, value);
38660
+ }
38702
38661
  };
38703
- const entityFromPayload = payload ?? {};
38704
- const reducerSnap = traitSnapshotDataRef.current.get(traitName);
38705
- const persistedRows = linkedEntity ? reducerSnap?.data[linkedEntity] : void 0;
38706
- let entityForBinding = entityFromPayload;
38707
- if (persistedRows && persistedRows.length > 0) {
38708
- const hybrid = Object.assign(
38709
- [...persistedRows],
38710
- persistedRows[0]
38711
- );
38712
- entityForBinding = hybrid;
38713
- }
38714
- reducerMirrorLog.info("read:bindingCtx", {
38715
- traitName,
38716
- linkedEntity,
38717
- eventKey: normalizedEvent,
38718
- snapDataKeys: reducerSnap ? Object.keys(reducerSnap.data).join(",") : "<no-snap>",
38719
- persistedRowCount: persistedRows?.length ?? 0,
38720
- source: persistedRows && persistedRows.length > 0 ? "reducer-mirror" : "payload",
38721
- entityJson: JSON.stringify(entityForBinding).slice(0, 200)
38722
- });
38662
+ const entityForBinding = traitFieldStatesRef.current.get(traitName) ?? {};
38723
38663
  const bindingCtx = {
38724
38664
  entity: entityForBinding,
38725
38665
  payload: payload || {},
@@ -38911,12 +38851,6 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
38911
38851
  for (const transition of binding.trait.transitions) {
38912
38852
  allEvents.add(transition.event);
38913
38853
  }
38914
- reducerMirrorLog.info("binding:transitions", {
38915
- traitName: binding.trait.name,
38916
- linkedEntity: binding.linkedEntity,
38917
- transitions: binding.trait.transitions.map((t) => `${t.from}->${t.to}/${t.event}`).join(","),
38918
- events: binding.trait.events.map((e) => e.key).join(",")
38919
- });
38920
38854
  }
38921
38855
  console.log("[TraitStateMachine] Subscribing to events:", Array.from(allEvents));
38922
38856
  const unsubscribes = [];
@@ -38931,27 +38865,11 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
38931
38865
  }
38932
38866
  const selfBusKey = `UI:${orbitalName}.${traitName}.${eventKey}`;
38933
38867
  crossTraitLog.debug("self:subscribe", { traitName, busKey: selfBusKey, eventKey });
38934
- const selfLinkedEntity = binding.linkedEntity;
38935
38868
  const unsub = eventBus.on(selfBusKey, (event) => {
38936
38869
  if (event.source && event.source.fromBridge) {
38937
38870
  crossTraitLog.debug("self:fire-skipped-bridge-echo", { traitName, busKey: selfBusKey, eventKey });
38938
38871
  return;
38939
38872
  }
38940
- if (selfLinkedEntity) {
38941
- const rowsFromPayload = readPayloadRows(event.payload);
38942
- if (rowsFromPayload !== null) {
38943
- const snapNow = traitSnapshotDataRef.current.get(traitName);
38944
- if (snapNow) {
38945
- snapNow.data[selfLinkedEntity] = rowsFromPayload;
38946
- reducerMirrorLog.info("write:self-emit", {
38947
- traitName,
38948
- eventKey,
38949
- linkedEntity: selfLinkedEntity,
38950
- rowCount: rowsFromPayload.length
38951
- });
38952
- }
38953
- }
38954
- }
38955
38873
  crossTraitLog.info("self:fire", { traitName, busKey: selfBusKey, eventKey });
38956
38874
  enqueueAndDrain(eventKey, event.payload);
38957
38875
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "4.16.3",
3
+ "version": "4.17.0",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "main": "./dist/components/index.js",
@@ -118,10 +118,10 @@
118
118
  "access": "public"
119
119
  },
120
120
  "dependencies": {
121
- "@almadar/core": "^7.7.1",
121
+ "@almadar/core": "^7.8.0",
122
122
  "@almadar/evaluator": ">=2.9.2",
123
123
  "@almadar/patterns": ">=2.17.1",
124
- "@almadar/runtime": "^5.11.1",
124
+ "@almadar/runtime": "^6.0.0",
125
125
  "@almadar/std": ">=6.4.1",
126
126
  "@almadar/syntax": ">=1.3.1",
127
127
  "@xyflow/react": "12.10.1",