@mmapp/react 0.1.0-alpha.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.
Files changed (98) hide show
  1. package/dist/atoms/index.d.mts +424 -0
  2. package/dist/atoms/index.d.ts +424 -0
  3. package/dist/atoms/index.js +195 -0
  4. package/dist/atoms/index.mjs +110 -0
  5. package/dist/chunk-2VJQJM7S.mjs +119 -0
  6. package/dist/index.d.mts +6999 -0
  7. package/dist/index.d.ts +6999 -0
  8. package/dist/index.js +8247 -0
  9. package/dist/index.mjs +8016 -0
  10. package/package.json +37 -0
  11. package/package.json.backup +41 -0
  12. package/src/Blueprint.ts +216 -0
  13. package/src/__tests__/Blueprint.test.ts +106 -0
  14. package/src/__tests__/action-context.test.ts +166 -0
  15. package/src/__tests__/actionCreators.test.ts +179 -0
  16. package/src/__tests__/builders.test.ts +336 -0
  17. package/src/__tests__/defineBlueprint-composition.test.ts +106 -0
  18. package/src/__tests__/factories.test.ts +229 -0
  19. package/src/__tests__/loader.test.ts +159 -0
  20. package/src/__tests__/logger.test.ts +70 -0
  21. package/src/__tests__/type-inference.test.ts +160 -0
  22. package/src/__tests__/typed-transitions.test.ts +126 -0
  23. package/src/__tests__/useModuleConfig.test.ts +61 -0
  24. package/src/actionCreators.ts +132 -0
  25. package/src/actions.ts +547 -0
  26. package/src/atoms/index.ts +600 -0
  27. package/src/authoring.ts +92 -0
  28. package/src/browser-player.ts +783 -0
  29. package/src/builders.ts +1342 -0
  30. package/src/components/ExperienceWorkflowBridge.tsx +123 -0
  31. package/src/components/PlayerProvider.tsx +43 -0
  32. package/src/components/atoms/index.tsx +269 -0
  33. package/src/components/index.ts +36 -0
  34. package/src/conditions.ts +692 -0
  35. package/src/config/defineBlueprint.ts +329 -0
  36. package/src/config/defineModel.ts +753 -0
  37. package/src/config/defineWorkspace.ts +24 -0
  38. package/src/core/WorkflowRuntime.ts +153 -0
  39. package/src/factories.ts +425 -0
  40. package/src/grammar/index.ts +173 -0
  41. package/src/hooks/index.ts +106 -0
  42. package/src/hooks/useAuth.ts +288 -0
  43. package/src/hooks/useChannel.ts +304 -0
  44. package/src/hooks/useComputed.ts +154 -0
  45. package/src/hooks/useDomainSubscription.ts +110 -0
  46. package/src/hooks/useDuringAction.ts +99 -0
  47. package/src/hooks/useExperienceState.ts +59 -0
  48. package/src/hooks/useExpressionLibrary.ts +129 -0
  49. package/src/hooks/useForm.ts +352 -0
  50. package/src/hooks/useGeolocation.ts +207 -0
  51. package/src/hooks/useMapView.ts +259 -0
  52. package/src/hooks/useMiddleware.ts +291 -0
  53. package/src/hooks/useModel.ts +363 -0
  54. package/src/hooks/useModule.ts +59 -0
  55. package/src/hooks/useModuleConfig.ts +61 -0
  56. package/src/hooks/useMutation.ts +237 -0
  57. package/src/hooks/useNotification.ts +151 -0
  58. package/src/hooks/useOnChange.ts +30 -0
  59. package/src/hooks/useOnEnter.ts +59 -0
  60. package/src/hooks/useOnEvent.ts +37 -0
  61. package/src/hooks/useOnExit.ts +27 -0
  62. package/src/hooks/useOnTransition.ts +30 -0
  63. package/src/hooks/usePackage.ts +128 -0
  64. package/src/hooks/useParams.ts +33 -0
  65. package/src/hooks/usePlayer.ts +308 -0
  66. package/src/hooks/useQuery.ts +184 -0
  67. package/src/hooks/useRealtimeQuery.ts +222 -0
  68. package/src/hooks/useRole.ts +191 -0
  69. package/src/hooks/useRouteParams.ts +100 -0
  70. package/src/hooks/useRouter.ts +347 -0
  71. package/src/hooks/useServerAction.ts +178 -0
  72. package/src/hooks/useServerState.ts +284 -0
  73. package/src/hooks/useToast.ts +164 -0
  74. package/src/hooks/useTransition.ts +39 -0
  75. package/src/hooks/useView.ts +102 -0
  76. package/src/hooks/useWhileIn.ts +48 -0
  77. package/src/hooks/useWorkflow.ts +63 -0
  78. package/src/index.ts +465 -0
  79. package/src/loader/experience-workflow-loader.ts +192 -0
  80. package/src/loader/index.ts +6 -0
  81. package/src/local/LocalEngine.ts +388 -0
  82. package/src/local/LocalEngineAdapter.ts +175 -0
  83. package/src/local/LocalEngineContext.ts +30 -0
  84. package/src/logger.ts +37 -0
  85. package/src/mixins.ts +1160 -0
  86. package/src/providers/RuntimeContext.ts +20 -0
  87. package/src/providers/WorkflowProvider.tsx +28 -0
  88. package/src/routing/instance-key.ts +107 -0
  89. package/src/server/transition-context.ts +172 -0
  90. package/src/testing/index.ts +9 -0
  91. package/src/testing/useBlueprintTestRunner.ts +91 -0
  92. package/src/testing/useGraphAnalysis.ts +18 -0
  93. package/src/testing/useTestRunner.ts +77 -0
  94. package/src/testing.ts +995 -0
  95. package/src/types/workflow-inference.ts +158 -0
  96. package/src/types.ts +114 -0
  97. package/tsconfig.json +27 -0
  98. package/vitest.config.ts +8 -0
@@ -0,0 +1,123 @@
1
+ /**
2
+ * ExperienceWorkflowBridge — Wrapper component that connects the player engine
3
+ * to the view rendering layer (ComponentTreeRenderer).
4
+ *
5
+ * This component bridges the reactive effects layer (player-core state machine +
6
+ * event bus + action dispatcher) with the view rendering layer (CTR). It:
7
+ *
8
+ * - Creates a player instance from an experience workflow definition
9
+ * - Provides the PlayerHandle via context to all descendants
10
+ * - Subscribes to domain events via WebSocket transport
11
+ * - Renders the appropriate experience tree based on the current state
12
+ * - Passes transition callbacks that wire through the player engine
13
+ *
14
+ * Usage:
15
+ * ```tsx
16
+ * <ExperienceWorkflowBridge
17
+ * definition={myWorkflowDef}
18
+ * transport={socketTransport}
19
+ * renderView={(player, viewConfig) => (
20
+ * <ComponentTreeRenderer tree={viewConfig.tree} entityType="..." entityId="..." />
21
+ * )}
22
+ * />
23
+ * ```
24
+ */
25
+
26
+ import { useMemo } from 'react';
27
+ import type { ActionHandlerFn } from '@mindmatrix/player-core';
28
+ import type {
29
+ ExperienceWorkflowDefinition,
30
+ ExperienceViewConfig,
31
+ PlayerHandle,
32
+ DomainSubscriptionConfig,
33
+ } from '../types';
34
+ import { usePlayer } from '../hooks/usePlayer';
35
+ import { useDomainSubscription, type DomainSubscriptionTransport } from '../hooks/useDomainSubscription';
36
+ import { PlayerProvider } from './PlayerProvider';
37
+
38
+ export interface ExperienceWorkflowBridgeProps {
39
+ /** Experience workflow definition to run */
40
+ definition: ExperienceWorkflowDefinition;
41
+ /** Initial state_data */
42
+ initialData?: Record<string, unknown>;
43
+ /** Custom action handlers */
44
+ actionHandlers?: Record<string, ActionHandlerFn>;
45
+ /** WebSocket transport for domain events */
46
+ transport?: DomainSubscriptionTransport | null;
47
+ /** Domain subscription configuration */
48
+ subscription?: Omit<DomainSubscriptionConfig, 'onEvent'>;
49
+ /** Render function — receives the player handle and view config for current state */
50
+ renderView: (player: PlayerHandle, viewConfig: ExperienceViewConfig | undefined) => React.ReactNode;
51
+ /** Enable debug logging */
52
+ debug?: boolean;
53
+ /** Callback for domain events */
54
+ onDomainEvent?: DomainSubscriptionConfig['onEvent'];
55
+ }
56
+
57
+ /**
58
+ * Hook to access the event bus for domain subscription wiring.
59
+ * Internal — used by ExperienceWorkflowBridge only.
60
+ */
61
+ function ExperienceWorkflowBridgeInner({
62
+ definition,
63
+ initialData,
64
+ actionHandlers,
65
+ transport,
66
+ subscription,
67
+ renderView,
68
+ debug,
69
+ onDomainEvent,
70
+ }: ExperienceWorkflowBridgeProps) {
71
+ const player = usePlayer({
72
+ definition,
73
+ initialData,
74
+ actionHandlers,
75
+ debug,
76
+ });
77
+
78
+ // Get the view config for the current state
79
+ const viewConfig = useMemo(() => {
80
+ if (!definition.state_views) return undefined;
81
+ return definition.state_views[player.currentState];
82
+ }, [definition.state_views, player.currentState]);
83
+
84
+ return (
85
+ <PlayerProvider player={player}>
86
+ <DomainSubscriptionBridge
87
+ player={player}
88
+ transport={transport ?? null}
89
+ subscription={subscription}
90
+ onDomainEvent={onDomainEvent}
91
+ />
92
+ {renderView(player, viewConfig)}
93
+ </PlayerProvider>
94
+ );
95
+ }
96
+
97
+ /**
98
+ * Internal component that wires domain subscriptions.
99
+ * Separated to avoid re-creating subscriptions on view re-renders.
100
+ */
101
+ function DomainSubscriptionBridge({
102
+ player,
103
+ transport,
104
+ subscription,
105
+ onDomainEvent,
106
+ }: {
107
+ player: PlayerHandle;
108
+ transport: DomainSubscriptionTransport | null;
109
+ subscription?: Omit<DomainSubscriptionConfig, 'onEvent'>;
110
+ onDomainEvent?: DomainSubscriptionConfig['onEvent'];
111
+ }) {
112
+ useDomainSubscription(player.eventBus, transport, {
113
+ ...subscription,
114
+ onEvent: onDomainEvent,
115
+ enabled: subscription?.enabled ?? true,
116
+ });
117
+
118
+ return null;
119
+ }
120
+
121
+ export function ExperienceWorkflowBridge(props: ExperienceWorkflowBridgeProps) {
122
+ return <ExperienceWorkflowBridgeInner {...props} />;
123
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * PlayerProvider — React context provider for the player engine.
3
+ *
4
+ * Wraps children with a PlayerHandle context, making the engine
5
+ * available to any descendant component via usePlayerContext().
6
+ */
7
+
8
+ import { createContext, useContext } from 'react';
9
+ import type { PlayerHandle } from '../types';
10
+
11
+ const PlayerContext = createContext<PlayerHandle | null>(null);
12
+
13
+ export interface PlayerProviderProps {
14
+ player: PlayerHandle;
15
+ children: React.ReactNode;
16
+ }
17
+
18
+ export function PlayerProvider({ player, children }: PlayerProviderProps) {
19
+ return (
20
+ <PlayerContext.Provider value={player}>
21
+ {children}
22
+ </PlayerContext.Provider>
23
+ );
24
+ }
25
+
26
+ /**
27
+ * Access the PlayerHandle from context.
28
+ * Must be used within a <PlayerProvider>.
29
+ */
30
+ export function usePlayerContext(): PlayerHandle {
31
+ const ctx = useContext(PlayerContext);
32
+ if (!ctx) {
33
+ throw new Error('usePlayerContext must be used within a <PlayerProvider>');
34
+ }
35
+ return ctx;
36
+ }
37
+
38
+ /**
39
+ * Optionally access the PlayerHandle (returns null if not in provider).
40
+ */
41
+ export function usePlayerContextSafe(): PlayerHandle | null {
42
+ return useContext(PlayerContext);
43
+ }
@@ -0,0 +1,269 @@
1
+ /**
2
+ * Layout Atoms — the building blocks for workflow views.
3
+ *
4
+ * These components are recognized by the @mindmatrix/react-compiler's
5
+ * component-extractor and compiled into Pure Form [view] nodes.
6
+ *
7
+ * Per Design 12 Section 17.3.
8
+ */
9
+ import React from 'react';
10
+
11
+ // =============================================================================
12
+ // Layout Containers
13
+ // =============================================================================
14
+
15
+ export interface StackProps {
16
+ children?: React.ReactNode;
17
+ gap?: number | string;
18
+ style?: React.CSSProperties;
19
+ className?: string;
20
+ }
21
+
22
+ /** Vertical layout container. Renders children in a column. */
23
+ export function Stack({ children, gap, style, className }: StackProps) {
24
+ return (
25
+ <div
26
+ className={className}
27
+ style={{ display: 'flex', flexDirection: 'column', gap, ...style }}
28
+ >
29
+ {children}
30
+ </div>
31
+ );
32
+ }
33
+
34
+ export interface RowProps {
35
+ children?: React.ReactNode;
36
+ gap?: number | string;
37
+ align?: 'start' | 'center' | 'end' | 'stretch';
38
+ style?: React.CSSProperties;
39
+ className?: string;
40
+ }
41
+
42
+ /** Horizontal layout container. Renders children in a row. */
43
+ export function Row({ children, gap, align, style, className }: RowProps) {
44
+ return (
45
+ <div
46
+ className={className}
47
+ style={{
48
+ display: 'flex',
49
+ flexDirection: 'row',
50
+ gap,
51
+ alignItems: align,
52
+ ...style,
53
+ }}
54
+ >
55
+ {children}
56
+ </div>
57
+ );
58
+ }
59
+
60
+ export interface ColumnProps {
61
+ children?: React.ReactNode;
62
+ span?: number;
63
+ style?: React.CSSProperties;
64
+ className?: string;
65
+ }
66
+
67
+ /** Column within a Row. */
68
+ export function Column({ children, span, style, className }: ColumnProps) {
69
+ return (
70
+ <div
71
+ className={className}
72
+ style={{ flex: span ?? 1, ...style }}
73
+ >
74
+ {children}
75
+ </div>
76
+ );
77
+ }
78
+
79
+ // =============================================================================
80
+ // Typography
81
+ // =============================================================================
82
+
83
+ export interface TextProps {
84
+ children?: React.ReactNode;
85
+ bold?: boolean;
86
+ size?: 'sm' | 'md' | 'lg';
87
+ color?: string;
88
+ style?: React.CSSProperties;
89
+ className?: string;
90
+ }
91
+
92
+ /** Text display component. */
93
+ export function Text({ children, bold, size, color, style, className }: TextProps) {
94
+ const fontSize = size === 'sm' ? '0.875rem' : size === 'lg' ? '1.25rem' : '1rem';
95
+ return (
96
+ <span
97
+ className={className}
98
+ style={{ fontWeight: bold ? 700 : 400, fontSize, color, ...style }}
99
+ >
100
+ {children}
101
+ </span>
102
+ );
103
+ }
104
+
105
+ export interface HeadingProps {
106
+ children?: React.ReactNode;
107
+ level?: 1 | 2 | 3 | 4 | 5 | 6;
108
+ style?: React.CSSProperties;
109
+ className?: string;
110
+ }
111
+
112
+ /** Heading component. */
113
+ export function Heading({ children, level = 2, style, className }: HeadingProps) {
114
+ const Tag = `h${level}` as 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
115
+ return React.createElement(Tag, { className, style }, children);
116
+ }
117
+
118
+ // =============================================================================
119
+ // Interactive
120
+ // =============================================================================
121
+
122
+ export interface ButtonProps {
123
+ children?: React.ReactNode;
124
+ onPress?: () => void;
125
+ variant?: 'primary' | 'secondary' | 'ghost' | 'danger';
126
+ disabled?: boolean;
127
+ style?: React.CSSProperties;
128
+ className?: string;
129
+ }
130
+
131
+ /** Button component. Uses onPress (not onClick) per the spec. */
132
+ export function Button({ children, onPress, variant = 'primary', disabled, style, className }: ButtonProps) {
133
+ return (
134
+ <button
135
+ className={className}
136
+ onClick={onPress}
137
+ disabled={disabled}
138
+ data-variant={variant}
139
+ style={style}
140
+ >
141
+ {children}
142
+ </button>
143
+ );
144
+ }
145
+
146
+ export interface TextInputProps {
147
+ value?: string;
148
+ onChange?: (value: string) => void;
149
+ placeholder?: string;
150
+ disabled?: boolean;
151
+ style?: React.CSSProperties;
152
+ className?: string;
153
+ }
154
+
155
+ /** Text input component. onChange receives value string directly. */
156
+ export function TextInput({ value, onChange, placeholder, disabled, style, className }: TextInputProps) {
157
+ return (
158
+ <input
159
+ type="text"
160
+ className={className}
161
+ value={value}
162
+ onChange={(e) => onChange?.(e.target.value)}
163
+ placeholder={placeholder}
164
+ disabled={disabled}
165
+ style={style}
166
+ />
167
+ );
168
+ }
169
+
170
+ // =============================================================================
171
+ // Control Flow
172
+ // =============================================================================
173
+
174
+ export interface EachProps<T> {
175
+ items?: T[];
176
+ keyBy?: string;
177
+ children: (item: T, index: number) => React.ReactNode;
178
+ }
179
+
180
+ /** Iterates over items, rendering children for each one. */
181
+ export function Each<T>({ items, keyBy, children }: EachProps<T>) {
182
+ if (!items || items.length === 0) return null;
183
+ return (
184
+ <>
185
+ {items.map((item, i) => {
186
+ const key = keyBy ? (item as any)[keyBy] : i;
187
+ return <React.Fragment key={key}>{children(item, i)}</React.Fragment>;
188
+ })}
189
+ </>
190
+ );
191
+ }
192
+
193
+ export interface ShowProps {
194
+ when?: unknown;
195
+ fallback?: React.ReactNode;
196
+ children?: React.ReactNode;
197
+ }
198
+
199
+ /** Conditional rendering. Shows children when condition is truthy. */
200
+ export function Show({ when, fallback, children }: ShowProps) {
201
+ if (!when) return fallback ? <>{fallback}</> : null;
202
+ return <>{children}</>;
203
+ }
204
+
205
+ // =============================================================================
206
+ // Composition
207
+ // =============================================================================
208
+
209
+ export interface SlotProps {
210
+ name: string;
211
+ children?: React.ReactNode;
212
+ }
213
+
214
+ /** Named slot for hub/spoke composition. */
215
+ export function Slot({ children }: SlotProps) {
216
+ return <>{children}</>;
217
+ }
218
+
219
+ // =============================================================================
220
+ // Display
221
+ // =============================================================================
222
+
223
+ export interface BadgeProps {
224
+ children?: React.ReactNode;
225
+ variant?: 'default' | 'success' | 'warning' | 'error';
226
+ style?: React.CSSProperties;
227
+ className?: string;
228
+ }
229
+
230
+ /** Badge/chip display component. */
231
+ export function Badge({ children, variant = 'default', style, className }: BadgeProps) {
232
+ return (
233
+ <span className={className} data-variant={variant} style={style}>
234
+ {children}
235
+ </span>
236
+ );
237
+ }
238
+
239
+ export interface CardProps {
240
+ children?: React.ReactNode;
241
+ style?: React.CSSProperties;
242
+ className?: string;
243
+ }
244
+
245
+ /** Card container with visual boundary. */
246
+ export function Card({ children, style, className }: CardProps) {
247
+ return (
248
+ <div
249
+ className={className}
250
+ style={{
251
+ border: '1px solid #e2e8f0',
252
+ borderRadius: '0.5rem',
253
+ padding: '1rem',
254
+ ...style,
255
+ }}
256
+ >
257
+ {children}
258
+ </div>
259
+ );
260
+ }
261
+
262
+ export interface DividerProps {
263
+ style?: React.CSSProperties;
264
+ }
265
+
266
+ /** Visual divider/separator. */
267
+ export function Divider({ style }: DividerProps) {
268
+ return <hr style={{ border: 'none', borderTop: '1px solid #e2e8f0', ...style }} />;
269
+ }
@@ -0,0 +1,36 @@
1
+ export { PlayerProvider, usePlayerContext, usePlayerContextSafe } from './PlayerProvider';
2
+ export type { PlayerProviderProps } from './PlayerProvider';
3
+ export { ExperienceWorkflowBridge } from './ExperienceWorkflowBridge';
4
+ export type { ExperienceWorkflowBridgeProps } from './ExperienceWorkflowBridge';
5
+
6
+ // Layout Atoms (Design 12 Section 17.3)
7
+ export {
8
+ Stack,
9
+ Row,
10
+ Column,
11
+ Text,
12
+ Heading,
13
+ Button,
14
+ TextInput,
15
+ Each,
16
+ Show,
17
+ Slot,
18
+ Badge,
19
+ Card,
20
+ Divider,
21
+ } from './atoms';
22
+ export type {
23
+ StackProps,
24
+ RowProps,
25
+ ColumnProps,
26
+ TextProps,
27
+ HeadingProps,
28
+ ButtonProps,
29
+ TextInputProps,
30
+ EachProps,
31
+ ShowProps,
32
+ SlotProps,
33
+ BadgeProps,
34
+ CardProps,
35
+ DividerProps,
36
+ } from './atoms';