@mmapp/react 0.1.0-alpha.18 → 0.1.0-alpha.19

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 (52) hide show
  1. package/dist/actions-MFI2V4DX.mjs +116 -0
  2. package/dist/atoms/index.d.mts +2 -2
  3. package/dist/atoms/index.d.ts +2 -2
  4. package/dist/atoms/index.js +1 -1
  5. package/dist/atoms/index.mjs +1 -1
  6. package/dist/builtin-atoms-C-sNyYJl.d.mts +647 -0
  7. package/dist/builtin-atoms-C-sNyYJl.d.ts +647 -0
  8. package/dist/builtin-atoms-DCKrjG7i.d.mts +96 -0
  9. package/dist/builtin-atoms-DCKrjG7i.d.ts +96 -0
  10. package/dist/builtin-atoms-DRD3EwG6.d.mts +648 -0
  11. package/dist/builtin-atoms-DRD3EwG6.d.ts +648 -0
  12. package/dist/builtin-atoms-jt04b7Rw.d.mts +643 -0
  13. package/dist/builtin-atoms-jt04b7Rw.d.ts +643 -0
  14. package/dist/chunk-247T4GDJ.mjs +677 -0
  15. package/dist/chunk-3H6CR7E7.mjs +1924 -0
  16. package/dist/chunk-3PL6FL6I.mjs +96 -0
  17. package/dist/chunk-3SJSW3C4.mjs +2039 -0
  18. package/dist/chunk-5OI2VI57.mjs +1964 -0
  19. package/dist/chunk-CL6FYZ43.mjs +105 -0
  20. package/dist/chunk-ENQOCZI5.mjs +1938 -0
  21. package/dist/chunk-FB3WCZAU.mjs +512 -0
  22. package/dist/chunk-GLJ7VC7Z.mjs +684 -0
  23. package/dist/chunk-HHMWR6NA.mjs +504 -0
  24. package/dist/chunk-HULEMSN2.mjs +120 -0
  25. package/dist/chunk-J5MW6CRU.mjs +1938 -0
  26. package/dist/chunk-PNTTKNYU.mjs +677 -0
  27. package/dist/chunk-TY5OTJP4.mjs +684 -0
  28. package/dist/chunk-WV7DVCP6.mjs +513 -0
  29. package/dist/chunk-YFMPTGUF.mjs +677 -0
  30. package/dist/{chunk-2VJQJM7S.mjs → chunk-ZDWACXZN.mjs} +1 -1
  31. package/dist/composition-BJ6QQTWT.mjs +12 -0
  32. package/dist/composition-XBGKKCI7.mjs +57 -0
  33. package/dist/content-QVPFUG4P.mjs +246 -0
  34. package/dist/control-flow-CBREHWJW.mjs +35 -0
  35. package/dist/control-flow-FWBOI6SM.mjs +35 -0
  36. package/dist/control-flow-ZWUGCDSP.mjs +35 -0
  37. package/dist/data-WCMIZYKD.mjs +97 -0
  38. package/dist/grouping-E6F377VZ.mjs +204 -0
  39. package/dist/grouping-FRPOEXO3.mjs +233 -0
  40. package/dist/index.d.mts +4 -433
  41. package/dist/index.d.ts +4 -433
  42. package/dist/index.js +3648 -581
  43. package/dist/index.mjs +335 -1040
  44. package/dist/input-PUOZDNSI.mjs +222 -0
  45. package/dist/layout-RATDMCLP.mjs +106 -0
  46. package/dist/navigation-VCT7ZBMA.mjs +15 -0
  47. package/dist/navigation-WFV7YWOU.mjs +14 -0
  48. package/dist/player/index.d.mts +37 -11
  49. package/dist/player/index.d.ts +37 -11
  50. package/dist/player/index.js +3280 -174
  51. package/dist/player/index.mjs +55 -5
  52. package/package.json +4 -4
@@ -0,0 +1,677 @@
1
+ // src/player/evaluator.ts
2
+ var EXPR_PATTERN = /\{\{(.+?)\}\}/g;
3
+ function containsExpression(value) {
4
+ return typeof value === "string" && EXPR_PATTERN.test(value);
5
+ }
6
+ function resolvePath(path, scope) {
7
+ const parts = path.trim().split(".");
8
+ let current = scope;
9
+ for (const part of parts) {
10
+ if (current == null || typeof current !== "object") return void 0;
11
+ current = current[part];
12
+ }
13
+ return current;
14
+ }
15
+ function evaluateExpression(expr, scopes) {
16
+ const trimmed = expr.trim();
17
+ if (trimmed.startsWith("'") && trimmed.endsWith("'") || trimmed.startsWith('"') && trimmed.endsWith('"')) {
18
+ return trimmed.slice(1, -1);
19
+ }
20
+ if (/^-?\d+(\.\d+)?$/.test(trimmed)) {
21
+ return Number(trimmed);
22
+ }
23
+ if (trimmed === "true") return true;
24
+ if (trimmed === "false") return false;
25
+ if (trimmed === "null" || trimmed === "undefined") return void 0;
26
+ const flatScope = { ...scopes };
27
+ if (scopes.state_data && typeof scopes.state_data === "object") {
28
+ Object.assign(flatScope, scopes.state_data);
29
+ }
30
+ if (scopes.context && typeof scopes.context === "object") {
31
+ Object.assign(flatScope, scopes.context);
32
+ }
33
+ return resolvePath(trimmed, flatScope);
34
+ }
35
+ function evaluateProp(value, scopes) {
36
+ if (typeof value !== "string") return value;
37
+ const fullMatch = value.match(/^\{\{(.+)\}\}$/s);
38
+ if (fullMatch) {
39
+ return evaluateExpression(fullMatch[1], scopes);
40
+ }
41
+ if (containsExpression(value)) {
42
+ return value.replace(EXPR_PATTERN, (_, expr) => {
43
+ const result = evaluateExpression(expr, scopes);
44
+ return result == null ? "" : String(result);
45
+ });
46
+ }
47
+ return value;
48
+ }
49
+
50
+ // src/player/ComponentTreeRenderer.tsx
51
+ import React, { useMemo, useCallback } from "react";
52
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
53
+ var UnknownAtom = ({ type, children }) => /* @__PURE__ */ jsxs("div", { style: { border: "1px dashed #e53e3e", borderRadius: 6, padding: "8px 12px", margin: 4, fontSize: 13, color: "#e53e3e", background: "#fff5f5" }, children: [
54
+ /* @__PURE__ */ jsxs("span", { style: { fontWeight: 600 }, children: [
55
+ "Unknown: ",
56
+ type
57
+ ] }),
58
+ children && /* @__PURE__ */ jsx("div", { style: { marginTop: 4 }, children })
59
+ ] });
60
+ var RenderNode = ({ node, scopes, atoms, onEvent }) => {
61
+ const nodeType = node.type || node.component || "";
62
+ const nodeProps = node.props || node.config || {};
63
+ if (node.$if) {
64
+ const condition = evaluateProp(node.$if, scopes);
65
+ if (!condition) return null;
66
+ }
67
+ if (node.$for) {
68
+ const { each, as, key: keyField } = node.$for;
69
+ const items = evaluateProp(each, scopes);
70
+ if (!Array.isArray(items)) return null;
71
+ return /* @__PURE__ */ jsx(Fragment, { children: items.map((item, index) => {
72
+ const loopScopes = {
73
+ ...scopes,
74
+ state_data: {
75
+ ...scopes.state_data ?? {},
76
+ [as]: item,
77
+ [`${as}Index`]: index
78
+ }
79
+ };
80
+ const nodeWithoutFor = { ...node, $for: void 0 };
81
+ const itemKey = keyField ? String(item[keyField] ?? index) : String(index);
82
+ return /* @__PURE__ */ jsx(RenderNode, { node: nodeWithoutFor, scopes: loopScopes, atoms, onEvent }, itemKey);
83
+ }) });
84
+ }
85
+ const Component = atoms[nodeType];
86
+ if (!Component) {
87
+ return /* @__PURE__ */ jsx(UnknownAtom, { type: nodeType });
88
+ }
89
+ const evaluatedProps = {};
90
+ if (node.className) evaluatedProps.className = node.className;
91
+ if (node.id) evaluatedProps["data-node-id"] = node.id;
92
+ for (const [key, value] of Object.entries(nodeProps)) {
93
+ if (key.startsWith("on") && typeof value === "string") {
94
+ evaluatedProps[key] = (...args) => {
95
+ if (containsExpression(value)) {
96
+ evaluateExpression(value.replace(/^\{\{|\}\}$/g, ""), scopes);
97
+ } else {
98
+ onEvent(value, args[0]);
99
+ }
100
+ };
101
+ } else {
102
+ evaluatedProps[key] = evaluateProp(value, scopes);
103
+ }
104
+ }
105
+ let children = null;
106
+ if (node.children) {
107
+ if (typeof node.children === "string") {
108
+ children = evaluateProp(node.children, scopes);
109
+ } else if (Array.isArray(node.children)) {
110
+ children = node.children.map((child, index) => /* @__PURE__ */ jsx(RenderNode, { node: child, scopes, atoms, onEvent }, child.id || index));
111
+ }
112
+ }
113
+ return /* @__PURE__ */ jsx(Component, { ...evaluatedProps, children });
114
+ };
115
+ var CTRErrorBoundary = class extends React.Component {
116
+ constructor(props) {
117
+ super(props);
118
+ this.state = { hasError: false };
119
+ }
120
+ static getDerivedStateFromError(error) {
121
+ return { hasError: true, error };
122
+ }
123
+ componentDidCatch(error, errorInfo) {
124
+ console.error("CTR rendering error:", error, errorInfo);
125
+ }
126
+ render() {
127
+ if (this.state.hasError) {
128
+ return this.props.fallback || /* @__PURE__ */ jsxs("div", { style: { padding: 16, background: "#fff5f5", border: "1px solid #fed7d7", borderRadius: 8 }, children: [
129
+ /* @__PURE__ */ jsx("strong", { style: { color: "#c53030" }, children: "Rendering Error" }),
130
+ /* @__PURE__ */ jsx("p", { style: { color: "#e53e3e", fontSize: 14, marginTop: 4 }, children: this.state.error?.message || "An error occurred while rendering" })
131
+ ] });
132
+ }
133
+ return this.props.children;
134
+ }
135
+ };
136
+ var ComponentTreeRenderer = ({
137
+ tree,
138
+ scopes,
139
+ atoms = {},
140
+ onEvent = () => {
141
+ },
142
+ fallback
143
+ }) => {
144
+ const allAtoms = useMemo(() => ({ ...atoms }), [atoms]);
145
+ const handleEvent = useCallback(
146
+ (eventName, payload) => onEvent(eventName, payload),
147
+ [onEvent]
148
+ );
149
+ const nodes = Array.isArray(tree) ? tree : [tree];
150
+ return /* @__PURE__ */ jsx(CTRErrorBoundary, { fallback, children: nodes.map((node, index) => /* @__PURE__ */ jsx(RenderNode, { node, scopes, atoms: allAtoms, onEvent: handleEvent }, index)) });
151
+ };
152
+
153
+ // src/player/builtin-atoms.tsx
154
+ import React2 from "react";
155
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
156
+ var Stack = ({ children, gap = 8, style, ...rest }) => /* @__PURE__ */ jsx2("div", { style: { display: "flex", flexDirection: "column", gap, ...style }, ...rest, children });
157
+ var Row = ({ children, gap = 8, align, justify, style, ...rest }) => /* @__PURE__ */ jsx2("div", { style: { display: "flex", flexDirection: "row", gap, alignItems: align, justifyContent: justify, ...style }, ...rest, children });
158
+ var Column = ({ children, span, style, ...rest }) => /* @__PURE__ */ jsx2("div", { style: { flex: span ? `0 0 ${Number(span) / 12 * 100}%` : 1, ...style }, ...rest, children });
159
+ var Grid = ({ children, columns = 2, gap = 8, style, ...rest }) => /* @__PURE__ */ jsx2("div", { style: { display: "grid", gridTemplateColumns: `repeat(${columns}, 1fr)`, gap, ...style }, ...rest, children });
160
+ var Divider = ({ style }) => /* @__PURE__ */ jsx2("hr", { style: { border: "none", borderTop: "1px solid #e2e8f0", margin: "8px 0", ...style } });
161
+ var Spacer = ({ size = 16 }) => /* @__PURE__ */ jsx2("div", { style: { height: size, flexShrink: 0 } });
162
+ var Text = ({ children, size, weight, color, style, ...rest }) => /* @__PURE__ */ jsx2("span", { style: { fontSize: size, fontWeight: weight, color, ...style }, ...rest, children });
163
+ var Heading = ({ children, level = 2, style, ...rest }) => {
164
+ const lvl = Math.min(Math.max(Number(level), 1), 6);
165
+ const s = { margin: "0 0 8px", ...style };
166
+ const c = children;
167
+ if (lvl === 1) return /* @__PURE__ */ jsx2("h1", { style: s, ...rest, children: c });
168
+ if (lvl === 2) return /* @__PURE__ */ jsx2("h2", { style: s, ...rest, children: c });
169
+ if (lvl === 3) return /* @__PURE__ */ jsx2("h3", { style: s, ...rest, children: c });
170
+ if (lvl === 4) return /* @__PURE__ */ jsx2("h4", { style: s, ...rest, children: c });
171
+ if (lvl === 5) return /* @__PURE__ */ jsx2("h5", { style: s, ...rest, children: c });
172
+ return /* @__PURE__ */ jsx2("h6", { style: s, ...rest, children: c });
173
+ };
174
+ var Field = ({ label, value, children, style }) => /* @__PURE__ */ jsxs2("div", { style: { marginBottom: 8, ...style }, children: [
175
+ label ? /* @__PURE__ */ jsx2("div", { style: { fontSize: 12, color: "#718096", marginBottom: 2 }, children: label }) : null,
176
+ /* @__PURE__ */ jsx2("div", { style: { fontSize: 14 }, children: children ?? value ?? "\u2014" })
177
+ ] });
178
+ var Badge = ({ children, variant = "default", style }) => {
179
+ const colors = {
180
+ default: { bg: "#edf2f7", fg: "#4a5568" },
181
+ success: { bg: "#c6f6d5", fg: "#276749" },
182
+ warning: { bg: "#fefcbf", fg: "#975a16" },
183
+ error: { bg: "#fed7d7", fg: "#9b2c2c" },
184
+ info: { bg: "#bee3f8", fg: "#2a4365" }
185
+ };
186
+ const c = colors[variant] ?? colors.default;
187
+ return /* @__PURE__ */ jsx2("span", { style: { display: "inline-block", padding: "2px 8px", borderRadius: 9999, fontSize: 12, fontWeight: 500, background: c.bg, color: c.fg, ...style }, children });
188
+ };
189
+ var ImageAtom = ({ src, alt, width, height, style, ...rest }) => /* @__PURE__ */ jsx2("img", { src, alt: alt ?? "", width, height, style: { maxWidth: "100%", ...style }, ...rest });
190
+ var Button = ({ children, onClick, variant = "primary", disabled, style, ...rest }) => {
191
+ const styles = {
192
+ primary: { background: "#3182ce", color: "#fff", border: "none" },
193
+ secondary: { background: "#edf2f7", color: "#4a5568", border: "1px solid #e2e8f0" },
194
+ danger: { background: "#e53e3e", color: "#fff", border: "none" },
195
+ ghost: { background: "transparent", color: "#4a5568", border: "none" }
196
+ };
197
+ const base = styles[variant] ?? styles.primary;
198
+ return /* @__PURE__ */ jsx2(
199
+ "button",
200
+ {
201
+ onClick,
202
+ disabled,
203
+ style: { padding: "6px 16px", borderRadius: 6, fontSize: 14, fontWeight: 500, cursor: disabled ? "not-allowed" : "pointer", opacity: disabled ? 0.5 : 1, ...base, ...style },
204
+ ...rest,
205
+ children
206
+ }
207
+ );
208
+ };
209
+ var LinkAtom = ({ children, href, style, ...rest }) => /* @__PURE__ */ jsx2("a", { href, style: { color: "#3182ce", textDecoration: "underline", ...style }, ...rest, children });
210
+ var TextInput = ({ value, onChange, placeholder, label, style, ...rest }) => /* @__PURE__ */ jsxs2("div", { style: { marginBottom: 8 }, children: [
211
+ label ? /* @__PURE__ */ jsx2("label", { style: { display: "block", fontSize: 12, color: "#718096", marginBottom: 2 }, children: label }) : null,
212
+ /* @__PURE__ */ jsx2(
213
+ "input",
214
+ {
215
+ type: "text",
216
+ value: value ?? "",
217
+ onChange,
218
+ placeholder,
219
+ style: { width: "100%", padding: "6px 10px", border: "1px solid #e2e8f0", borderRadius: 6, fontSize: 14, ...style },
220
+ ...rest
221
+ }
222
+ )
223
+ ] });
224
+ var SelectAtom = ({ value, onChange, options, label, placeholder, style }) => /* @__PURE__ */ jsxs2("div", { style: { marginBottom: 8 }, children: [
225
+ label ? /* @__PURE__ */ jsx2("label", { style: { display: "block", fontSize: 12, color: "#718096", marginBottom: 2 }, children: label }) : null,
226
+ /* @__PURE__ */ jsxs2(
227
+ "select",
228
+ {
229
+ value: value ?? "",
230
+ onChange,
231
+ style: { width: "100%", padding: "6px 10px", border: "1px solid #e2e8f0", borderRadius: 6, fontSize: 14, ...style },
232
+ children: [
233
+ placeholder ? /* @__PURE__ */ jsx2("option", { value: "", children: placeholder }) : null,
234
+ Array.isArray(options) && options.map((opt) => {
235
+ const v = typeof opt === "string" ? opt : opt.value;
236
+ const l = typeof opt === "string" ? opt : opt.label;
237
+ return /* @__PURE__ */ jsx2("option", { value: v, children: l }, v);
238
+ })
239
+ ]
240
+ }
241
+ )
242
+ ] });
243
+ var Card = ({ children, title, style, ...rest }) => /* @__PURE__ */ jsxs2("div", { style: { border: "1px solid #e2e8f0", borderRadius: 8, padding: 16, background: "#fff", ...style }, ...rest, children: [
244
+ title ? /* @__PURE__ */ jsx2("div", { style: { fontWeight: 600, fontSize: 16, marginBottom: 12 }, children: title }) : null,
245
+ children
246
+ ] });
247
+ var Section = ({ children, title, style, ...rest }) => /* @__PURE__ */ jsxs2("section", { style: { marginBottom: 24, ...style }, ...rest, children: [
248
+ title ? /* @__PURE__ */ jsx2("h3", { style: { fontSize: 18, fontWeight: 600, marginBottom: 8 }, children: title }) : null,
249
+ children
250
+ ] });
251
+ var Show = ({ when, children, fallback }) => when ? /* @__PURE__ */ jsx2(Fragment2, { children }) : /* @__PURE__ */ jsx2(Fragment2, { children: fallback ?? null });
252
+ var Each = ({ items, children, renderItem }) => {
253
+ if (!Array.isArray(items)) return null;
254
+ if (typeof renderItem === "function") return /* @__PURE__ */ jsx2(Fragment2, { children: items.map((item, i) => renderItem(item, i)) });
255
+ return /* @__PURE__ */ jsx2(Fragment2, { children });
256
+ };
257
+ var RouterContext = React2.createContext({ path: "/", navigate: () => {
258
+ } });
259
+ var Router = ({ children, basePath, className, style, ...rest }) => {
260
+ const [path, setPath] = React2.useState("/");
261
+ const navigate = React2.useCallback((to) => setPath(to), []);
262
+ return /* @__PURE__ */ jsx2(RouterContext.Provider, { value: { path, navigate }, children: /* @__PURE__ */ jsx2("div", { className, style, ...rest, children }) });
263
+ };
264
+ var Route = ({ children, path, exact, fallback: _fallback, className, style }) => {
265
+ const { path: currentPath } = React2.useContext(RouterContext);
266
+ const routePath = path || "/";
267
+ const isExact = exact !== false;
268
+ const matches = isExact ? currentPath === routePath || routePath === "/" && currentPath === "/" : currentPath.startsWith(routePath);
269
+ if (!matches) return null;
270
+ return /* @__PURE__ */ jsx2("div", { className, style, children });
271
+ };
272
+ var NavLink = ({ children, to, label, icon, className, style, ...rest }) => {
273
+ const { path, navigate } = React2.useContext(RouterContext);
274
+ const target = to || "/";
275
+ const isActive = path === target;
276
+ return /* @__PURE__ */ jsx2(
277
+ "button",
278
+ {
279
+ onClick: () => navigate(target),
280
+ className,
281
+ style: {
282
+ background: isActive ? "#edf2f7" : "transparent",
283
+ border: "none",
284
+ borderRadius: 4,
285
+ padding: "4px 12px",
286
+ fontSize: 13,
287
+ cursor: "pointer",
288
+ fontWeight: isActive ? 600 : 400,
289
+ color: isActive ? "#2d3748" : "#718096",
290
+ ...style
291
+ },
292
+ ...rest,
293
+ children: children || label || target
294
+ }
295
+ );
296
+ };
297
+ var RoleGuard = ({ children, role: _role, fallback: _fallback }) => {
298
+ return /* @__PURE__ */ jsx2(Fragment2, { children });
299
+ };
300
+ var Icon = ({ name, size = 16, color, style }) => /* @__PURE__ */ jsx2("span", { style: { display: "inline-flex", alignItems: "center", justifyContent: "center", width: size, height: size, fontSize: size, color, ...style }, title: name, children: iconGlyphs[name] || "\u25A1" });
301
+ var iconGlyphs = {
302
+ home: "\u2302",
303
+ settings: "\u2699",
304
+ plus: "+",
305
+ search: "\u{1F50D}",
306
+ box: "\u25A1",
307
+ inbox: "\u2709",
308
+ chevronRight: "\u203A",
309
+ chevronLeft: "\u2039",
310
+ x: "\u2715",
311
+ check: "\u2713",
312
+ edit: "\u270E",
313
+ trash: "\u{1F5D1}",
314
+ star: "\u2605",
315
+ heart: "\u2665",
316
+ user: "\u{1F464}",
317
+ menu: "\u2630",
318
+ close: "\u2715",
319
+ arrow_right: "\u2192",
320
+ arrow_left: "\u2190"
321
+ };
322
+ var Tabs = ({ children, tabs, defaultTab, style }) => {
323
+ const tabList = tabs || [];
324
+ const [active, setActive] = React2.useState(defaultTab || tabList[0]?.id || "");
325
+ return /* @__PURE__ */ jsxs2("div", { style, children: [
326
+ /* @__PURE__ */ jsx2("div", { style: { display: "flex", borderBottom: "1px solid #e2e8f0", marginBottom: 12 }, children: tabList.map((t) => /* @__PURE__ */ jsx2(
327
+ "button",
328
+ {
329
+ onClick: () => setActive(t.id),
330
+ style: { padding: "6px 16px", border: "none", borderBottom: active === t.id ? "2px solid #3182ce" : "2px solid transparent", background: "none", cursor: "pointer", fontWeight: active === t.id ? 600 : 400, color: active === t.id ? "#3182ce" : "#718096" },
331
+ children: t.label
332
+ },
333
+ t.id
334
+ )) }),
335
+ children
336
+ ] });
337
+ };
338
+ var Accordion = ({ children, style }) => /* @__PURE__ */ jsx2("div", { style, children });
339
+ var Modal = ({ children, open, title, onClose: _onClose, style }) => {
340
+ if (!open) return null;
341
+ return /* @__PURE__ */ jsx2("div", { style: { position: "fixed", inset: 0, background: "rgba(0,0,0,0.5)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 1e3 }, children: /* @__PURE__ */ jsxs2("div", { style: { background: "#fff", borderRadius: 12, padding: 24, maxWidth: 480, width: "100%", ...style }, children: [
342
+ title && /* @__PURE__ */ jsx2("div", { style: { fontWeight: 600, fontSize: 18, marginBottom: 16 }, children: String(title) }),
343
+ children
344
+ ] }) });
345
+ };
346
+ var Markdown = ({ content, children, style }) => /* @__PURE__ */ jsx2("div", { style: { lineHeight: 1.6, ...style }, children: content || children });
347
+ var ScrollArea = ({ children, maxHeight = 400, style }) => /* @__PURE__ */ jsx2("div", { style: { overflow: "auto", maxHeight, ...style }, children });
348
+ var Slot = ({ children, fallback }) => /* @__PURE__ */ jsx2(Fragment2, { children: children || fallback || null });
349
+ var ModuleOutlet = ({ children, module: moduleName, fallback }) => /* @__PURE__ */ jsx2("div", { "data-module": moduleName, children: children || fallback || /* @__PURE__ */ jsxs2("span", { style: { color: "#a0aec0", fontSize: 13 }, children: [
350
+ "Module: ",
351
+ moduleName
352
+ ] }) });
353
+ var builtinAtoms = {
354
+ // Layout
355
+ Stack,
356
+ Row,
357
+ Column,
358
+ Grid,
359
+ Divider,
360
+ Spacer,
361
+ // Typography
362
+ Text,
363
+ Heading,
364
+ Field,
365
+ Badge,
366
+ Image: ImageAtom,
367
+ Icon,
368
+ // Interactive
369
+ Button,
370
+ Link: LinkAtom,
371
+ // Form
372
+ TextInput,
373
+ Select: SelectAtom,
374
+ // Containers
375
+ Card,
376
+ Section,
377
+ Tabs,
378
+ Accordion,
379
+ Modal,
380
+ // Content
381
+ Markdown,
382
+ ScrollArea,
383
+ // Control Flow
384
+ Show,
385
+ Each,
386
+ // Routing
387
+ Router,
388
+ Route,
389
+ NavLink,
390
+ RoleGuard,
391
+ // Composition
392
+ Slot,
393
+ ModuleOutlet
394
+ };
395
+
396
+ // src/player/DevPlayer.tsx
397
+ import { useState, useCallback as useCallback2, useRef, useEffect, useMemo as useMemo2 } from "react";
398
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
399
+ var S = {
400
+ shell: {
401
+ display: "flex",
402
+ flexDirection: "column",
403
+ height: "100%",
404
+ minHeight: "100vh",
405
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
406
+ background: "#f7fafc",
407
+ color: "#1a202c"
408
+ },
409
+ toolbar: {
410
+ display: "flex",
411
+ alignItems: "center",
412
+ gap: 12,
413
+ padding: "8px 16px",
414
+ background: "#1a202c",
415
+ color: "#e2e8f0",
416
+ fontSize: 13,
417
+ flexShrink: 0
418
+ },
419
+ toolbarTitle: { fontWeight: 600, fontSize: 14 },
420
+ toolbarBadge: {
421
+ display: "inline-block",
422
+ padding: "1px 8px",
423
+ borderRadius: 4,
424
+ background: "#2d3748",
425
+ color: "#a0aec0",
426
+ fontSize: 11,
427
+ fontFamily: "monospace"
428
+ },
429
+ toolbarBtn: {
430
+ background: "none",
431
+ border: "1px solid #4a5568",
432
+ borderRadius: 4,
433
+ color: "#a0aec0",
434
+ padding: "2px 10px",
435
+ fontSize: 12,
436
+ cursor: "pointer"
437
+ },
438
+ toolbarBtnActive: {
439
+ background: "#2b6cb0",
440
+ borderColor: "#2b6cb0",
441
+ color: "#fff"
442
+ },
443
+ body: { display: "flex", flex: 1, overflow: "hidden" },
444
+ preview: { flex: 1, overflow: "auto", padding: 24 },
445
+ sidebar: {
446
+ width: 340,
447
+ flexShrink: 0,
448
+ borderLeft: "1px solid #e2e8f0",
449
+ background: "#fff",
450
+ overflow: "auto",
451
+ fontSize: 13
452
+ },
453
+ sidebarSection: { padding: "12px 16px", borderBottom: "1px solid #f0f0f0" },
454
+ sidebarHeading: {
455
+ fontSize: 11,
456
+ fontWeight: 700,
457
+ textTransform: "uppercase",
458
+ color: "#a0aec0",
459
+ letterSpacing: "0.05em",
460
+ marginBottom: 8
461
+ },
462
+ pre: {
463
+ background: "#f7fafc",
464
+ border: "1px solid #e2e8f0",
465
+ borderRadius: 6,
466
+ padding: "8px 12px",
467
+ fontSize: 12,
468
+ fontFamily: "monospace",
469
+ whiteSpace: "pre-wrap",
470
+ wordBreak: "break-word",
471
+ maxHeight: 260,
472
+ overflow: "auto"
473
+ },
474
+ eventRow: {
475
+ display: "flex",
476
+ gap: 8,
477
+ padding: "4px 0",
478
+ borderBottom: "1px solid #f7fafc",
479
+ fontSize: 12,
480
+ fontFamily: "monospace"
481
+ },
482
+ eventTime: { color: "#a0aec0", flexShrink: 0 },
483
+ eventName: { color: "#3182ce", fontWeight: 500 },
484
+ dot: (connected) => ({
485
+ width: 8,
486
+ height: 8,
487
+ borderRadius: "50%",
488
+ background: connected ? "#48bb78" : "#e53e3e",
489
+ flexShrink: 0
490
+ })
491
+ };
492
+ function useDevSocket(wsUrl, onReload) {
493
+ const [connected, setConnected] = useState(false);
494
+ const wsRef = useRef(null);
495
+ useEffect(() => {
496
+ if (typeof window === "undefined") return;
497
+ const url = wsUrl ?? `ws://${window.location.host}/__mm_dev`;
498
+ let ws;
499
+ let reconnectTimer;
500
+ function connect() {
501
+ try {
502
+ ws = new WebSocket(url);
503
+ wsRef.current = ws;
504
+ ws.onopen = () => setConnected(true);
505
+ ws.onclose = () => {
506
+ setConnected(false);
507
+ reconnectTimer = setTimeout(connect, 3e3);
508
+ };
509
+ ws.onmessage = (ev) => {
510
+ try {
511
+ const msg = JSON.parse(ev.data);
512
+ if (msg.type === "workflow:compiled" || msg.type === "workflow:rebuild") {
513
+ onReload?.();
514
+ }
515
+ } catch {
516
+ }
517
+ };
518
+ } catch {
519
+ reconnectTimer = setTimeout(connect, 3e3);
520
+ }
521
+ }
522
+ connect();
523
+ return () => {
524
+ clearTimeout(reconnectTimer);
525
+ wsRef.current?.close();
526
+ wsRef.current = null;
527
+ };
528
+ }, [wsUrl, onReload]);
529
+ return connected;
530
+ }
531
+ var DevPlayer = ({
532
+ tree,
533
+ scopes = {},
534
+ atoms: userAtoms,
535
+ title = "DevPlayer",
536
+ bare = false,
537
+ wsUrl,
538
+ onReload,
539
+ onEvent: externalOnEvent
540
+ }) => {
541
+ const [showSidebar, setShowSidebar] = useState(true);
542
+ const [events, setEvents] = useState([]);
543
+ const nextId = useRef(0);
544
+ const connected = useDevSocket(wsUrl, onReload);
545
+ const mergedAtoms = useMemo2(
546
+ () => ({ ...builtinAtoms, ...userAtoms }),
547
+ [userAtoms]
548
+ );
549
+ const handleEvent = useCallback2(
550
+ (name, payload) => {
551
+ setEvents((prev) => {
552
+ const entry = {
553
+ id: nextId.current++,
554
+ time: (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false }),
555
+ name,
556
+ payload
557
+ };
558
+ const next = [entry, ...prev];
559
+ return next.length > 100 ? next.slice(0, 100) : next;
560
+ });
561
+ externalOnEvent?.(name, payload);
562
+ },
563
+ [externalOnEvent]
564
+ );
565
+ if (bare) {
566
+ return /* @__PURE__ */ jsx3(
567
+ ComponentTreeRenderer,
568
+ {
569
+ tree,
570
+ scopes,
571
+ atoms: mergedAtoms,
572
+ onEvent: handleEvent
573
+ }
574
+ );
575
+ }
576
+ return /* @__PURE__ */ jsxs3("div", { style: S.shell, children: [
577
+ /* @__PURE__ */ jsxs3("div", { style: S.toolbar, children: [
578
+ /* @__PURE__ */ jsx3("div", { style: S.dot(connected), title: connected ? "HMR connected" : "HMR disconnected" }),
579
+ /* @__PURE__ */ jsx3("span", { style: S.toolbarTitle, children: title }),
580
+ /* @__PURE__ */ jsxs3("span", { style: S.toolbarBadge, children: [
581
+ Array.isArray(tree) ? tree.length : 1,
582
+ " node",
583
+ Array.isArray(tree) && tree.length !== 1 ? "s" : ""
584
+ ] }),
585
+ /* @__PURE__ */ jsxs3("span", { style: S.toolbarBadge, children: [
586
+ Object.keys(mergedAtoms).length,
587
+ " atoms"
588
+ ] }),
589
+ /* @__PURE__ */ jsx3("div", { style: { flex: 1 } }),
590
+ /* @__PURE__ */ jsx3(
591
+ "button",
592
+ {
593
+ style: { ...S.toolbarBtn, ...showSidebar ? S.toolbarBtnActive : {} },
594
+ onClick: () => setShowSidebar((v) => !v),
595
+ children: "Inspector"
596
+ }
597
+ )
598
+ ] }),
599
+ /* @__PURE__ */ jsxs3("div", { style: S.body, children: [
600
+ /* @__PURE__ */ jsx3("div", { style: S.preview, children: /* @__PURE__ */ jsx3(
601
+ ComponentTreeRenderer,
602
+ {
603
+ tree,
604
+ scopes,
605
+ atoms: mergedAtoms,
606
+ onEvent: handleEvent
607
+ }
608
+ ) }),
609
+ showSidebar && /* @__PURE__ */ jsxs3("div", { style: S.sidebar, children: [
610
+ /* @__PURE__ */ jsxs3("div", { style: S.sidebarSection, children: [
611
+ /* @__PURE__ */ jsx3("div", { style: S.sidebarHeading, children: "Scopes" }),
612
+ /* @__PURE__ */ jsx3("pre", { style: S.pre, children: JSON.stringify(scopes, null, 2) })
613
+ ] }),
614
+ /* @__PURE__ */ jsxs3("div", { style: S.sidebarSection, children: [
615
+ /* @__PURE__ */ jsxs3("div", { style: S.sidebarHeading, children: [
616
+ "Atoms (",
617
+ Object.keys(mergedAtoms).length,
618
+ ")"
619
+ ] }),
620
+ /* @__PURE__ */ jsx3("div", { style: { display: "flex", flexWrap: "wrap", gap: 4 }, children: Object.keys(mergedAtoms).sort().map((name) => /* @__PURE__ */ jsx3(
621
+ "span",
622
+ {
623
+ style: {
624
+ display: "inline-block",
625
+ padding: "1px 6px",
626
+ borderRadius: 3,
627
+ background: userAtoms?.[name] ? "#ebf8ff" : "#f7fafc",
628
+ border: `1px solid ${userAtoms?.[name] ? "#90cdf4" : "#e2e8f0"}`,
629
+ fontSize: 11,
630
+ fontFamily: "monospace",
631
+ color: userAtoms?.[name] ? "#2b6cb0" : "#718096"
632
+ },
633
+ children: name
634
+ },
635
+ name
636
+ )) })
637
+ ] }),
638
+ /* @__PURE__ */ jsxs3("div", { style: S.sidebarSection, children: [
639
+ /* @__PURE__ */ jsxs3("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 8 }, children: [
640
+ /* @__PURE__ */ jsxs3("div", { style: S.sidebarHeading, children: [
641
+ "Events (",
642
+ events.length,
643
+ ")"
644
+ ] }),
645
+ events.length > 0 && /* @__PURE__ */ jsx3(
646
+ "button",
647
+ {
648
+ style: { background: "none", border: "none", color: "#a0aec0", fontSize: 11, cursor: "pointer" },
649
+ onClick: () => setEvents([]),
650
+ children: "Clear"
651
+ }
652
+ )
653
+ ] }),
654
+ events.length === 0 && /* @__PURE__ */ jsx3("div", { style: { color: "#a0aec0", fontSize: 12, fontStyle: "italic" }, children: "No events yet" }),
655
+ events.slice(0, 50).map((e) => /* @__PURE__ */ jsxs3("div", { style: S.eventRow, children: [
656
+ /* @__PURE__ */ jsx3("span", { style: S.eventTime, children: e.time }),
657
+ /* @__PURE__ */ jsx3("span", { style: S.eventName, children: e.name }),
658
+ e.payload !== void 0 && /* @__PURE__ */ jsx3("span", { style: { color: "#718096", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: JSON.stringify(e.payload) })
659
+ ] }, e.id))
660
+ ] }),
661
+ /* @__PURE__ */ jsxs3("div", { style: S.sidebarSection, children: [
662
+ /* @__PURE__ */ jsx3("div", { style: S.sidebarHeading, children: "Tree (JSON)" }),
663
+ /* @__PURE__ */ jsx3("pre", { style: { ...S.pre, maxHeight: 400 }, children: JSON.stringify(tree, null, 2) })
664
+ ] })
665
+ ] })
666
+ ] })
667
+ ] });
668
+ };
669
+
670
+ export {
671
+ containsExpression,
672
+ evaluateExpression,
673
+ evaluateProp,
674
+ ComponentTreeRenderer,
675
+ builtinAtoms,
676
+ DevPlayer
677
+ };
@@ -2,7 +2,7 @@
2
2
  function stub(displayName) {
3
3
  const Component = () => {
4
4
  throw new Error(
5
- `<${displayName}> is a compile-time stub from @mindmatrix/react/atoms. It should only appear in .workflow.tsx files processed by the compiler. At runtime, use the ComponentTreeRenderer which resolves "${displayName}" from the component registry.`
5
+ `<${displayName}> is a compile-time stub from @mmapp/react/atoms. It should only appear in .workflow.tsx files processed by the compiler. At runtime, use the ComponentTreeRenderer which resolves "${displayName}" from the component registry.`
6
6
  );
7
7
  };
8
8
  Component.displayName = displayName;