@daltonr/pathwrite-react 0.1.1

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/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Richard Dalton
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,103 @@
1
+ # @daltonr/pathwrite-react
2
+
3
+ React hooks over `@daltonr/pathwrite-core`. Exposes path state as reactive React state via `useSyncExternalStore`, with stable action callbacks and an optional context provider.
4
+
5
+ ## Setup
6
+
7
+ ### Option A — `usePath` hook (component-scoped)
8
+
9
+ Each call to `usePath` creates an isolated path engine instance.
10
+
11
+ ```tsx
12
+ import { usePath } from "@daltonr/pathwrite-react";
13
+
14
+ function MyPathHost() {
15
+ const { snapshot, start, next, previous, cancel, setData } = usePath({
16
+ onEvent(event) {
17
+ console.log(event);
18
+ }
19
+ });
20
+
21
+ return (
22
+ <div>
23
+ {snapshot ? (
24
+ <>
25
+ <h2>{snapshot.stepTitle ?? snapshot.stepId}</h2>
26
+ <p>Step {snapshot.stepIndex + 1} of {snapshot.stepCount}</p>
27
+ <button onClick={previous} disabled={snapshot.isNavigating}>Back</button>
28
+ <button onClick={next} disabled={snapshot.isNavigating}>
29
+ {snapshot.isLastStep ? "Finish" : "Next"}
30
+ </button>
31
+ <button onClick={cancel}>Cancel</button>
32
+ </>
33
+ ) : (
34
+ <button onClick={() => start(myPath)}>Start Path</button>
35
+ )}
36
+ </div>
37
+ );
38
+ }
39
+ ```
40
+
41
+ ### Option B — `PathProvider` + `usePathContext` (shared across components)
42
+
43
+ Wrap a subtree so that multiple components can read and drive the same path instance.
44
+
45
+ ```tsx
46
+ import { PathProvider, usePathContext } from "@daltonr/pathwrite-react";
47
+
48
+ function App() {
49
+ return (
50
+ <PathProvider onEvent={(e) => console.log(e)}>
51
+ <StepDisplay />
52
+ <NavButtons />
53
+ </PathProvider>
54
+ );
55
+ }
56
+
57
+ function StepDisplay() {
58
+ const { snapshot } = usePathContext();
59
+ if (!snapshot) return <p>No path running.</p>;
60
+ return <h2>{snapshot.stepTitle ?? snapshot.stepId}</h2>;
61
+ }
62
+
63
+ function NavButtons() {
64
+ const { snapshot, next, previous } = usePathContext();
65
+ if (!snapshot) return null;
66
+ return (
67
+ <>
68
+ <button onClick={previous}>Back</button>
69
+ <button onClick={next}>Next</button>
70
+ </>
71
+ );
72
+ }
73
+ ```
74
+
75
+ ## `usePath` API
76
+
77
+ ### Options
78
+
79
+ | Option | Type | Description |
80
+ |--------|------|-------------|
81
+ | `onEvent` | `(event: PathEvent) => void` | Called for every engine event. The callback ref is kept current — changing it does **not** re-subscribe to the engine. |
82
+
83
+ ### Return value
84
+
85
+ | Property | Type | Description |
86
+ |----------|------|-------------|
87
+ | `snapshot` | `PathSnapshot \| null` | Current snapshot. `null` when no path is active. Triggers a React re-render on change. |
88
+ | `start(definition, data?)` | `function` | Start or re-start a path. |
89
+ | `startSubPath(definition, data?)` | `function` | Push a sub-path. Requires an active path. |
90
+ | `next()` | `function` | Advance one step. Completes the path on the last step. |
91
+ | `previous()` | `function` | Go back one step. Cancels the path from the first step. |
92
+ | `cancel()` | `function` | Cancel the active path (or sub-path). |
93
+ | `goToStep(stepId)` | `function` | Jump directly to a step by ID. Calls `onLeave` / `onEnter` but bypasses guards and `shouldSkip`. |
94
+ | `setData(key, value)` | `function` | Update a single data value; triggers re-render via `stateChanged`. |
95
+
96
+ All action callbacks are **referentially stable** — safe to pass as props or include in dependency arrays without causing unnecessary re-renders.
97
+
98
+ ## Design notes
99
+
100
+ - **`useSyncExternalStore`** — the hook subscribes to the core `PathEngine` using React 18's `useSyncExternalStore`, giving tear-free reads with no `useEffect` timing gaps.
101
+ - **Ref-based callback** — `onEvent` is stored in a ref so that a new closure on every render does not cause a re-subscription.
102
+ - **No RxJS** — unlike the Angular adapter, there is no RxJS dependency. The hook is pure React.
103
+
@@ -0,0 +1,102 @@
1
+ import type { PropsWithChildren, ReactElement, ReactNode } from "react";
2
+ import { PathData, PathDefinition, PathEvent, PathSnapshot } from "@daltonr/pathwrite-core";
3
+ export interface UsePathOptions {
4
+ /** Called for every engine event (stateChanged, completed, cancelled, resumed). */
5
+ onEvent?: (event: PathEvent) => void;
6
+ }
7
+ export interface UsePathReturn {
8
+ /** Current path snapshot, or `null` when no path is active. Triggers a React re-render on change. */
9
+ snapshot: PathSnapshot | null;
10
+ /** Start (or restart) a path. */
11
+ start: (path: PathDefinition, initialData?: PathData) => void;
12
+ /** Push a sub-path onto the stack. Requires an active path. */
13
+ startSubPath: (path: PathDefinition, initialData?: PathData) => void;
14
+ /** Advance one step. Completes the path on the last step. */
15
+ next: () => void;
16
+ /** Go back one step. Cancels the path from the first step. */
17
+ previous: () => void;
18
+ /** Cancel the active path (or sub-path). */
19
+ cancel: () => void;
20
+ /** Jump directly to a step by ID. Calls onLeave / onEnter but bypasses guards and shouldSkip. */
21
+ goToStep: (stepId: string) => void;
22
+ /** Update a single data value; triggers a re-render via stateChanged. */
23
+ setData: (key: string, value: unknown) => void;
24
+ }
25
+ export type PathProviderProps = PropsWithChildren<{
26
+ /** Forwarded to the internal usePath hook. */
27
+ onEvent?: (event: PathEvent) => void;
28
+ }>;
29
+ export declare function usePath(options?: UsePathOptions): UsePathReturn;
30
+ /**
31
+ * Provides a single `usePath` instance to all descendants.
32
+ * Consume with `usePathContext()`.
33
+ */
34
+ export declare function PathProvider({ children, onEvent }: PathProviderProps): ReactElement;
35
+ /**
36
+ * Access the nearest `PathProvider`'s path instance.
37
+ * Throws if used outside of a `<PathProvider>`.
38
+ */
39
+ export declare function usePathContext(): UsePathReturn;
40
+ export interface PathStepProps {
41
+ /** Must match a step `id` in the path definition. */
42
+ id: string;
43
+ children: ReactNode;
44
+ }
45
+ /**
46
+ * Wraps step content. Only renders its children when the current step matches `id`.
47
+ * Must be used inside a `<PathShell>`.
48
+ */
49
+ export declare function PathStep(_props: PathStepProps): ReactElement | null;
50
+ export interface PathShellProps {
51
+ /** The path definition to drive. */
52
+ path: PathDefinition;
53
+ /** Initial data passed to `engine.start()`. */
54
+ initialData?: PathData;
55
+ /** If true, the path is started automatically on mount. Defaults to `true`. */
56
+ autoStart?: boolean;
57
+ /** Called when the path completes. Receives the final data. */
58
+ onComplete?: (data: PathData) => void;
59
+ /** Called when the path is cancelled. Receives the data at time of cancellation. */
60
+ onCancel?: (data: PathData) => void;
61
+ /** Called for every engine event. */
62
+ onEvent?: (event: PathEvent) => void;
63
+ /** Label for the Back button. Defaults to `"Back"`. */
64
+ backLabel?: string;
65
+ /** Label for the Next button. Defaults to `"Next"`. */
66
+ nextLabel?: string;
67
+ /** Label for the Finish button (shown on the last step). Defaults to `"Finish"`. */
68
+ finishLabel?: string;
69
+ /** Label for the Cancel button. Defaults to `"Cancel"`. */
70
+ cancelLabel?: string;
71
+ /** If true, hide the Cancel button. Defaults to `false`. */
72
+ hideCancel?: boolean;
73
+ /** If true, hide the progress indicator. Defaults to `false`. */
74
+ hideProgress?: boolean;
75
+ /** Optional extra CSS class on the root element. */
76
+ className?: string;
77
+ /** Render prop to replace the entire header (progress area). Receives the snapshot. */
78
+ renderHeader?: (snapshot: PathSnapshot) => ReactNode;
79
+ /** Render prop to replace the entire footer (navigation area). Receives the snapshot and actions. */
80
+ renderFooter?: (snapshot: PathSnapshot, actions: PathShellActions) => ReactNode;
81
+ /** `<PathStep>` children. */
82
+ children: ReactNode;
83
+ }
84
+ export interface PathShellActions {
85
+ next: () => void;
86
+ previous: () => void;
87
+ cancel: () => void;
88
+ goToStep: (stepId: string) => void;
89
+ setData: (key: string, value: unknown) => void;
90
+ }
91
+ /**
92
+ * Default UI shell that renders a progress indicator, step content, and navigation
93
+ * buttons. Wrap `<PathStep>` children inside to define per-step content.
94
+ *
95
+ * ```tsx
96
+ * <PathShell path={myPath} initialData={{ name: "" }} onComplete={handleDone}>
97
+ * <PathStep id="details"><DetailsForm /></PathStep>
98
+ * <PathStep id="review"><ReviewPanel /></PathStep>
99
+ * </PathShell>
100
+ * ```
101
+ */
102
+ export declare function PathShell({ path: pathDef, initialData, autoStart, onComplete, onCancel, onEvent, backLabel, nextLabel, finishLabel, cancelLabel, hideCancel, hideProgress, className, renderHeader, renderFooter, children }: PathShellProps): ReactElement;
package/dist/index.js ADDED
@@ -0,0 +1,178 @@
1
+ import { createContext, createElement, useCallback, useContext, useEffect, useRef, useSyncExternalStore } from "react";
2
+ import { PathEngine } from "@daltonr/pathwrite-core";
3
+ // ---------------------------------------------------------------------------
4
+ // usePath hook
5
+ // ---------------------------------------------------------------------------
6
+ export function usePath(options) {
7
+ // Stable engine instance for the lifetime of the hook
8
+ const engineRef = useRef(null);
9
+ if (engineRef.current === null) {
10
+ engineRef.current = new PathEngine();
11
+ }
12
+ const engine = engineRef.current;
13
+ // Keep the onEvent callback current without changing the subscribe identity
14
+ const onEventRef = useRef(options?.onEvent);
15
+ onEventRef.current = options?.onEvent;
16
+ // Cached snapshot — updated only inside the subscribe callback
17
+ const snapshotRef = useRef(null);
18
+ const subscribe = useCallback((callback) => engine.subscribe((event) => {
19
+ if (event.type === "stateChanged" || event.type === "resumed") {
20
+ snapshotRef.current = event.snapshot;
21
+ }
22
+ else if (event.type === "completed" || event.type === "cancelled") {
23
+ snapshotRef.current = null;
24
+ }
25
+ onEventRef.current?.(event);
26
+ callback();
27
+ }), [engine]);
28
+ const getSnapshot = useCallback(() => snapshotRef.current, []);
29
+ const snapshot = useSyncExternalStore(subscribe, getSnapshot);
30
+ // Stable action callbacks
31
+ const start = useCallback((path, initialData = {}) => engine.start(path, initialData), [engine]);
32
+ const startSubPath = useCallback((path, initialData = {}) => engine.startSubPath(path, initialData), [engine]);
33
+ const next = useCallback(() => engine.next(), [engine]);
34
+ const previous = useCallback(() => engine.previous(), [engine]);
35
+ const cancel = useCallback(() => engine.cancel(), [engine]);
36
+ const goToStep = useCallback((stepId) => engine.goToStep(stepId), [engine]);
37
+ const setData = useCallback((key, value) => engine.setData(key, value), [engine]);
38
+ return { snapshot, start, startSubPath, next, previous, cancel, goToStep, setData };
39
+ }
40
+ // ---------------------------------------------------------------------------
41
+ // Context + Provider
42
+ // ---------------------------------------------------------------------------
43
+ const PathContext = createContext(null);
44
+ /**
45
+ * Provides a single `usePath` instance to all descendants.
46
+ * Consume with `usePathContext()`.
47
+ */
48
+ export function PathProvider({ children, onEvent }) {
49
+ const path = usePath({ onEvent });
50
+ return createElement(PathContext.Provider, { value: path }, children);
51
+ }
52
+ /**
53
+ * Access the nearest `PathProvider`'s path instance.
54
+ * Throws if used outside of a `<PathProvider>`.
55
+ */
56
+ export function usePathContext() {
57
+ const ctx = useContext(PathContext);
58
+ if (ctx === null) {
59
+ throw new Error("usePathContext must be used within a <PathProvider>.");
60
+ }
61
+ return ctx;
62
+ }
63
+ /**
64
+ * Wraps step content. Only renders its children when the current step matches `id`.
65
+ * Must be used inside a `<PathShell>`.
66
+ */
67
+ export function PathStep(_props) {
68
+ // Rendering is handled by PathShell — PathStep is never rendered directly.
69
+ // It exists purely as a typed container so PathShell can inspect its props.
70
+ return null;
71
+ }
72
+ /**
73
+ * Default UI shell that renders a progress indicator, step content, and navigation
74
+ * buttons. Wrap `<PathStep>` children inside to define per-step content.
75
+ *
76
+ * ```tsx
77
+ * <PathShell path={myPath} initialData={{ name: "" }} onComplete={handleDone}>
78
+ * <PathStep id="details"><DetailsForm /></PathStep>
79
+ * <PathStep id="review"><ReviewPanel /></PathStep>
80
+ * </PathShell>
81
+ * ```
82
+ */
83
+ export function PathShell({ path: pathDef, initialData = {}, autoStart = true, onComplete, onCancel, onEvent, backLabel = "Back", nextLabel = "Next", finishLabel = "Finish", cancelLabel = "Cancel", hideCancel = false, hideProgress = false, className, renderHeader, renderFooter, children }) {
84
+ const pathReturn = usePath({
85
+ onEvent(event) {
86
+ onEvent?.(event);
87
+ if (event.type === "completed")
88
+ onComplete?.(event.data);
89
+ if (event.type === "cancelled")
90
+ onCancel?.(event.data);
91
+ }
92
+ });
93
+ const { snapshot, start, next, previous, cancel, goToStep, setData } = pathReturn;
94
+ // Auto-start on mount
95
+ const startedRef = useRef(false);
96
+ useEffect(() => {
97
+ if (autoStart && !startedRef.current) {
98
+ startedRef.current = true;
99
+ start(pathDef, initialData);
100
+ }
101
+ // eslint-disable-next-line react-hooks/exhaustive-deps
102
+ }, []);
103
+ // Resolve which <PathStep> children to display
104
+ const stepContent = resolveStepContent(children, snapshot);
105
+ if (!snapshot) {
106
+ return createElement("div", { className: cls("pw-shell", className) }, createElement("div", { className: "pw-shell__empty" }, createElement("p", null, "No active path."), !autoStart && createElement("button", {
107
+ type: "button",
108
+ className: "pw-shell__start-btn",
109
+ onClick: () => start(pathDef, initialData)
110
+ }, "Start")));
111
+ }
112
+ const actions = { next, previous, cancel, goToStep, setData };
113
+ return createElement("div", { className: cls("pw-shell", className) },
114
+ // Header — progress indicator
115
+ !hideProgress && (renderHeader
116
+ ? renderHeader(snapshot)
117
+ : defaultHeader(snapshot)),
118
+ // Body — step content
119
+ createElement("div", { className: "pw-shell__body" }, stepContent),
120
+ // Footer — navigation buttons
121
+ renderFooter
122
+ ? renderFooter(snapshot, actions)
123
+ : defaultFooter(snapshot, actions, {
124
+ backLabel, nextLabel, finishLabel, cancelLabel, hideCancel
125
+ }));
126
+ }
127
+ // ---------------------------------------------------------------------------
128
+ // Default header (progress indicator)
129
+ // ---------------------------------------------------------------------------
130
+ function defaultHeader(snapshot) {
131
+ return createElement("div", { className: "pw-shell__header" }, createElement("div", { className: "pw-shell__steps" }, ...snapshot.steps.map((step, i) => createElement("div", {
132
+ key: step.id,
133
+ className: cls("pw-shell__step", `pw-shell__step--${step.status}`)
134
+ }, createElement("span", { className: "pw-shell__step-dot" }, step.status === "completed" ? "✓" : String(i + 1)), createElement("span", { className: "pw-shell__step-label" }, step.title ?? step.id)))), createElement("div", { className: "pw-shell__track" }, createElement("div", {
135
+ className: "pw-shell__track-fill",
136
+ style: { width: `${snapshot.progress * 100}%` }
137
+ })));
138
+ }
139
+ function defaultFooter(snapshot, actions, labels) {
140
+ return createElement("div", { className: "pw-shell__footer" }, createElement("div", { className: "pw-shell__footer-left" }, !snapshot.isFirstStep && createElement("button", {
141
+ type: "button",
142
+ className: "pw-shell__btn pw-shell__btn--back",
143
+ disabled: snapshot.isNavigating,
144
+ onClick: actions.previous
145
+ }, labels.backLabel)), createElement("div", { className: "pw-shell__footer-right" }, !labels.hideCancel && createElement("button", {
146
+ type: "button",
147
+ className: "pw-shell__btn pw-shell__btn--cancel",
148
+ disabled: snapshot.isNavigating,
149
+ onClick: actions.cancel
150
+ }, labels.cancelLabel), createElement("button", {
151
+ type: "button",
152
+ className: "pw-shell__btn pw-shell__btn--next",
153
+ disabled: snapshot.isNavigating,
154
+ onClick: actions.next
155
+ }, snapshot.isLastStep ? labels.finishLabel : labels.nextLabel)));
156
+ }
157
+ // ---------------------------------------------------------------------------
158
+ // Helpers
159
+ // ---------------------------------------------------------------------------
160
+ function resolveStepContent(children, snapshot) {
161
+ if (!snapshot || !children)
162
+ return null;
163
+ const arr = Array.isArray(children) ? children : [children];
164
+ for (const child of arr) {
165
+ if (child &&
166
+ typeof child === "object" &&
167
+ "type" in child &&
168
+ child.type === PathStep &&
169
+ child.props?.id === snapshot.stepId) {
170
+ return child.props.children ?? null;
171
+ }
172
+ }
173
+ return null;
174
+ }
175
+ function cls(...parts) {
176
+ return parts.filter(Boolean).join(" ");
177
+ }
178
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,aAAa,EACb,WAAW,EACX,UAAU,EACV,SAAS,EACT,MAAM,EACN,oBAAoB,EACrB,MAAM,OAAO,CAAC;AAEf,OAAO,EAGL,UAAU,EAGX,MAAM,yBAAyB,CAAC;AAmCjC,8EAA8E;AAC9E,eAAe;AACf,8EAA8E;AAE9E,MAAM,UAAU,OAAO,CAAC,OAAwB;IAC9C,sDAAsD;IACtD,MAAM,SAAS,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAC;IAClD,IAAI,SAAS,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;QAC/B,SAAS,CAAC,OAAO,GAAG,IAAI,UAAU,EAAE,CAAC;IACvC,CAAC;IACD,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC;IAEjC,4EAA4E;IAC5E,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5C,UAAU,CAAC,OAAO,GAAG,OAAO,EAAE,OAAO,CAAC;IAEtC,+DAA+D;IAC/D,MAAM,WAAW,GAAG,MAAM,CAAsB,IAAI,CAAC,CAAC;IAEtD,MAAM,SAAS,GAAG,WAAW,CAC3B,CAAC,QAAoB,EAAE,EAAE,CACvB,MAAM,CAAC,SAAS,CAAC,CAAC,KAAgB,EAAE,EAAE;QACpC,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC9D,WAAW,CAAC,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC;QACvC,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YACpE,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;QAC7B,CAAC;QACD,UAAU,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;QAC5B,QAAQ,EAAE,CAAC;IACb,CAAC,CAAC,EACJ,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAE/D,MAAM,QAAQ,GAAG,oBAAoB,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAE9D,0BAA0B;IAC1B,MAAM,KAAK,GAAG,WAAW,CACvB,CAAC,IAAoB,EAAE,cAAwB,EAAE,EAAE,EAAE,CACnD,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,WAAW,CAAC,EACjC,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,MAAM,YAAY,GAAG,WAAW,CAC9B,CAAC,IAAoB,EAAE,cAAwB,EAAE,EAAE,EAAE,CACnD,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,WAAW,CAAC,EACxC,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IACxD,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAChE,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAE5D,MAAM,QAAQ,GAAG,WAAW,CAC1B,CAAC,MAAc,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAC3C,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,MAAM,OAAO,GAAG,WAAW,CACzB,CAAC,GAAW,EAAE,KAAc,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,EAC3D,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AACtF,CAAC;AAED,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E,MAAM,WAAW,GAAG,aAAa,CAAuB,IAAI,CAAC,CAAC;AAE9D;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAqB;IACnE,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IAClC,OAAO,aAAa,CAAC,WAAW,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC;AACxE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,GAAG,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IACpC,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAYD;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,MAAqB;IAC5C,2EAA2E;IAC3E,4EAA4E;IAC5E,OAAO,IAAI,CAAC;AACd,CAAC;AA6CD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,SAAS,CAAC,EACxB,IAAI,EAAE,OAAO,EACb,WAAW,GAAG,EAAE,EAChB,SAAS,GAAG,IAAI,EAChB,UAAU,EACV,QAAQ,EACR,OAAO,EACP,SAAS,GAAG,MAAM,EAClB,SAAS,GAAG,MAAM,EAClB,WAAW,GAAG,QAAQ,EACtB,WAAW,GAAG,QAAQ,EACtB,UAAU,GAAG,KAAK,EAClB,YAAY,GAAG,KAAK,EACpB,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,QAAQ,EACO;IACf,MAAM,UAAU,GAAG,OAAO,CAAC;QACzB,OAAO,CAAC,KAAK;YACX,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;YACjB,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW;gBAAE,UAAU,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACzD,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW;gBAAE,QAAQ,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACzD,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC;IAElF,sBAAsB;IACtB,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACjC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,SAAS,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;YACrC,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC;YAC1B,KAAK,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;QAC9B,CAAC;QACD,uDAAuD;IACzD,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,+CAA+C;IAC/C,MAAM,WAAW,GAAG,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAE3D,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,aAAa,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,GAAG,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE,EACnE,aAAa,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE,EACnD,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE,iBAAiB,CAAC,EAC3C,CAAC,SAAS,IAAI,aAAa,CAAC,QAAQ,EAAE;YACpC,IAAI,EAAE,QAAQ;YACd,SAAS,EAAE,qBAAqB;YAChC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,WAAW,CAAC;SAC3C,EAAE,OAAO,CAAC,CACZ,CACF,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAqB,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IAEhF,OAAO,aAAa,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,GAAG,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE;IACnE,8BAA8B;IAC9B,CAAC,YAAY,IAAI,CAAC,YAAY;QAC5B,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC;QACxB,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC5B,sBAAsB;IACtB,aAAa,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,gBAAgB,EAAE,EAAE,WAAW,CAAC;IAClE,8BAA8B;IAC9B,YAAY;QACV,CAAC,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC;QACjC,CAAC,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE;YAC/B,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU;SAC3D,CAAC,CACP,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,sCAAsC;AACtC,8EAA8E;AAE9E,SAAS,aAAa,CAAC,QAAsB;IAC3C,OAAO,aAAa,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,kBAAkB,EAAE,EAC3D,aAAa,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE,EACnD,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAChC,aAAa,CAAC,KAAK,EAAE;QACnB,GAAG,EAAE,IAAI,CAAC,EAAE;QACZ,SAAS,EAAE,GAAG,CAAC,gBAAgB,EAAE,mBAAmB,IAAI,CAAC,MAAM,EAAE,CAAC;KACnE,EACC,aAAa,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,oBAAoB,EAAE,EACvD,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAClD,EACD,aAAa,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,sBAAsB,EAAE,EACzD,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,EAAE,CACtB,CACF,CACF,CACF,EACD,aAAa,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE,EACnD,aAAa,CAAC,KAAK,EAAE;QACnB,SAAS,EAAE,sBAAsB;QACjC,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC,QAAQ,GAAG,GAAG,GAAG,EAAE;KAChD,CAAC,CACH,CACF,CAAC;AACJ,CAAC;AAcD,SAAS,aAAa,CACpB,QAAsB,EACtB,OAAyB,EACzB,MAAoB;IAEpB,OAAO,aAAa,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,kBAAkB,EAAE,EAC3D,aAAa,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,uBAAuB,EAAE,EACzD,CAAC,QAAQ,CAAC,WAAW,IAAI,aAAa,CAAC,QAAQ,EAAE;QAC/C,IAAI,EAAE,QAAQ;QACd,SAAS,EAAE,mCAAmC;QAC9C,QAAQ,EAAE,QAAQ,CAAC,YAAY;QAC/B,OAAO,EAAE,OAAO,CAAC,QAAQ;KAC1B,EAAE,MAAM,CAAC,SAAS,CAAC,CACrB,EACD,aAAa,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,wBAAwB,EAAE,EAC1D,CAAC,MAAM,CAAC,UAAU,IAAI,aAAa,CAAC,QAAQ,EAAE;QAC5C,IAAI,EAAE,QAAQ;QACd,SAAS,EAAE,qCAAqC;QAChD,QAAQ,EAAE,QAAQ,CAAC,YAAY;QAC/B,OAAO,EAAE,OAAO,CAAC,MAAM;KACxB,EAAE,MAAM,CAAC,WAAW,CAAC,EACtB,aAAa,CAAC,QAAQ,EAAE;QACtB,IAAI,EAAE,QAAQ;QACd,SAAS,EAAE,mCAAmC;QAC9C,QAAQ,EAAE,QAAQ,CAAC,YAAY;QAC/B,OAAO,EAAE,OAAO,CAAC,IAAI;KACtB,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAChE,CACF,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,SAAS,kBAAkB,CAAC,QAAmB,EAAE,QAA6B;IAC5E,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAExC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC5D,KAAK,MAAM,KAAK,IAAI,GAAG,EAAE,CAAC;QACxB,IACE,KAAK;YACL,OAAO,KAAK,KAAK,QAAQ;YACzB,MAAM,IAAI,KAAK;YACf,KAAK,CAAC,IAAI,KAAK,QAAQ;YACvB,KAAK,CAAC,KAAK,EAAE,EAAE,KAAK,QAAQ,CAAC,MAAM,EACnC,CAAC;YACD,OAAO,KAAK,CAAC,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC;QACtC,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,GAAG,CAAC,GAAG,KAA4C;IAC1D,OAAO,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@daltonr/pathwrite-react",
3
+ "version": "0.1.1",
4
+ "type": "module",
5
+ "license": "MIT",
6
+ "description": "React adapter for @daltonr/pathwrite-core — hooks, context provider, and optional <PathShell> default UI.",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/richardadalton/pathwrite.git",
10
+ "directory": "packages/react-adapter"
11
+ },
12
+ "keywords": [
13
+ "wizard",
14
+ "stepper",
15
+ "path",
16
+ "react",
17
+ "hooks",
18
+ "multi-step",
19
+ "workflow"
20
+ ],
21
+ "sideEffects": false,
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "import": "./dist/index.js"
26
+ }
27
+ },
28
+ "main": "dist/index.js",
29
+ "types": "dist/index.d.ts",
30
+ "files": [
31
+ "dist",
32
+ "README.md",
33
+ "LICENSE"
34
+ ],
35
+ "scripts": {
36
+ "build": "tsc -p tsconfig.json",
37
+ "clean": "rm -rf dist tsconfig.tsbuildinfo",
38
+ "prepublishOnly": "npm run clean && npm run build"
39
+ },
40
+ "peerDependencies": {
41
+ "react": ">=18.0.0"
42
+ },
43
+ "dependencies": {
44
+ "@daltonr/pathwrite-core": "^0.1.1"
45
+ },
46
+ "devDependencies": {
47
+ "react": "^18.3.1",
48
+ "react-dom": "^18.3.1",
49
+ "@types/react": "^18.3.12",
50
+ "@types/react-dom": "^18.3.1",
51
+ "@testing-library/react": "^16.1.0",
52
+ "jsdom": "^25.0.1"
53
+ },
54
+ "publishConfig": {
55
+ "access": "public"
56
+ }
57
+ }