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

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 (55) hide show
  1. package/dist/actions-HOXZPBTT.mjs +116 -0
  2. package/dist/actions-MFI2V4DX.mjs +116 -0
  3. package/dist/atoms/index.d.mts +2 -2
  4. package/dist/atoms/index.d.ts +2 -2
  5. package/dist/atoms/index.js +1 -1
  6. package/dist/atoms/index.mjs +1 -1
  7. package/dist/builtin-atoms-C-sNyYJl.d.mts +647 -0
  8. package/dist/builtin-atoms-C-sNyYJl.d.ts +647 -0
  9. package/dist/builtin-atoms-DCKrjG7i.d.mts +96 -0
  10. package/dist/builtin-atoms-DCKrjG7i.d.ts +96 -0
  11. package/dist/builtin-atoms-DRD3EwG6.d.mts +648 -0
  12. package/dist/builtin-atoms-DRD3EwG6.d.ts +648 -0
  13. package/dist/builtin-atoms-jt04b7Rw.d.mts +643 -0
  14. package/dist/builtin-atoms-jt04b7Rw.d.ts +643 -0
  15. package/dist/chunk-247T4GDJ.mjs +677 -0
  16. package/dist/chunk-3H6CR7E7.mjs +1924 -0
  17. package/dist/chunk-3PL6FL6I.mjs +96 -0
  18. package/dist/chunk-3SJSW3C4.mjs +2039 -0
  19. package/dist/chunk-5OI2VI57.mjs +1964 -0
  20. package/dist/chunk-CL6FYZ43.mjs +105 -0
  21. package/dist/chunk-ENQOCZI5.mjs +1938 -0
  22. package/dist/chunk-FB3WCZAU.mjs +512 -0
  23. package/dist/chunk-FBKUGKQI.mjs +1938 -0
  24. package/dist/chunk-GLJ7VC7Z.mjs +684 -0
  25. package/dist/chunk-HHMWR6NA.mjs +504 -0
  26. package/dist/chunk-HULEMSN2.mjs +120 -0
  27. package/dist/chunk-J5MW6CRU.mjs +1938 -0
  28. package/dist/chunk-PNTTKNYU.mjs +677 -0
  29. package/dist/chunk-TY5OTJP4.mjs +684 -0
  30. package/dist/chunk-WV7DVCP6.mjs +513 -0
  31. package/dist/chunk-YFMPTGUF.mjs +677 -0
  32. package/dist/chunk-ZAHMWAER.mjs +1960 -0
  33. package/dist/{chunk-2VJQJM7S.mjs → chunk-ZDWACXZN.mjs} +1 -1
  34. package/dist/composition-BJ6QQTWT.mjs +12 -0
  35. package/dist/composition-XBGKKCI7.mjs +57 -0
  36. package/dist/content-QVPFUG4P.mjs +246 -0
  37. package/dist/control-flow-CBREHWJW.mjs +35 -0
  38. package/dist/control-flow-FWBOI6SM.mjs +35 -0
  39. package/dist/control-flow-ZWUGCDSP.mjs +35 -0
  40. package/dist/data-WCMIZYKD.mjs +97 -0
  41. package/dist/grouping-E6F377VZ.mjs +204 -0
  42. package/dist/grouping-FRPOEXO3.mjs +233 -0
  43. package/dist/index.d.mts +4 -433
  44. package/dist/index.d.ts +4 -433
  45. package/dist/index.js +3671 -582
  46. package/dist/index.mjs +335 -1040
  47. package/dist/input-PUOZDNSI.mjs +222 -0
  48. package/dist/layout-RATDMCLP.mjs +106 -0
  49. package/dist/navigation-VCT7ZBMA.mjs +15 -0
  50. package/dist/navigation-WFV7YWOU.mjs +14 -0
  51. package/dist/player/index.d.mts +37 -11
  52. package/dist/player/index.d.ts +37 -11
  53. package/dist/player/index.js +3321 -193
  54. package/dist/player/index.mjs +55 -5
  55. package/package.json +4 -4
@@ -0,0 +1,684 @@
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, bind, style, ...rest }) => {
211
+ const isControlled = typeof onChange === "function";
212
+ const [localValue, setLocalValue] = React2.useState(value ?? "");
213
+ const handleChange = (e) => {
214
+ setLocalValue(e.target.value);
215
+ if (typeof onChange === "function") onChange(e);
216
+ };
217
+ return /* @__PURE__ */ jsxs2("div", { style: { marginBottom: 8 }, children: [
218
+ label ? /* @__PURE__ */ jsx2("label", { style: { display: "block", fontSize: 12, color: "#718096", marginBottom: 2 }, children: label }) : null,
219
+ /* @__PURE__ */ jsx2(
220
+ "input",
221
+ {
222
+ type: "text",
223
+ value: isControlled ? value ?? "" : localValue,
224
+ onChange: handleChange,
225
+ placeholder,
226
+ style: { width: "100%", padding: "6px 10px", border: "1px solid #e2e8f0", borderRadius: 6, fontSize: 14, ...style }
227
+ }
228
+ )
229
+ ] });
230
+ };
231
+ var SelectAtom = ({ value, onChange, options, label, placeholder, style }) => /* @__PURE__ */ jsxs2("div", { style: { marginBottom: 8 }, children: [
232
+ label ? /* @__PURE__ */ jsx2("label", { style: { display: "block", fontSize: 12, color: "#718096", marginBottom: 2 }, children: label }) : null,
233
+ /* @__PURE__ */ jsxs2(
234
+ "select",
235
+ {
236
+ value: value ?? "",
237
+ onChange,
238
+ style: { width: "100%", padding: "6px 10px", border: "1px solid #e2e8f0", borderRadius: 6, fontSize: 14, ...style },
239
+ children: [
240
+ placeholder ? /* @__PURE__ */ jsx2("option", { value: "", children: placeholder }) : null,
241
+ Array.isArray(options) && options.map((opt) => {
242
+ const v = typeof opt === "string" ? opt : opt.value;
243
+ const l = typeof opt === "string" ? opt : opt.label;
244
+ return /* @__PURE__ */ jsx2("option", { value: v, children: l }, v);
245
+ })
246
+ ]
247
+ }
248
+ )
249
+ ] });
250
+ var Card = ({ children, title, style, ...rest }) => /* @__PURE__ */ jsxs2("div", { style: { border: "1px solid #e2e8f0", borderRadius: 8, padding: 16, background: "#fff", ...style }, ...rest, children: [
251
+ title ? /* @__PURE__ */ jsx2("div", { style: { fontWeight: 600, fontSize: 16, marginBottom: 12 }, children: title }) : null,
252
+ children
253
+ ] });
254
+ var Section = ({ children, title, style, ...rest }) => /* @__PURE__ */ jsxs2("section", { style: { marginBottom: 24, ...style }, ...rest, children: [
255
+ title ? /* @__PURE__ */ jsx2("h3", { style: { fontSize: 18, fontWeight: 600, marginBottom: 8 }, children: title }) : null,
256
+ children
257
+ ] });
258
+ var Show = ({ when, children, fallback }) => when ? /* @__PURE__ */ jsx2(Fragment2, { children }) : /* @__PURE__ */ jsx2(Fragment2, { children: fallback ?? null });
259
+ var Each = ({ items, children, renderItem }) => {
260
+ if (!Array.isArray(items)) return null;
261
+ if (typeof renderItem === "function") return /* @__PURE__ */ jsx2(Fragment2, { children: items.map((item, i) => renderItem(item, i)) });
262
+ return /* @__PURE__ */ jsx2(Fragment2, { children });
263
+ };
264
+ var RouterContext = React2.createContext({ path: "/", navigate: () => {
265
+ } });
266
+ var Router = ({ children, basePath, className, style, ...rest }) => {
267
+ const [path, setPath] = React2.useState("/");
268
+ const navigate = React2.useCallback((to) => setPath(to), []);
269
+ return /* @__PURE__ */ jsx2(RouterContext.Provider, { value: { path, navigate }, children: /* @__PURE__ */ jsx2("div", { className, style, ...rest, children }) });
270
+ };
271
+ var Route = ({ children, path, exact, fallback: _fallback, className, style }) => {
272
+ const { path: currentPath } = React2.useContext(RouterContext);
273
+ const routePath = path || "/";
274
+ const isExact = exact !== false;
275
+ const matches = isExact ? currentPath === routePath || routePath === "/" && currentPath === "/" : currentPath.startsWith(routePath);
276
+ if (!matches) return null;
277
+ return /* @__PURE__ */ jsx2("div", { className, style, children });
278
+ };
279
+ var NavLink = ({ children, to, label, icon, className, style, ...rest }) => {
280
+ const { path, navigate } = React2.useContext(RouterContext);
281
+ const target = to || "/";
282
+ const isActive = path === target;
283
+ return /* @__PURE__ */ jsx2(
284
+ "button",
285
+ {
286
+ onClick: () => navigate(target),
287
+ className,
288
+ style: {
289
+ background: isActive ? "#edf2f7" : "transparent",
290
+ border: "none",
291
+ borderRadius: 4,
292
+ padding: "4px 12px",
293
+ fontSize: 13,
294
+ cursor: "pointer",
295
+ fontWeight: isActive ? 600 : 400,
296
+ color: isActive ? "#2d3748" : "#718096",
297
+ ...style
298
+ },
299
+ ...rest,
300
+ children: children || label || target
301
+ }
302
+ );
303
+ };
304
+ var RoleGuard = ({ children, role: _role, fallback: _fallback }) => {
305
+ return /* @__PURE__ */ jsx2(Fragment2, { children });
306
+ };
307
+ 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" });
308
+ var iconGlyphs = {
309
+ home: "\u2302",
310
+ settings: "\u2699",
311
+ plus: "+",
312
+ search: "\u{1F50D}",
313
+ box: "\u25A1",
314
+ inbox: "\u2709",
315
+ chevronRight: "\u203A",
316
+ chevronLeft: "\u2039",
317
+ x: "\u2715",
318
+ check: "\u2713",
319
+ edit: "\u270E",
320
+ trash: "\u{1F5D1}",
321
+ star: "\u2605",
322
+ heart: "\u2665",
323
+ user: "\u{1F464}",
324
+ menu: "\u2630",
325
+ close: "\u2715",
326
+ arrow_right: "\u2192",
327
+ arrow_left: "\u2190"
328
+ };
329
+ var Tabs = ({ children, tabs, defaultTab, style }) => {
330
+ const tabList = tabs || [];
331
+ const [active, setActive] = React2.useState(defaultTab || tabList[0]?.id || "");
332
+ return /* @__PURE__ */ jsxs2("div", { style, children: [
333
+ /* @__PURE__ */ jsx2("div", { style: { display: "flex", borderBottom: "1px solid #e2e8f0", marginBottom: 12 }, children: tabList.map((t) => /* @__PURE__ */ jsx2(
334
+ "button",
335
+ {
336
+ onClick: () => setActive(t.id),
337
+ 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" },
338
+ children: t.label
339
+ },
340
+ t.id
341
+ )) }),
342
+ children
343
+ ] });
344
+ };
345
+ var Accordion = ({ children, style }) => /* @__PURE__ */ jsx2("div", { style, children });
346
+ var Modal = ({ children, open, title, onClose: _onClose, style }) => {
347
+ if (!open) return null;
348
+ 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: [
349
+ title ? /* @__PURE__ */ jsx2("div", { style: { fontWeight: 600, fontSize: 18, marginBottom: 16 }, children: String(title) }) : null,
350
+ children
351
+ ] }) });
352
+ };
353
+ var Markdown = ({ content, children, style }) => /* @__PURE__ */ jsx2("div", { style: { lineHeight: 1.6, ...style }, children: content || children });
354
+ var ScrollArea = ({ children, maxHeight = 400, style }) => /* @__PURE__ */ jsx2("div", { style: { overflow: "auto", maxHeight, ...style }, children });
355
+ var Slot = ({ children, fallback }) => /* @__PURE__ */ jsx2(Fragment2, { children: children || fallback || null });
356
+ var ModuleOutlet = ({ children, module: moduleName, fallback }) => /* @__PURE__ */ jsx2("div", { "data-module": moduleName, children: children || fallback || /* @__PURE__ */ jsxs2("span", { style: { color: "#a0aec0", fontSize: 13 }, children: [
357
+ "Module: ",
358
+ moduleName
359
+ ] }) });
360
+ var builtinAtoms = {
361
+ // Layout
362
+ Stack,
363
+ Row,
364
+ Column,
365
+ Grid,
366
+ Divider,
367
+ Spacer,
368
+ // Typography
369
+ Text,
370
+ Heading,
371
+ Field,
372
+ Badge,
373
+ Image: ImageAtom,
374
+ Icon,
375
+ // Interactive
376
+ Button,
377
+ Link: LinkAtom,
378
+ // Form
379
+ TextInput,
380
+ Select: SelectAtom,
381
+ // Containers
382
+ Card,
383
+ Section,
384
+ Tabs,
385
+ Accordion,
386
+ Modal,
387
+ // Content
388
+ Markdown,
389
+ ScrollArea,
390
+ // Control Flow
391
+ Show,
392
+ Each,
393
+ // Routing
394
+ Router,
395
+ Route,
396
+ NavLink,
397
+ RoleGuard,
398
+ // Composition
399
+ Slot,
400
+ ModuleOutlet
401
+ };
402
+
403
+ // src/player/DevPlayer.tsx
404
+ import { useState, useCallback as useCallback2, useRef, useEffect, useMemo as useMemo2 } from "react";
405
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
406
+ var S = {
407
+ shell: {
408
+ display: "flex",
409
+ flexDirection: "column",
410
+ height: "100%",
411
+ minHeight: "100vh",
412
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
413
+ background: "#f7fafc",
414
+ color: "#1a202c"
415
+ },
416
+ toolbar: {
417
+ display: "flex",
418
+ alignItems: "center",
419
+ gap: 12,
420
+ padding: "8px 16px",
421
+ background: "#1a202c",
422
+ color: "#e2e8f0",
423
+ fontSize: 13,
424
+ flexShrink: 0
425
+ },
426
+ toolbarTitle: { fontWeight: 600, fontSize: 14 },
427
+ toolbarBadge: {
428
+ display: "inline-block",
429
+ padding: "1px 8px",
430
+ borderRadius: 4,
431
+ background: "#2d3748",
432
+ color: "#a0aec0",
433
+ fontSize: 11,
434
+ fontFamily: "monospace"
435
+ },
436
+ toolbarBtn: {
437
+ background: "none",
438
+ border: "1px solid #4a5568",
439
+ borderRadius: 4,
440
+ color: "#a0aec0",
441
+ padding: "2px 10px",
442
+ fontSize: 12,
443
+ cursor: "pointer"
444
+ },
445
+ toolbarBtnActive: {
446
+ background: "#2b6cb0",
447
+ borderColor: "#2b6cb0",
448
+ color: "#fff"
449
+ },
450
+ body: { display: "flex", flex: 1, overflow: "hidden" },
451
+ preview: { flex: 1, overflow: "auto", padding: 24 },
452
+ sidebar: {
453
+ width: 340,
454
+ flexShrink: 0,
455
+ borderLeft: "1px solid #e2e8f0",
456
+ background: "#fff",
457
+ overflow: "auto",
458
+ fontSize: 13
459
+ },
460
+ sidebarSection: { padding: "12px 16px", borderBottom: "1px solid #f0f0f0" },
461
+ sidebarHeading: {
462
+ fontSize: 11,
463
+ fontWeight: 700,
464
+ textTransform: "uppercase",
465
+ color: "#a0aec0",
466
+ letterSpacing: "0.05em",
467
+ marginBottom: 8
468
+ },
469
+ pre: {
470
+ background: "#f7fafc",
471
+ border: "1px solid #e2e8f0",
472
+ borderRadius: 6,
473
+ padding: "8px 12px",
474
+ fontSize: 12,
475
+ fontFamily: "monospace",
476
+ whiteSpace: "pre-wrap",
477
+ wordBreak: "break-word",
478
+ maxHeight: 260,
479
+ overflow: "auto"
480
+ },
481
+ eventRow: {
482
+ display: "flex",
483
+ gap: 8,
484
+ padding: "4px 0",
485
+ borderBottom: "1px solid #f7fafc",
486
+ fontSize: 12,
487
+ fontFamily: "monospace"
488
+ },
489
+ eventTime: { color: "#a0aec0", flexShrink: 0 },
490
+ eventName: { color: "#3182ce", fontWeight: 500 },
491
+ dot: (connected) => ({
492
+ width: 8,
493
+ height: 8,
494
+ borderRadius: "50%",
495
+ background: connected ? "#48bb78" : "#e53e3e",
496
+ flexShrink: 0
497
+ })
498
+ };
499
+ function useDevSocket(wsUrl, onReload) {
500
+ const [connected, setConnected] = useState(false);
501
+ const wsRef = useRef(null);
502
+ useEffect(() => {
503
+ if (typeof window === "undefined") return;
504
+ const url = wsUrl ?? `ws://${window.location.host}/__mm_dev`;
505
+ let ws;
506
+ let reconnectTimer;
507
+ function connect() {
508
+ try {
509
+ ws = new WebSocket(url);
510
+ wsRef.current = ws;
511
+ ws.onopen = () => setConnected(true);
512
+ ws.onclose = () => {
513
+ setConnected(false);
514
+ reconnectTimer = setTimeout(connect, 3e3);
515
+ };
516
+ ws.onmessage = (ev) => {
517
+ try {
518
+ const msg = JSON.parse(ev.data);
519
+ if (msg.type === "workflow:compiled" || msg.type === "workflow:rebuild") {
520
+ onReload?.();
521
+ }
522
+ } catch {
523
+ }
524
+ };
525
+ } catch {
526
+ reconnectTimer = setTimeout(connect, 3e3);
527
+ }
528
+ }
529
+ connect();
530
+ return () => {
531
+ clearTimeout(reconnectTimer);
532
+ wsRef.current?.close();
533
+ wsRef.current = null;
534
+ };
535
+ }, [wsUrl, onReload]);
536
+ return connected;
537
+ }
538
+ var DevPlayer = ({
539
+ tree,
540
+ scopes = {},
541
+ atoms: userAtoms,
542
+ title = "DevPlayer",
543
+ bare = false,
544
+ wsUrl,
545
+ onReload,
546
+ onEvent: externalOnEvent
547
+ }) => {
548
+ const [showSidebar, setShowSidebar] = useState(true);
549
+ const [events, setEvents] = useState([]);
550
+ const nextId = useRef(0);
551
+ const connected = useDevSocket(wsUrl, onReload);
552
+ const mergedAtoms = useMemo2(
553
+ () => ({ ...builtinAtoms, ...userAtoms }),
554
+ [userAtoms]
555
+ );
556
+ const handleEvent = useCallback2(
557
+ (name, payload) => {
558
+ setEvents((prev) => {
559
+ const entry = {
560
+ id: nextId.current++,
561
+ time: (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false }),
562
+ name,
563
+ payload
564
+ };
565
+ const next = [entry, ...prev];
566
+ return next.length > 100 ? next.slice(0, 100) : next;
567
+ });
568
+ externalOnEvent?.(name, payload);
569
+ },
570
+ [externalOnEvent]
571
+ );
572
+ if (bare) {
573
+ return /* @__PURE__ */ jsx3(
574
+ ComponentTreeRenderer,
575
+ {
576
+ tree,
577
+ scopes,
578
+ atoms: mergedAtoms,
579
+ onEvent: handleEvent
580
+ }
581
+ );
582
+ }
583
+ return /* @__PURE__ */ jsxs3("div", { style: S.shell, children: [
584
+ /* @__PURE__ */ jsxs3("div", { style: S.toolbar, children: [
585
+ /* @__PURE__ */ jsx3("div", { style: S.dot(connected), title: connected ? "HMR connected" : "HMR disconnected" }),
586
+ /* @__PURE__ */ jsx3("span", { style: S.toolbarTitle, children: title }),
587
+ /* @__PURE__ */ jsxs3("span", { style: S.toolbarBadge, children: [
588
+ Array.isArray(tree) ? tree.length : 1,
589
+ " node",
590
+ Array.isArray(tree) && tree.length !== 1 ? "s" : ""
591
+ ] }),
592
+ /* @__PURE__ */ jsxs3("span", { style: S.toolbarBadge, children: [
593
+ Object.keys(mergedAtoms).length,
594
+ " atoms"
595
+ ] }),
596
+ /* @__PURE__ */ jsx3("div", { style: { flex: 1 } }),
597
+ /* @__PURE__ */ jsx3(
598
+ "button",
599
+ {
600
+ style: { ...S.toolbarBtn, ...showSidebar ? S.toolbarBtnActive : {} },
601
+ onClick: () => setShowSidebar((v) => !v),
602
+ children: "Inspector"
603
+ }
604
+ )
605
+ ] }),
606
+ /* @__PURE__ */ jsxs3("div", { style: S.body, children: [
607
+ /* @__PURE__ */ jsx3("div", { style: S.preview, children: /* @__PURE__ */ jsx3(
608
+ ComponentTreeRenderer,
609
+ {
610
+ tree,
611
+ scopes,
612
+ atoms: mergedAtoms,
613
+ onEvent: handleEvent
614
+ }
615
+ ) }),
616
+ showSidebar && /* @__PURE__ */ jsxs3("div", { style: S.sidebar, children: [
617
+ /* @__PURE__ */ jsxs3("div", { style: S.sidebarSection, children: [
618
+ /* @__PURE__ */ jsx3("div", { style: S.sidebarHeading, children: "Scopes" }),
619
+ /* @__PURE__ */ jsx3("pre", { style: S.pre, children: JSON.stringify(scopes, null, 2) })
620
+ ] }),
621
+ /* @__PURE__ */ jsxs3("div", { style: S.sidebarSection, children: [
622
+ /* @__PURE__ */ jsxs3("div", { style: S.sidebarHeading, children: [
623
+ "Atoms (",
624
+ Object.keys(mergedAtoms).length,
625
+ ")"
626
+ ] }),
627
+ /* @__PURE__ */ jsx3("div", { style: { display: "flex", flexWrap: "wrap", gap: 4 }, children: Object.keys(mergedAtoms).sort().map((name) => /* @__PURE__ */ jsx3(
628
+ "span",
629
+ {
630
+ style: {
631
+ display: "inline-block",
632
+ padding: "1px 6px",
633
+ borderRadius: 3,
634
+ background: userAtoms?.[name] ? "#ebf8ff" : "#f7fafc",
635
+ border: `1px solid ${userAtoms?.[name] ? "#90cdf4" : "#e2e8f0"}`,
636
+ fontSize: 11,
637
+ fontFamily: "monospace",
638
+ color: userAtoms?.[name] ? "#2b6cb0" : "#718096"
639
+ },
640
+ children: name
641
+ },
642
+ name
643
+ )) })
644
+ ] }),
645
+ /* @__PURE__ */ jsxs3("div", { style: S.sidebarSection, children: [
646
+ /* @__PURE__ */ jsxs3("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 8 }, children: [
647
+ /* @__PURE__ */ jsxs3("div", { style: S.sidebarHeading, children: [
648
+ "Events (",
649
+ events.length,
650
+ ")"
651
+ ] }),
652
+ events.length > 0 && /* @__PURE__ */ jsx3(
653
+ "button",
654
+ {
655
+ style: { background: "none", border: "none", color: "#a0aec0", fontSize: 11, cursor: "pointer" },
656
+ onClick: () => setEvents([]),
657
+ children: "Clear"
658
+ }
659
+ )
660
+ ] }),
661
+ events.length === 0 && /* @__PURE__ */ jsx3("div", { style: { color: "#a0aec0", fontSize: 12, fontStyle: "italic" }, children: "No events yet" }),
662
+ events.slice(0, 50).map((e) => /* @__PURE__ */ jsxs3("div", { style: S.eventRow, children: [
663
+ /* @__PURE__ */ jsx3("span", { style: S.eventTime, children: e.time }),
664
+ /* @__PURE__ */ jsx3("span", { style: S.eventName, children: e.name }),
665
+ e.payload !== void 0 && /* @__PURE__ */ jsx3("span", { style: { color: "#718096", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: JSON.stringify(e.payload) })
666
+ ] }, e.id))
667
+ ] }),
668
+ /* @__PURE__ */ jsxs3("div", { style: S.sidebarSection, children: [
669
+ /* @__PURE__ */ jsx3("div", { style: S.sidebarHeading, children: "Tree (JSON)" }),
670
+ /* @__PURE__ */ jsx3("pre", { style: { ...S.pre, maxHeight: 400 }, children: JSON.stringify(tree, null, 2) })
671
+ ] })
672
+ ] })
673
+ ] })
674
+ ] });
675
+ };
676
+
677
+ export {
678
+ containsExpression,
679
+ evaluateExpression,
680
+ evaluateProp,
681
+ ComponentTreeRenderer,
682
+ builtinAtoms,
683
+ DevPlayer
684
+ };