@directive-run/react 0.1.1 → 0.2.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/README.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # @directive-run/react
2
2
 
3
- React hooks for Directive. Provides `useSyncExternalStore`-based hooks for reading facts, derivations, and dispatching events.
3
+ [![npm](https://img.shields.io/npm/v/@directive-run/react?color=%236366f1)](https://www.npmjs.com/package/@directive-run/react)
4
+ [![downloads](https://img.shields.io/npm/dm/@directive-run/react)](https://www.npmjs.com/package/@directive-run/react)
5
+ [![bundle size](https://img.shields.io/bundlephobia/minzip/@directive-run/react)](https://bundlephobia.com/package/@directive-run/react)
6
+
7
+ React hooks for [Directive](https://www.npmjs.com/package/@directive-run/core). Built on `useSyncExternalStore` for tear-free reads with concurrent rendering support.
4
8
 
5
9
  ## Install
6
10
 
@@ -8,12 +12,43 @@ React hooks for Directive. Provides `useSyncExternalStore`-based hooks for readi
8
12
  npm install @directive-run/core @directive-run/react
9
13
  ```
10
14
 
11
- ## Usage
15
+ ## Quick Start
16
+
17
+ Define a module in a shared file, then use it in any component:
18
+
19
+ ```typescript
20
+ // system.ts
21
+ import { createModule, createSystem, t } from "@directive-run/core";
22
+
23
+ const counter = createModule("counter", {
24
+ schema: {
25
+ facts: { count: t.number() },
26
+ derivations: { doubled: t.number() },
27
+ events: { increment: {}, decrement: {} },
28
+ requirements: {},
29
+ },
30
+ init: (facts) => {
31
+ facts.count = 0;
32
+ },
33
+ derive: {
34
+ doubled: (facts) => facts.count * 2,
35
+ },
36
+ events: {
37
+ increment: (facts) => { facts.count += 1; },
38
+ decrement: (facts) => { facts.count -= 1; },
39
+ },
40
+ });
41
+
42
+ export const system = createSystem({ module: counter });
43
+ system.start();
44
+ ```
12
45
 
13
46
  ```tsx
47
+ // Counter.tsx
14
48
  import { useFact, useDerived, useEvents } from "@directive-run/react";
49
+ import { system } from "./system";
15
50
 
16
- function Counter({ system }) {
51
+ export function Counter() {
17
52
  const count = useFact(system, "count");
18
53
  const doubled = useDerived(system, "doubled");
19
54
  const events = useEvents(system);
@@ -22,22 +57,77 @@ function Counter({ system }) {
22
57
  <div>
23
58
  <p>Count: {count} (doubled: {doubled})</p>
24
59
  <button onClick={() => events.increment()}>+</button>
60
+ <button onClick={() => events.decrement()}>&minus;</button>
25
61
  </div>
26
62
  );
27
63
  }
28
64
  ```
29
65
 
30
- ## Exports
66
+ ## useSelector
67
+
68
+ Auto-tracking selector over facts and derivations. Subscribes only to the keys your selector reads:
69
+
70
+ ```tsx
71
+ import { useSelector } from "@directive-run/react";
72
+ import { system } from "./system";
73
+
74
+ function Summary() {
75
+ const label = useSelector(system, (state) => {
76
+ return state.count > 10 ? "High" : "Low";
77
+ });
78
+
79
+ return <span>{label}</span>;
80
+ }
81
+ ```
82
+
83
+ ## API Reference
84
+
85
+ ### Core Hooks
86
+
87
+ | Hook | Return Type | Description |
88
+ |------|------------|-------------|
89
+ | `useFact(system, key)` | `T \| undefined` | Subscribe to a single fact value |
90
+ | `useFact(system, [keys])` | `Pick<Facts, K>` | Subscribe to multiple facts |
91
+ | `useDerived(system, key)` | `T` | Subscribe to a single derivation |
92
+ | `useDerived(system, [keys])` | `Pick<Derivations, K>` | Subscribe to multiple derivations |
93
+ | `useSelector(system, fn)` | `R` | Auto-tracking selector with optional equality function |
94
+ | `useEvents(system)` | `Events` | Memoized events dispatcher |
95
+ | `useDispatch(system)` | `(event) => void` | Low-level dispatch function |
96
+
97
+ ### Advanced Hooks
31
98
 
32
- `useFact`, `useDerived`, `useSelector`, `useDispatch`, `useEvents`, `useWatch`, `useInspect`, `useRequirementStatus`, `useSuspenseRequirement`, `useExplain`, `useConstraintStatus`, `useOptimisticUpdate`, `useTimeTravel`, `useDirective`, `useDirectiveRef`, `useHydratedSystem`, `DirectiveDevTools`, `DirectiveHydrator`, `shallowEqual`
99
+ | Hook | Return Type | Description |
100
+ |------|------------|-------------|
101
+ | `useWatch(system, key, cb)` | `void` | Side-effect on fact or derivation change (no re-render) |
102
+ | `useInspect(system)` | `InspectState` | Consolidated system state (isSettled, unmet, inflight) |
103
+ | `useRequirementStatus(plugin, type)` | `RequirementTypeStatus` | Requirement loading/error state |
104
+ | `useExplain(system, reqId)` | `string \| null` | Human-readable requirement explanation |
105
+ | `useConstraintStatus(system)` | `ConstraintInfo[]` | All constraint states |
106
+ | `useOptimisticUpdate(system)` | `{ mutate, isPending, error, rollback }` | Optimistic mutation with auto-rollback |
107
+ | `useTimeTravel(system)` | `TimeTravelState \| null` | Undo/redo navigation |
108
+
109
+ ### React-Specific
110
+
111
+ | Export | Description |
112
+ |--------|-------------|
113
+ | `useDirective(module, options?)` | Scoped system with selected facts/derivations |
114
+ | `useDirectiveRef(module)` | Scoped system lifecycle (start on mount, destroy on unmount) |
115
+ | `useSuspenseRequirement(plugin, type)` | Suspense-compatible requirement status |
116
+ | `useHydratedSystem(module)` | Client-side system hydrated from server snapshot |
117
+ | `DirectiveDevTools` | Floating dev panel (tree-shaken in production) |
118
+ | `DirectiveHydrator` | SSR/RSC snapshot provider |
119
+ | `shallowEqual` | Shallow equality helper for selectors |
33
120
 
34
121
  ## Peer Dependencies
35
122
 
36
123
  - `react >= 18`
37
124
  - `@directive-run/core`
38
125
 
126
+ ## Documentation
127
+
128
+ - [React Adapter Guide](https://directive.run/docs/adapters/react)
129
+ - [API Reference](https://directive.run/docs/api)
130
+
39
131
  ## License
40
132
 
41
133
  MIT
42
-
43
- [Full documentation](https://directive.run/docs)
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';var react=require('react'),core=require('@directive-run/core'),adapterUtils=require('@directive-run/core/adapter-utils'),jsxRuntime=require('react/jsx-runtime');var M=Symbol("directive.uninitialized");function me(e,t){return adapterUtils.assertSystem("useFact",e),process.env.NODE_ENV!=="production"&&typeof t=="function"&&console.error("[Directive] useFact() received a function. Did you mean useSelector()? useFact() takes a string key or array of keys, not a selector function."),Array.isArray(t)?oe(e,t):se(e,t)}function se(e,t){process.env.NODE_ENV!=="production"&&(t in e.facts.$store.toObject()||console.warn(`[Directive] useFact("${t}") \u2014 fact not found in store. Check that "${t}" is defined in your module's schema.`));let r=react.useCallback(s=>e.facts.$store.subscribe([t],s),[e,t]),i=react.useCallback(()=>e.facts[t],[e,t]);return react.useSyncExternalStore(r,i,i)}function oe(e,t){let r=react.useRef(M),i=react.useCallback(o=>e.facts.$store.subscribe(t,o),[e,...t]),s=react.useCallback(()=>{let o={};for(let n of t)o[n]=e.facts[n];if(r.current!==M){let n=true;for(let u of t)if(!Object.is(r.current[u],o[u])){n=false;break}if(n)return r.current}return r.current=o,o},[e,...t]);return react.useSyncExternalStore(i,s,s)}function he(e,t){return adapterUtils.assertSystem("useDerived",e),process.env.NODE_ENV!=="production"&&typeof t=="function"&&console.error("[Directive] useDerived() received a function. Did you mean useSelector()? useDerived() takes a string key or array of keys, not a selector function."),Array.isArray(t)?ue(e,t):ie(e,t)}function ie(e,t){process.env.NODE_ENV!=="production"&&(t in e.derive||console.warn(`[Directive] useDerived("${t}") \u2014 derivation not found. Check that "${t}" is defined in your module's derive property.`));let r=react.useCallback(s=>e.subscribe([t],s),[e,t]),i=react.useCallback(()=>e.read(t),[e,t]);return react.useSyncExternalStore(r,i,i)}function ue(e,t){let r=react.useRef(M),i=react.useCallback(o=>e.subscribe(t,o),[e,...t]),s=react.useCallback(()=>{let o={};for(let n of t)o[n]=e.read(n);if(r.current!==M){let n=true;for(let u of t)if(!Object.is(r.current[u],o[u])){n=false;break}if(n)return r.current}return r.current=o,o},[e,...t]);return react.useSyncExternalStore(i,s,s)}function Re(e,t,r,i){let s,o=false,n;typeof r=="function"&&i===void 0?n=r:(r!==void 0&&(s=r,o=true),n=i??adapterUtils.defaultEquality),process.env.NODE_ENV!=="production"&&!e&&!o&&console.error("[Directive] useSelector() received a null/undefined system without a default value. Provide a default value as the 3rd parameter: useSelector(system, selector, defaultValue)");let u=react.useRef(t),l=react.useRef(n),S=react.useRef(s);u.current=t,l.current=n,S.current=s;let c=react.useRef([]),g=react.useRef([]),y=react.useRef(M),D=react.useRef([]),h=react.useMemo(()=>e?new Set(Object.keys(e.derive)):new Set,[e]),R=react.useCallback(()=>e?adapterUtils.runTrackedSelector(e,h,u.current):{value:S.current,factKeys:[],deriveKeys:[]},[e,h]),a=react.useCallback(b=>{if(!e)return ()=>{};let K=()=>{for(let p of D.current)p();D.current=[];let{factKeys:F,deriveKeys:T}=R();c.current=F,g.current=T,F.length>0?D.current.push(e.facts.$store.subscribe(F,()=>{let p=R();adapterUtils.depsChanged(c.current,p.factKeys,g.current,p.deriveKeys)&&K(),b();})):T.length===0&&D.current.push(e.facts.$store.subscribeAll(b)),T.length>0&&D.current.push(e.subscribe(T,()=>{let p=R();adapterUtils.depsChanged(c.current,p.factKeys,g.current,p.deriveKeys)&&K(),b();}));};return K(),()=>{for(let F of D.current)F();D.current=[];}},[e,R]),x=react.useCallback(()=>{let b;if(!e)b=S.current;else {let{value:K}=R();b=K===void 0&&o?S.current:K;}return y.current!==M&&l.current(y.current,b)?y.current:(y.current=b,b)},[R,e,o]);return react.useSyncExternalStore(a,x,x)}function xe(e){return adapterUtils.assertSystem("useDispatch",e),react.useCallback(t=>{e.dispatch(t);},[e])}function De(e,t,r,i){adapterUtils.assertSystem("useWatch",e);let s=t==="fact"&&typeof r=="string"&&typeof i=="function",o=s?r:t,n=s?i:r,u=react.useRef(n);u.current=n,react.useEffect(()=>e.watch(o,(l,S)=>{u.current(l,S);}),[e,o]);}function L(e,t){adapterUtils.assertSystem("useInspect",e);let r=ae(e),i=t?.throttleMs,[s,o]=react.useState(r),n=react.useRef(null);return react.useEffect(()=>{if(!i||i<=0){n.current?.cleanup(),n.current=null;return}return n.current?.cleanup(),n.current=adapterUtils.createThrottle((...u)=>{o(u[0]);},i),()=>{n.current?.cleanup(),n.current=null;}},[i]),react.useEffect(()=>{n.current&&n.current.throttled(r);},[r]),!i||i<=0?r:s}function ce(e){return adapterUtils.computeInspectState(e)}function ae(e){let t=react.useRef(null),r=react.useRef([]),i=react.useRef([]),s=react.useRef(null),o=react.useCallback(u=>{let l=e.facts.$store.subscribeAll(u),S=e.onSettledChange(u);return ()=>{l(),S();}},[e]),n=react.useCallback(()=>{let u=ce(e),l=u.unmet.length===r.current.length&&u.unmet.every((g,y)=>g.id===r.current[y]),S=u.inflight.length===i.current.length&&u.inflight.every((g,y)=>g.id===i.current[y]),c=u.isSettled===s.current;return l&&S&&c&&t.current?t.current:(t.current=u,r.current=u.unmet.map(g=>g.id),i.current=u.inflight.map(g=>g.id),s.current=u.isSettled,u)},[e]);return react.useSyncExternalStore(o,n,n)}function ke(e){adapterUtils.assertSystem("useTimeTravel",e);let t=react.useRef(null),r=react.useCallback(s=>e.onTimeTravelChange(s),[e]),i=react.useCallback(()=>{let s=adapterUtils.buildTimeTravelState(e);return s?(t.current&&t.current.canUndo===s.canUndo&&t.current.canRedo===s.canRedo&&t.current.currentIndex===s.currentIndex&&t.current.totalSnapshots===s.totalSnapshots&&t.current.isPaused===s.isPaused||(t.current=s),t.current):null},[e]);return react.useSyncExternalStore(r,i,i)}function Me(e,t){return Array.isArray(t)?de(e,t):le(e,t)}function le(e,t){let r=react.useRef(M),i=react.useCallback(o=>e.subscribe(o),[e]),s=react.useCallback(()=>{let o=e.getStatus(t);if(r.current!==M){let n=r.current;if(n.pending===o.pending&&n.inflight===o.inflight&&n.failed===o.failed&&n.isLoading===o.isLoading&&n.hasError===o.hasError&&n.lastError===o.lastError)return r.current}return r.current=o,o},[e,t]);return react.useSyncExternalStore(i,s,s)}function de(e,t){let r=react.useRef(null),i=react.useRef(""),s=react.useCallback(n=>e.subscribe(n),[e]),o=react.useCallback(()=>{let n={},u=[];for(let S of t){let c=e.getStatus(S);n[S]=c,u.push(`${S}:${c.pending}:${c.inflight}:${c.failed}:${c.hasError}:${c.lastError?.message??""}`);}let l=u.join("|");return l!==i.current&&(i.current=l,r.current=n),r.current??n},[e,...t]);return react.useSyncExternalStore(s,o,o)}var $=new WeakMap;function _(e){let t=$.get(e);return t||(t=new Map,$.set(e,t)),t}function Ie(e,t){return Array.isArray(t)?Se(e,t):fe(e,t)}function fe(e,t){let r=e.getStatus(t);if(r.hasError&&r.lastError)throw r.lastError;if(r.isLoading){let i=_(e),s=i.get(t);throw s||(s=new Promise(o=>{let n=e.subscribe(()=>{e.getStatus(t).isLoading||(i.delete(t),n(),o());});}),i.set(t,s)),s}return r}function Se(e,t){let r={},i=false,s=null;for(let o of t){let n=e.getStatus(o);r[o]=n,n.hasError&&n.lastError&&!s&&(s=n.lastError),n.isLoading&&(i=true);}if(s)throw s;if(i){let o=_(e),n=t.slice().sort().join(","),u=o.get(n);throw u||(u=new Promise(l=>{let S=e.subscribe(()=>{t.every(g=>!e.getStatus(g).isLoading)&&(o.delete(n),S(),l());});}),o.set(n,u)),u}return r}function B(e,t){let r=react.useRef(null),i=react.useRef(null),s=t?.status===true;if(!r.current){let o="id"in e&&"schema"in e,n=o?e:e.module,u=o?{}:e,l=t?.plugins??u.plugins??[],S=t?.debug??u.debug,c=t?.errorBoundary??u.errorBoundary,g=t?.tickMs??u.tickMs,y=t?.zeroConfig??u.zeroConfig,D=t?.initialFacts??u.initialFacts,h=[...l];s&&(i.current=core.createRequirementStatusPlugin(),h=[...h,i.current.plugin]),r.current=core.createSystem({module:n,plugins:h.length>0?h:void 0,debug:S,errorBoundary:c,tickMs:g,zeroConfig:y,initialFacts:D});}return react.useEffect(()=>{let o=r.current;return o?.start(),()=>{o?.destroy(),r.current=null,i.current=null;}},[]),s?{system:r.current,statusPlugin:i.current}:r.current}function we(e,t={}){let{facts:r,derived:i,status:s,...o}=t,n=r??[],u=i??[],l=n.length===0&&u.length===0,S=s?B(e,{status:true,...o}):B(e,o),c=s?S.system:S,g=s?S.statusPlugin:void 0,y=react.useMemo(()=>l?Object.keys(c.derive):[],[c,l]),D=react.useCallback(p=>{let I=[];return l?(I.push(c.facts.$store.subscribeAll(p)),y.length>0&&I.push(c.subscribe(y,p))):(n.length>0&&I.push(c.facts.$store.subscribe(n,p)),u.length>0&&I.push(c.subscribe(u,p))),()=>{for(let P of I)P();}},[c,l,...n,...u,...y]),h=react.useRef(M),R=react.useRef(M),a=react.useRef(null),x=react.useCallback(()=>{let p,I,P,N;if(l){p=c.facts.$store.toObject(),P=Object.keys(p),I={};for(let k of y)I[k]=c.read(k);N=y;}else {p={};for(let k of n)p[k]=c.facts[k];P=n,I={};for(let k of u)I[k]=c.read(k);N=u;}let C=h.current!==M;if(C){let k=h.current;if(Object.keys(k).length!==P.length)C=false;else for(let V of P)if(!Object.is(k[V],p[V])){C=false;break}}let q=R.current!==M;if(q){let k=R.current;if(Object.keys(k).length!==N.length)q=false;else for(let V of N)if(!Object.is(k[V],I[V])){q=false;break}}let z=C?h.current:p,H=q?R.current:I;return C||(h.current=p),q||(R.current=I),C&&q&&a.current||(a.current={facts:z,derived:H}),a.current},[c,l,...n,...u,...y]),b=react.useSyncExternalStore(D,x,x),K=react.useCallback(p=>c.dispatch(p),[c]),F=pe(c),T={system:c,dispatch:K,events:F,facts:b.facts,derived:b.derived};return s&&g?{...T,statusPlugin:g}:T}function Ke({system:e,position:t="bottom-right",defaultOpen:r=false}){let[i,s]=react.useState(r),o=react.useRef(null),{isSettled:n,unmet:u,inflight:l}=L(e);react.useEffect(()=>{i&&o.current&&o.current.focus();},[i]);let S=react.useCallback(a=>e.facts.$store.subscribeAll(a),[e]),c=react.useRef(M),g=react.useCallback(()=>{let a=e.facts.$store.toObject();if(c.current!==M){let x=Object.keys(c.current),b=Object.keys(a);if(x.length===b.length){let K=true;for(let F of b)if(!Object.is(c.current[F],a[F])){K=false;break}if(K)return c.current}}return c.current=a,a},[e]),y=react.useSyncExternalStore(S,g,g);if(process.env.NODE_ENV==="production")return null;let D={position:"fixed",zIndex:99999,...t.includes("bottom")?{bottom:12}:{top:12},...t.includes("right")?{right:12}:{left:12}};if(!i)return jsxRuntime.jsx("button",{type:"button",onClick:()=>s(true),"aria-label":`Open Directive DevTools${n?"":" (system working)"}`,"aria-expanded":false,style:{...D,background:"#1a1a2e",color:"#e0e0e0",border:"1px solid #333",borderRadius:6,padding:"6px 12px",cursor:"pointer",fontFamily:"monospace",fontSize:12},children:n?"Directive":"Directive..."});let h=Object.keys(e.derive),R={};for(let a of h)try{R[a]=e.read(a);}catch{R[a]="<error>";}return jsxRuntime.jsxs("div",{role:"region","aria-label":"Directive DevTools",tabIndex:-1,onKeyDown:a=>{a.key==="Escape"&&s(false);},style:{...D,background:"#1a1a2e",color:"#e0e0e0",border:"1px solid #333",borderRadius:8,padding:12,fontFamily:"monospace",fontSize:11,maxWidth:380,maxHeight:500,overflow:"auto",boxShadow:"0 4px 20px rgba(0,0,0,0.5)"},children:[jsxRuntime.jsxs("div",{style:{display:"flex",justifyContent:"space-between",marginBottom:8},children:[jsxRuntime.jsx("strong",{style:{color:"#7c8aff"},children:"Directive DevTools"}),jsxRuntime.jsx("button",{ref:o,type:"button",onClick:()=>s(false),"aria-label":"Close DevTools",style:{background:"none",border:"none",color:"#888",cursor:"pointer",fontSize:14},children:"\xD7"})]}),jsxRuntime.jsx("div",{style:{marginBottom:6},"aria-live":"polite",children:jsxRuntime.jsx("span",{style:{color:n?"#4ade80":"#fbbf24"},children:n?"Settled":"Working..."})}),jsxRuntime.jsxs("details",{open:true,children:[jsxRuntime.jsxs("summary",{style:{cursor:"pointer",color:"#7c8aff",marginBottom:4},children:["Facts (",Object.keys(y).length,")"]}),jsxRuntime.jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:11},children:[jsxRuntime.jsx("thead",{children:jsxRuntime.jsxs("tr",{children:[jsxRuntime.jsx("th",{style:{textAlign:"left",padding:"2px 4px",color:"#7c8aff"},children:"Key"}),jsxRuntime.jsx("th",{style:{textAlign:"left",padding:"2px 4px",color:"#7c8aff"},children:"Value"})]})}),jsxRuntime.jsx("tbody",{children:Object.entries(y).map(([a,x])=>{let b;try{b=typeof x=="object"?JSON.stringify(x):String(x);}catch{b="<error>";}return jsxRuntime.jsxs("tr",{style:{borderBottom:"1px solid #2a2a4a"},children:[jsxRuntime.jsx("td",{style:{padding:"2px 4px",color:"#a0a0c0"},children:a}),jsxRuntime.jsx("td",{style:{padding:"2px 4px"},children:b})]},a)})})]})]}),h.length>0&&jsxRuntime.jsxs("details",{children:[jsxRuntime.jsxs("summary",{style:{cursor:"pointer",color:"#7c8aff",marginBottom:4},children:["Derivations (",h.length,")"]}),jsxRuntime.jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:11},children:[jsxRuntime.jsx("thead",{children:jsxRuntime.jsxs("tr",{children:[jsxRuntime.jsx("th",{style:{textAlign:"left",padding:"2px 4px",color:"#7c8aff"},children:"Key"}),jsxRuntime.jsx("th",{style:{textAlign:"left",padding:"2px 4px",color:"#7c8aff"},children:"Value"})]})}),jsxRuntime.jsx("tbody",{children:Object.entries(R).map(([a,x])=>jsxRuntime.jsxs("tr",{style:{borderBottom:"1px solid #2a2a4a"},children:[jsxRuntime.jsx("td",{style:{padding:"2px 4px",color:"#a0a0c0"},children:a}),jsxRuntime.jsx("td",{style:{padding:"2px 4px"},children:typeof x=="object"?JSON.stringify(x):String(x)})]},a))})]})]}),l.length>0&&jsxRuntime.jsxs("details",{open:true,children:[jsxRuntime.jsxs("summary",{style:{cursor:"pointer",color:"#fbbf24",marginBottom:4},children:["Inflight (",l.length,")"]}),jsxRuntime.jsx("ul",{style:{margin:0,paddingLeft:16},children:l.map(a=>jsxRuntime.jsxs("li",{style:{fontSize:11},children:[a.resolverId," (",a.id,")"]},a.id))})]}),u.length>0&&jsxRuntime.jsxs("details",{open:true,children:[jsxRuntime.jsxs("summary",{style:{cursor:"pointer",color:"#f87171",marginBottom:4},children:["Unmet (",u.length,")"]}),jsxRuntime.jsx("ul",{style:{margin:0,paddingLeft:16},children:u.map(a=>jsxRuntime.jsxs("li",{style:{fontSize:11},children:[a.requirement.type," from ",a.fromConstraint]},a.id))})]})]})}function pe(e){return adapterUtils.assertSystem("useEvents",e),react.useMemo(()=>e.events,[e])}function Fe(e,t){adapterUtils.assertSystem("useExplain",e);let r=react.useCallback(s=>{let o=e.facts.$store.subscribeAll(s),n=e.onSettledChange(s);return ()=>{o(),n();}},[e]),i=react.useCallback(()=>e.explain(t),[e,t]);return react.useSyncExternalStore(r,i,i)}function Ee(e,t){adapterUtils.assertSystem("useConstraintStatus",e);let r=L(e);return react.useMemo(()=>{let i=e.inspect();return t?i.constraints.find(s=>s.id===t)??null:i.constraints},[e,t,r])}function Te(e,t,r){adapterUtils.assertSystem("useOptimisticUpdate",e);let[i,s]=react.useState(false),[o,n]=react.useState(null),u=react.useRef(null),l=react.useCallback(()=>{u.current&&(e.restore(u.current),u.current=null),s(false),n(null);},[e]),S=react.useCallback(c=>{u.current=e.getSnapshot(),s(true),n(null),e.batch(c);},[e]);return react.useEffect(()=>{if(!(!t||!r||!i))return t.subscribe(()=>{let c=t.getStatus(r);!c.isLoading&&!c.hasError?(u.current=null,s(false)):c.hasError&&(n(c.lastError),l());})},[t,r,i,l]),{mutate:S,isPending:i,error:o,rollback:l}}var W=react.createContext(null);function Pe({snapshot:e,children:t}){return jsxRuntime.jsx(W.Provider,{value:e,children:t})}function Ce(e,t){let r=react.useContext(W),i=react.useMemo(()=>r?.data?{...t??{},initialFacts:{...t?.initialFacts??{},...r.data}}:t??{},[r,t]);return B(e,i)}Object.defineProperty(exports,"shallowEqual",{enumerable:true,get:function(){return adapterUtils.shallowEqual}});exports.DirectiveDevTools=Ke;exports.DirectiveHydrator=Pe;exports.useConstraintStatus=Ee;exports.useDerived=he;exports.useDirective=we;exports.useDirectiveRef=B;exports.useDispatch=xe;exports.useEvents=pe;exports.useExplain=Fe;exports.useFact=me;exports.useHydratedSystem=Ce;exports.useInspect=L;exports.useOptimisticUpdate=Te;exports.useRequirementStatus=Me;exports.useSelector=Re;exports.useSuspenseRequirement=Ie;exports.useTimeTravel=ke;exports.useWatch=De;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';var react=require('react'),core=require('@directive-run/core'),adapterUtils=require('@directive-run/core/adapter-utils'),jsxRuntime=require('react/jsx-runtime');var k=Symbol("directive.uninitialized");function me(e,t){return adapterUtils.assertSystem("useFact",e),process.env.NODE_ENV!=="production"&&typeof t=="function"&&console.error("[Directive] useFact() received a function. Did you mean useSelector()? useFact() takes a string key or array of keys, not a selector function."),Array.isArray(t)?oe(e,t):se(e,t)}function se(e,t){process.env.NODE_ENV!=="production"&&(t in e.facts.$store.toObject()||console.warn(`[Directive] useFact("${t}") \u2014 fact not found in store. Check that "${t}" is defined in your module's schema.`));let r=react.useCallback(s=>e.facts.$store.subscribe([t],s),[e,t]),i=react.useCallback(()=>e.facts[t],[e,t]);return react.useSyncExternalStore(r,i,i)}function oe(e,t){let r=react.useRef(k),i=react.useCallback(o=>e.facts.$store.subscribe(t,o),[e,...t]),s=react.useCallback(()=>{let o={};for(let n of t)o[n]=e.facts[n];if(r.current!==k){let n=true;for(let u of t)if(!Object.is(r.current[u],o[u])){n=false;break}if(n)return r.current}return r.current=o,o},[e,...t]);return react.useSyncExternalStore(i,s,s)}function he(e,t){return adapterUtils.assertSystem("useDerived",e),process.env.NODE_ENV!=="production"&&typeof t=="function"&&console.error("[Directive] useDerived() received a function. Did you mean useSelector()? useDerived() takes a string key or array of keys, not a selector function."),Array.isArray(t)?ue(e,t):ie(e,t)}function ie(e,t){process.env.NODE_ENV!=="production"&&(t in e.derive||console.warn(`[Directive] useDerived("${t}") \u2014 derivation not found. Check that "${t}" is defined in your module's derive property.`));let r=react.useCallback(s=>e.subscribe([t],s),[e,t]),i=react.useCallback(()=>e.read(t),[e,t]);return react.useSyncExternalStore(r,i,i)}function ue(e,t){let r=react.useRef(k),i=react.useCallback(o=>e.subscribe(t,o),[e,...t]),s=react.useCallback(()=>{let o={};for(let n of t)o[n]=e.read(n);if(r.current!==k){let n=true;for(let u of t)if(!Object.is(r.current[u],o[u])){n=false;break}if(n)return r.current}return r.current=o,o},[e,...t]);return react.useSyncExternalStore(i,s,s)}function Re(e,t,r,i){let s,o=false,n=i??adapterUtils.defaultEquality;r!==void 0&&(s=r,o=true),process.env.NODE_ENV!=="production"&&!e&&!o&&console.error("[Directive] useSelector() received a null/undefined system without a default value. Provide a default value as the 3rd parameter: useSelector(system, selector, defaultValue)");let u=react.useRef(t),d=react.useRef(n),S=react.useRef(s);u.current=t,d.current=n,S.current=s;let c=react.useRef([]),g=react.useRef([]),y=react.useRef(k),D=react.useRef([]),h=react.useMemo(()=>e?new Set(Object.keys(e.derive)):new Set,[e]),R=react.useCallback(()=>e?adapterUtils.runTrackedSelector(e,h,u.current):{value:S.current,factKeys:[],deriveKeys:[]},[e,h]),a=react.useCallback(b=>{if(!e)return ()=>{};let K=()=>{for(let p of D.current)p();D.current=[];let{factKeys:F,deriveKeys:T}=R();c.current=F,g.current=T,F.length>0?D.current.push(e.facts.$store.subscribe(F,()=>{let p=R();adapterUtils.depsChanged(c.current,p.factKeys,g.current,p.deriveKeys)&&K(),b();})):T.length===0&&D.current.push(e.facts.$store.subscribeAll(b)),T.length>0&&D.current.push(e.subscribe(T,()=>{let p=R();adapterUtils.depsChanged(c.current,p.factKeys,g.current,p.deriveKeys)&&K(),b();}));};return K(),()=>{for(let F of D.current)F();D.current=[];}},[e,R]),x=react.useCallback(()=>{let b;if(!e)b=S.current;else {let{value:K}=R();b=K===void 0&&o?S.current:K;}return y.current!==k&&d.current(y.current,b)?y.current:(y.current=b,b)},[R,e,o]);return react.useSyncExternalStore(a,x,x)}function xe(e){return adapterUtils.assertSystem("useDispatch",e),react.useCallback(t=>{e.dispatch(t);},[e])}function De(e,t,r){adapterUtils.assertSystem("useWatch",e);let i=react.useRef(r);i.current=r,react.useEffect(()=>e.watch(t,(s,o)=>{i.current(s,o);}),[e,t]);}function L(e,t){adapterUtils.assertSystem("useInspect",e);let r=ae(e),i=t?.throttleMs,[s,o]=react.useState(r),n=react.useRef(null);return react.useEffect(()=>{if(!i||i<=0){n.current?.cleanup(),n.current=null;return}return n.current?.cleanup(),n.current=adapterUtils.createThrottle((...u)=>{o(u[0]);},i),()=>{n.current?.cleanup(),n.current=null;}},[i]),react.useEffect(()=>{n.current&&n.current.throttled(r);},[r]),!i||i<=0?r:s}function ce(e){return adapterUtils.computeInspectState(e)}function ae(e){let t=react.useRef(null),r=react.useRef([]),i=react.useRef([]),s=react.useRef(null),o=react.useCallback(u=>{let d=e.facts.$store.subscribeAll(u),S=e.onSettledChange(u);return ()=>{d(),S();}},[e]),n=react.useCallback(()=>{let u=ce(e),d=u.unmet.length===r.current.length&&u.unmet.every((g,y)=>g.id===r.current[y]),S=u.inflight.length===i.current.length&&u.inflight.every((g,y)=>g.id===i.current[y]),c=u.isSettled===s.current;return d&&S&&c&&t.current?t.current:(t.current=u,r.current=u.unmet.map(g=>g.id),i.current=u.inflight.map(g=>g.id),s.current=u.isSettled,u)},[e]);return react.useSyncExternalStore(o,n,n)}function Me(e){adapterUtils.assertSystem("useTimeTravel",e);let t=react.useRef(null),r=react.useCallback(s=>e.onTimeTravelChange(s),[e]),i=react.useCallback(()=>{let s=adapterUtils.buildTimeTravelState(e);return s?(t.current&&t.current.canUndo===s.canUndo&&t.current.canRedo===s.canRedo&&t.current.currentIndex===s.currentIndex&&t.current.totalSnapshots===s.totalSnapshots&&t.current.isPaused===s.isPaused||(t.current=s),t.current):null},[e]);return react.useSyncExternalStore(r,i,i)}function ke(e,t){return Array.isArray(t)?de(e,t):le(e,t)}function le(e,t){let r=react.useRef(k),i=react.useCallback(o=>e.subscribe(o),[e]),s=react.useCallback(()=>{let o=e.getStatus(t);if(r.current!==k){let n=r.current;if(n.pending===o.pending&&n.inflight===o.inflight&&n.failed===o.failed&&n.isLoading===o.isLoading&&n.hasError===o.hasError&&n.lastError===o.lastError)return r.current}return r.current=o,o},[e,t]);return react.useSyncExternalStore(i,s,s)}function de(e,t){let r=react.useRef(null),i=react.useRef(""),s=react.useCallback(n=>e.subscribe(n),[e]),o=react.useCallback(()=>{let n={},u=[];for(let S of t){let c=e.getStatus(S);n[S]=c,u.push(`${S}:${c.pending}:${c.inflight}:${c.failed}:${c.hasError}:${c.lastError?.message??""}`);}let d=u.join("|");return d!==i.current&&(i.current=d,r.current=n),r.current??n},[e,...t]);return react.useSyncExternalStore(s,o,o)}var $=new WeakMap;function _(e){let t=$.get(e);return t||(t=new Map,$.set(e,t)),t}function Ie(e,t){return Array.isArray(t)?Se(e,t):fe(e,t)}function fe(e,t){let r=e.getStatus(t);if(r.hasError&&r.lastError)throw r.lastError;if(r.isLoading){let i=_(e),s=i.get(t);throw s||(s=new Promise(o=>{let n=e.subscribe(()=>{e.getStatus(t).isLoading||(i.delete(t),n(),o());});}),i.set(t,s)),s}return r}function Se(e,t){let r={},i=false,s=null;for(let o of t){let n=e.getStatus(o);r[o]=n,n.hasError&&n.lastError&&!s&&(s=n.lastError),n.isLoading&&(i=true);}if(s)throw s;if(i){let o=_(e),n=t.slice().sort().join(","),u=o.get(n);throw u||(u=new Promise(d=>{let S=e.subscribe(()=>{t.every(g=>!e.getStatus(g).isLoading)&&(o.delete(n),S(),d());});}),o.set(n,u)),u}return r}function B(e,t){let r=react.useRef(null),i=react.useRef(null),s=t?.status===true;if(!r.current){let o="id"in e&&"schema"in e,n=o?e:e.module,u=o?{}:e,d=t?.plugins??u.plugins??[],S=t?.debug??u.debug,c=t?.errorBoundary??u.errorBoundary,g=t?.tickMs??u.tickMs,y=t?.zeroConfig??u.zeroConfig,D=t?.initialFacts??u.initialFacts,h=[...d];s&&(i.current=core.createRequirementStatusPlugin(),h=[...h,i.current.plugin]),r.current=core.createSystem({module:n,plugins:h.length>0?h:void 0,debug:S,errorBoundary:c,tickMs:g,zeroConfig:y,initialFacts:D});}return react.useEffect(()=>{let o=r.current;return o?.start(),()=>{o?.destroy(),r.current=null,i.current=null;}},[]),s?{system:r.current,statusPlugin:i.current}:r.current}function we(e,t={}){let{facts:r,derived:i,status:s,...o}=t,n=r??[],u=i??[],d=n.length===0&&u.length===0,S=s?B(e,{status:true,...o}):B(e,o),c=s?S.system:S,g=s?S.statusPlugin:void 0,y=react.useMemo(()=>d?Object.keys(c.derive):[],[c,d]),D=react.useCallback(p=>{let I=[];return d?(I.push(c.facts.$store.subscribeAll(p)),y.length>0&&I.push(c.subscribe(y,p))):(n.length>0&&I.push(c.facts.$store.subscribe(n,p)),u.length>0&&I.push(c.subscribe(u,p))),()=>{for(let P of I)P();}},[c,d,...n,...u,...y]),h=react.useRef(k),R=react.useRef(k),a=react.useRef(null),x=react.useCallback(()=>{let p,I,P,A;if(d){p=c.facts.$store.toObject(),P=Object.keys(p),I={};for(let M of y)I[M]=c.read(M);A=y;}else {p={};for(let M of n)p[M]=c.facts[M];P=n,I={};for(let M of u)I[M]=c.read(M);A=u;}let C=h.current!==k;if(C){let M=h.current;if(Object.keys(M).length!==P.length)C=false;else for(let U of P)if(!Object.is(M[U],p[U])){C=false;break}}let O=R.current!==k;if(O){let M=R.current;if(Object.keys(M).length!==A.length)O=false;else for(let U of A)if(!Object.is(M[U],I[U])){O=false;break}}let W=C?h.current:p,H=O?R.current:I;return C||(h.current=p),O||(R.current=I),C&&O&&a.current||(a.current={facts:W,derived:H}),a.current},[c,d,...n,...u,...y]),b=react.useSyncExternalStore(D,x,x),K=react.useCallback(p=>c.dispatch(p),[c]),F=pe(c),T={system:c,dispatch:K,events:F,facts:b.facts,derived:b.derived};return s&&g?{...T,statusPlugin:g}:T}function Ke({system:e,position:t="bottom-right",defaultOpen:r=false}){let[i,s]=react.useState(r),o=react.useRef(null),{isSettled:n,unmet:u,inflight:d}=L(e);react.useEffect(()=>{i&&o.current&&o.current.focus();},[i]);let S=react.useCallback(a=>e.facts.$store.subscribeAll(a),[e]),c=react.useRef(k),g=react.useCallback(()=>{let a=e.facts.$store.toObject();if(c.current!==k){let x=Object.keys(c.current),b=Object.keys(a);if(x.length===b.length){let K=true;for(let F of b)if(!Object.is(c.current[F],a[F])){K=false;break}if(K)return c.current}}return c.current=a,a},[e]),y=react.useSyncExternalStore(S,g,g);if(process.env.NODE_ENV==="production")return null;let D={position:"fixed",zIndex:99999,...t.includes("bottom")?{bottom:12}:{top:12},...t.includes("right")?{right:12}:{left:12}};if(!i)return jsxRuntime.jsx("button",{type:"button",onClick:()=>s(true),"aria-label":`Open Directive DevTools${n?"":" (system working)"}`,"aria-expanded":false,style:{...D,background:"#1a1a2e",color:"#e0e0e0",border:"1px solid #333",borderRadius:6,padding:"6px 12px",cursor:"pointer",fontFamily:"monospace",fontSize:12},children:n?"Directive":"Directive..."});let h=Object.keys(e.derive),R={};for(let a of h)try{R[a]=e.read(a);}catch{R[a]="<error>";}return jsxRuntime.jsxs("div",{role:"region","aria-label":"Directive DevTools",tabIndex:-1,onKeyDown:a=>{a.key==="Escape"&&s(false);},style:{...D,background:"#1a1a2e",color:"#e0e0e0",border:"1px solid #333",borderRadius:8,padding:12,fontFamily:"monospace",fontSize:11,maxWidth:380,maxHeight:500,overflow:"auto",boxShadow:"0 4px 20px rgba(0,0,0,0.5)"},children:[jsxRuntime.jsxs("div",{style:{display:"flex",justifyContent:"space-between",marginBottom:8},children:[jsxRuntime.jsx("strong",{style:{color:"#7c8aff"},children:"Directive DevTools"}),jsxRuntime.jsx("button",{ref:o,type:"button",onClick:()=>s(false),"aria-label":"Close DevTools",style:{background:"none",border:"none",color:"#888",cursor:"pointer",fontSize:14},children:"\xD7"})]}),jsxRuntime.jsx("div",{style:{marginBottom:6},"aria-live":"polite",children:jsxRuntime.jsx("span",{style:{color:n?"#4ade80":"#fbbf24"},children:n?"Settled":"Working..."})}),jsxRuntime.jsxs("details",{open:true,children:[jsxRuntime.jsxs("summary",{style:{cursor:"pointer",color:"#7c8aff",marginBottom:4},children:["Facts (",Object.keys(y).length,")"]}),jsxRuntime.jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:11},children:[jsxRuntime.jsx("thead",{children:jsxRuntime.jsxs("tr",{children:[jsxRuntime.jsx("th",{style:{textAlign:"left",padding:"2px 4px",color:"#7c8aff"},children:"Key"}),jsxRuntime.jsx("th",{style:{textAlign:"left",padding:"2px 4px",color:"#7c8aff"},children:"Value"})]})}),jsxRuntime.jsx("tbody",{children:Object.entries(y).map(([a,x])=>{let b;try{b=typeof x=="object"?JSON.stringify(x):String(x);}catch{b="<error>";}return jsxRuntime.jsxs("tr",{style:{borderBottom:"1px solid #2a2a4a"},children:[jsxRuntime.jsx("td",{style:{padding:"2px 4px",color:"#a0a0c0"},children:a}),jsxRuntime.jsx("td",{style:{padding:"2px 4px"},children:b})]},a)})})]})]}),h.length>0&&jsxRuntime.jsxs("details",{children:[jsxRuntime.jsxs("summary",{style:{cursor:"pointer",color:"#7c8aff",marginBottom:4},children:["Derivations (",h.length,")"]}),jsxRuntime.jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:11},children:[jsxRuntime.jsx("thead",{children:jsxRuntime.jsxs("tr",{children:[jsxRuntime.jsx("th",{style:{textAlign:"left",padding:"2px 4px",color:"#7c8aff"},children:"Key"}),jsxRuntime.jsx("th",{style:{textAlign:"left",padding:"2px 4px",color:"#7c8aff"},children:"Value"})]})}),jsxRuntime.jsx("tbody",{children:Object.entries(R).map(([a,x])=>jsxRuntime.jsxs("tr",{style:{borderBottom:"1px solid #2a2a4a"},children:[jsxRuntime.jsx("td",{style:{padding:"2px 4px",color:"#a0a0c0"},children:a}),jsxRuntime.jsx("td",{style:{padding:"2px 4px"},children:typeof x=="object"?JSON.stringify(x):String(x)})]},a))})]})]}),d.length>0&&jsxRuntime.jsxs("details",{open:true,children:[jsxRuntime.jsxs("summary",{style:{cursor:"pointer",color:"#fbbf24",marginBottom:4},children:["Inflight (",d.length,")"]}),jsxRuntime.jsx("ul",{style:{margin:0,paddingLeft:16},children:d.map(a=>jsxRuntime.jsxs("li",{style:{fontSize:11},children:[a.resolverId," (",a.id,")"]},a.id))})]}),u.length>0&&jsxRuntime.jsxs("details",{open:true,children:[jsxRuntime.jsxs("summary",{style:{cursor:"pointer",color:"#f87171",marginBottom:4},children:["Unmet (",u.length,")"]}),jsxRuntime.jsx("ul",{style:{margin:0,paddingLeft:16},children:u.map(a=>jsxRuntime.jsxs("li",{style:{fontSize:11},children:[a.requirement.type," from ",a.fromConstraint]},a.id))})]})]})}function pe(e){return adapterUtils.assertSystem("useEvents",e),react.useMemo(()=>e.events,[e])}function Fe(e,t){adapterUtils.assertSystem("useExplain",e);let r=react.useCallback(s=>{let o=e.facts.$store.subscribeAll(s),n=e.onSettledChange(s);return ()=>{o(),n();}},[e]),i=react.useCallback(()=>e.explain(t),[e,t]);return react.useSyncExternalStore(r,i,i)}function Ee(e,t){adapterUtils.assertSystem("useConstraintStatus",e);let r=L(e);return react.useMemo(()=>{let i=e.inspect();return t?i.constraints.find(s=>s.id===t)??null:i.constraints},[e,t,r])}function Te(e,t,r){adapterUtils.assertSystem("useOptimisticUpdate",e);let[i,s]=react.useState(false),[o,n]=react.useState(null),u=react.useRef(null),d=react.useCallback(()=>{u.current&&(e.restore(u.current),u.current=null),s(false),n(null);},[e]),S=react.useCallback(c=>{u.current=e.getSnapshot(),s(true),n(null),e.batch(c);},[e]);return react.useEffect(()=>{if(!(!t||!r||!i))return t.subscribe(()=>{let c=t.getStatus(r);!c.isLoading&&!c.hasError?(u.current=null,s(false)):c.hasError&&(n(c.lastError),d());})},[t,r,i,d]),{mutate:S,isPending:i,error:o,rollback:d}}var z=react.createContext(null);function Pe({snapshot:e,children:t}){return jsxRuntime.jsx(z.Provider,{value:e,children:t})}function Ce(e,t){let r=react.useContext(z),i=react.useMemo(()=>r?.data?{...t??{},initialFacts:{...t?.initialFacts??{},...r.data}}:t??{},[r,t]);return B(e,i)}Object.defineProperty(exports,"shallowEqual",{enumerable:true,get:function(){return adapterUtils.shallowEqual}});exports.DirectiveDevTools=Ke;exports.DirectiveHydrator=Pe;exports.useConstraintStatus=Ee;exports.useDerived=he;exports.useDirective=we;exports.useDirectiveRef=B;exports.useDispatch=xe;exports.useEvents=pe;exports.useExplain=Fe;exports.useFact=me;exports.useHydratedSystem=Ce;exports.useInspect=L;exports.useOptimisticUpdate=Te;exports.useRequirementStatus=ke;exports.useSelector=Re;exports.useSuspenseRequirement=Ie;exports.useTimeTravel=Me;exports.useWatch=De;//# sourceMappingURL=index.cjs.map
2
2
  //# sourceMappingURL=index.cjs.map