@almadar/ui 2.28.2 → 2.30.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.
@@ -6029,43 +6029,43 @@ function useQuerySingleton(query) {
6029
6029
  if (!query) {
6030
6030
  return null;
6031
6031
  }
6032
- const store = useMemo(() => getOrCreateStore(query), [query]);
6032
+ const store2 = useMemo(() => getOrCreateStore(query), [query]);
6033
6033
  useMemo(() => {
6034
6034
  const listener = () => forceUpdate({});
6035
- store.listeners.add(listener);
6035
+ store2.listeners.add(listener);
6036
6036
  return () => {
6037
- store.listeners.delete(listener);
6037
+ store2.listeners.delete(listener);
6038
6038
  };
6039
- }, [store]);
6039
+ }, [store2]);
6040
6040
  const notifyListeners = useCallback(() => {
6041
- store.listeners.forEach((listener) => listener());
6042
- }, [store]);
6041
+ store2.listeners.forEach((listener) => listener());
6042
+ }, [store2]);
6043
6043
  const setSearch = useCallback((value) => {
6044
- store.search = value;
6044
+ store2.search = value;
6045
6045
  notifyListeners();
6046
- }, [store, notifyListeners]);
6046
+ }, [store2, notifyListeners]);
6047
6047
  const setFilter = useCallback((key, value) => {
6048
- store.filters = { ...store.filters, [key]: value };
6048
+ store2.filters = { ...store2.filters, [key]: value };
6049
6049
  notifyListeners();
6050
- }, [store, notifyListeners]);
6050
+ }, [store2, notifyListeners]);
6051
6051
  const clearFilters = useCallback(() => {
6052
- store.filters = {};
6053
- store.search = "";
6052
+ store2.filters = {};
6053
+ store2.search = "";
6054
6054
  notifyListeners();
6055
- }, [store, notifyListeners]);
6055
+ }, [store2, notifyListeners]);
6056
6056
  const setSort = useCallback((field, direction) => {
6057
- store.sortField = field;
6058
- store.sortDirection = direction;
6057
+ store2.sortField = field;
6058
+ store2.sortDirection = direction;
6059
6059
  notifyListeners();
6060
- }, [store, notifyListeners]);
6060
+ }, [store2, notifyListeners]);
6061
6061
  return {
6062
- search: store.search,
6062
+ search: store2.search,
6063
6063
  setSearch,
6064
- filters: store.filters,
6064
+ filters: store2.filters,
6065
6065
  setFilter,
6066
6066
  clearFilters,
6067
- sortField: store.sortField,
6068
- sortDirection: store.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 advance = () => {
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(advance, stepDurationMs);
27497
+ timerRef.current = setTimeout(advance2, stepDurationMs);
27498
27498
  }
27499
27499
  };
27500
- timerRef.current = setTimeout(advance, stepDurationMs);
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,14 @@ 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
+ const finalProps = entityType ? { ...renderedProps, entity: storeData } : renderedProps;
35016
35069
  return /* @__PURE__ */ jsx(
35017
35070
  Box,
35018
35071
  {
35019
35072
  className: "slot-content",
35020
35073
  "data-pattern": content.pattern,
35021
35074
  "data-id": content.id,
35022
- children: /* @__PURE__ */ jsx(PatternComponent, { ...renderedProps, children: renderedChildren })
35075
+ children: /* @__PURE__ */ jsx(PatternComponent, { ...finalProps, children: renderedChildren })
35023
35076
  }
35024
35077
  );
35025
35078
  }
@@ -37574,13 +37627,13 @@ function clearEntities() {
37574
37627
  entities = /* @__PURE__ */ new Map();
37575
37628
  notify();
37576
37629
  }
37577
- function getSnapshot2() {
37630
+ function getSnapshot3() {
37578
37631
  return entities;
37579
37632
  }
37580
37633
 
37581
37634
  // hooks/useEntities.ts
37582
37635
  function useEntities() {
37583
- const entities2 = useSyncExternalStore(subscribe, getSnapshot2, getSnapshot2);
37636
+ const entities2 = useSyncExternalStore(subscribe, getSnapshot3, getSnapshot3);
37584
37637
  return {
37585
37638
  entities: entities2,
37586
37639
  getEntity,
@@ -37595,15 +37648,15 @@ function useEntities() {
37595
37648
  };
37596
37649
  }
37597
37650
  function useEntity2(id) {
37598
- const entities2 = useSyncExternalStore(subscribe, getSnapshot2, getSnapshot2);
37651
+ const entities2 = useSyncExternalStore(subscribe, getSnapshot3, getSnapshot3);
37599
37652
  return entities2.get(id);
37600
37653
  }
37601
37654
  function useEntitiesByType(type) {
37602
- const entities2 = useSyncExternalStore(subscribe, getSnapshot2, getSnapshot2);
37655
+ const entities2 = useSyncExternalStore(subscribe, getSnapshot3, getSnapshot3);
37603
37656
  return [...entities2.values()].filter((e) => e.type === type);
37604
37657
  }
37605
37658
  function useSingletonEntity(type) {
37606
- const entities2 = useSyncExternalStore(subscribe, getSnapshot2, getSnapshot2);
37659
+ const entities2 = useSyncExternalStore(subscribe, getSnapshot3, getSnapshot3);
37607
37660
  return [...entities2.values()].find((e) => e.type === type);
37608
37661
  }
37609
37662
  function usePlayer() {
@@ -0,0 +1,49 @@
1
+ /**
2
+ * EntityStoreProvider
3
+ *
4
+ * Reactive entity store for Orbital applications. Holds per-entity-type snapshots.
5
+ * When `advance()` is called (after a persist/set/swap!/atomic response from the server),
6
+ * all `useEntityRef` subscribers for that entity type re-render with fresh data.
7
+ * `useEntityWatch` callbacks fire for side effects (toasts, cross-orbital emits).
8
+ *
9
+ * This is the client-side half of the `ref` operator. The server-side half is the
10
+ * initial DB query and auto-fetch-after-mutation in the generated handler / runtime.
11
+ *
12
+ * @packageDocumentation
13
+ */
14
+ import React, { type ReactNode } from 'react';
15
+ type StoreListener = () => void;
16
+ type WatchCallback = (oldData: unknown[], newData: unknown[]) => void;
17
+ export declare function subscribeToStore(listener: StoreListener): () => void;
18
+ /**
19
+ * Subscribe to an entity type's data reactively.
20
+ * Re-renders only when the data for this specific entity type changes.
21
+ *
22
+ * This is the client-side implementation of the `["ref", "EntityType"]` operator.
23
+ */
24
+ export declare function useEntityRef(entityType: string): unknown[];
25
+ /**
26
+ * Register a callback that fires when an entity type's data changes.
27
+ *
28
+ * This is the client-side implementation of the `["watch", "EntityType", effects]` operator.
29
+ * The callback receives (oldData, newData) and should execute side effects (notify, emit, log).
30
+ */
31
+ export declare function useEntityWatch(entityType: string, callback: WatchCallback): void;
32
+ export interface EntityStoreContextValue {
33
+ advance: (entityType: string, data: unknown[]) => void;
34
+ getSnapshot: (entityType: string) => unknown[];
35
+ }
36
+ export declare const EntityStoreContext: React.Context<EntityStoreContextValue>;
37
+ /**
38
+ * Access the entity store's advance function.
39
+ * Used by useOrbitalBridge and OrbPreview to push server response data into the store.
40
+ */
41
+ export declare function useEntityStore(): EntityStoreContextValue;
42
+ /**
43
+ * Provider component. Wrap the app or page with this to enable entity reactivity.
44
+ * Already included in OrbitalProvider.
45
+ */
46
+ export declare function EntityStoreProvider({ children }: {
47
+ children: ReactNode;
48
+ }): React.ReactElement;
49
+ export {};