@mmapp/react 0.1.0-alpha.11 → 0.1.0-alpha.12

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/dist/index.mjs CHANGED
@@ -3599,6 +3599,559 @@ function useCollection(definition, options = {}) {
3599
3599
  return handle;
3600
3600
  }
3601
3601
 
3602
+ // src/player/ComponentTreeRenderer.tsx
3603
+ import React, { useMemo as useMemo17, useCallback as useCallback21 } from "react";
3604
+
3605
+ // src/player/evaluator.ts
3606
+ var EXPR_PATTERN = /\{\{(.+?)\}\}/g;
3607
+ function containsExpression(value) {
3608
+ return typeof value === "string" && EXPR_PATTERN.test(value);
3609
+ }
3610
+ function resolvePath(path, scope) {
3611
+ const parts = path.trim().split(".");
3612
+ let current = scope;
3613
+ for (const part of parts) {
3614
+ if (current == null || typeof current !== "object") return void 0;
3615
+ current = current[part];
3616
+ }
3617
+ return current;
3618
+ }
3619
+ function evaluateExpression(expr2, scopes) {
3620
+ const trimmed = expr2.trim();
3621
+ if (trimmed.startsWith("'") && trimmed.endsWith("'") || trimmed.startsWith('"') && trimmed.endsWith('"')) {
3622
+ return trimmed.slice(1, -1);
3623
+ }
3624
+ if (/^-?\d+(\.\d+)?$/.test(trimmed)) {
3625
+ return Number(trimmed);
3626
+ }
3627
+ if (trimmed === "true") return true;
3628
+ if (trimmed === "false") return false;
3629
+ if (trimmed === "null" || trimmed === "undefined") return void 0;
3630
+ const flatScope = { ...scopes };
3631
+ if (scopes.state_data && typeof scopes.state_data === "object") {
3632
+ Object.assign(flatScope, scopes.state_data);
3633
+ }
3634
+ if (scopes.context && typeof scopes.context === "object") {
3635
+ Object.assign(flatScope, scopes.context);
3636
+ }
3637
+ return resolvePath(trimmed, flatScope);
3638
+ }
3639
+ function evaluateProp(value, scopes) {
3640
+ if (typeof value !== "string") return value;
3641
+ const fullMatch = value.match(/^\{\{(.+)\}\}$/s);
3642
+ if (fullMatch) {
3643
+ return evaluateExpression(fullMatch[1], scopes);
3644
+ }
3645
+ if (containsExpression(value)) {
3646
+ return value.replace(EXPR_PATTERN, (_, expr2) => {
3647
+ const result = evaluateExpression(expr2, scopes);
3648
+ return result == null ? "" : String(result);
3649
+ });
3650
+ }
3651
+ return value;
3652
+ }
3653
+
3654
+ // src/player/ComponentTreeRenderer.tsx
3655
+ import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
3656
+ 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: [
3657
+ /* @__PURE__ */ jsxs("span", { style: { fontWeight: 600 }, children: [
3658
+ "Unknown: ",
3659
+ type
3660
+ ] }),
3661
+ children && /* @__PURE__ */ jsx2("div", { style: { marginTop: 4 }, children })
3662
+ ] });
3663
+ var RenderNode = ({ node, scopes, atoms, onEvent }) => {
3664
+ if (node.$if) {
3665
+ const condition = evaluateProp(node.$if, scopes);
3666
+ if (!condition) return null;
3667
+ }
3668
+ if (node.$for) {
3669
+ const { each, as, key: keyField } = node.$for;
3670
+ const items = evaluateProp(each, scopes);
3671
+ if (!Array.isArray(items)) return null;
3672
+ return /* @__PURE__ */ jsx2(Fragment, { children: items.map((item, index) => {
3673
+ const loopScopes = {
3674
+ ...scopes,
3675
+ state_data: {
3676
+ ...scopes.state_data ?? {},
3677
+ [as]: item,
3678
+ [`${as}Index`]: index
3679
+ }
3680
+ };
3681
+ const nodeWithoutFor = { ...node, $for: void 0 };
3682
+ const itemKey = keyField ? String(item[keyField] ?? index) : String(index);
3683
+ return /* @__PURE__ */ jsx2(RenderNode, { node: nodeWithoutFor, scopes: loopScopes, atoms, onEvent }, itemKey);
3684
+ }) });
3685
+ }
3686
+ const Component = atoms[node.type];
3687
+ if (!Component) {
3688
+ return /* @__PURE__ */ jsx2(UnknownAtom, { type: node.type });
3689
+ }
3690
+ const evaluatedProps = {};
3691
+ if (node.props) {
3692
+ for (const [key, value] of Object.entries(node.props)) {
3693
+ if (key.startsWith("on") && typeof value === "string") {
3694
+ evaluatedProps[key] = (...args) => {
3695
+ if (containsExpression(value)) {
3696
+ evaluateExpression(value.replace(/^\{\{|\}\}$/g, ""), scopes);
3697
+ } else {
3698
+ onEvent(value, args[0]);
3699
+ }
3700
+ };
3701
+ } else {
3702
+ evaluatedProps[key] = evaluateProp(value, scopes);
3703
+ }
3704
+ }
3705
+ }
3706
+ let children = null;
3707
+ if (node.children) {
3708
+ if (typeof node.children === "string") {
3709
+ children = evaluateProp(node.children, scopes);
3710
+ } else if (Array.isArray(node.children)) {
3711
+ children = node.children.map((child, index) => /* @__PURE__ */ jsx2(RenderNode, { node: child, scopes, atoms, onEvent }, index));
3712
+ }
3713
+ }
3714
+ return /* @__PURE__ */ jsx2(Component, { ...evaluatedProps, children });
3715
+ };
3716
+ var CTRErrorBoundary = class extends React.Component {
3717
+ constructor(props) {
3718
+ super(props);
3719
+ this.state = { hasError: false };
3720
+ }
3721
+ static getDerivedStateFromError(error) {
3722
+ return { hasError: true, error };
3723
+ }
3724
+ componentDidCatch(error, errorInfo) {
3725
+ console.error("CTR rendering error:", error, errorInfo);
3726
+ }
3727
+ render() {
3728
+ if (this.state.hasError) {
3729
+ return this.props.fallback || /* @__PURE__ */ jsxs("div", { style: { padding: 16, background: "#fff5f5", border: "1px solid #fed7d7", borderRadius: 8 }, children: [
3730
+ /* @__PURE__ */ jsx2("strong", { style: { color: "#c53030" }, children: "Rendering Error" }),
3731
+ /* @__PURE__ */ jsx2("p", { style: { color: "#e53e3e", fontSize: 14, marginTop: 4 }, children: this.state.error?.message || "An error occurred while rendering" })
3732
+ ] });
3733
+ }
3734
+ return this.props.children;
3735
+ }
3736
+ };
3737
+ var ComponentTreeRenderer = ({
3738
+ tree,
3739
+ scopes,
3740
+ atoms = {},
3741
+ onEvent = () => {
3742
+ },
3743
+ fallback
3744
+ }) => {
3745
+ const allAtoms = useMemo17(() => ({ ...atoms }), [atoms]);
3746
+ const handleEvent = useCallback21(
3747
+ (eventName, payload) => onEvent(eventName, payload),
3748
+ [onEvent]
3749
+ );
3750
+ const nodes = Array.isArray(tree) ? tree : [tree];
3751
+ return /* @__PURE__ */ jsx2(CTRErrorBoundary, { fallback, children: nodes.map((node, index) => /* @__PURE__ */ jsx2(RenderNode, { node, scopes, atoms: allAtoms, onEvent: handleEvent }, index)) });
3752
+ };
3753
+
3754
+ // src/player/DevPlayer.tsx
3755
+ import { useState as useState21, useCallback as useCallback22, useRef as useRef25, useEffect as useEffect22, useMemo as useMemo18 } from "react";
3756
+
3757
+ // src/player/builtin-atoms.tsx
3758
+ import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
3759
+ var Stack = ({ children, gap = 8, style, ...rest }) => /* @__PURE__ */ jsx3("div", { style: { display: "flex", flexDirection: "column", gap, ...style }, ...rest, children });
3760
+ var Row = ({ children, gap = 8, align, justify, style, ...rest }) => /* @__PURE__ */ jsx3("div", { style: { display: "flex", flexDirection: "row", gap, alignItems: align, justifyContent: justify, ...style }, ...rest, children });
3761
+ var Column = ({ children, span, style, ...rest }) => /* @__PURE__ */ jsx3("div", { style: { flex: span ? `0 0 ${Number(span) / 12 * 100}%` : 1, ...style }, ...rest, children });
3762
+ var Grid = ({ children, columns = 2, gap = 8, style, ...rest }) => /* @__PURE__ */ jsx3("div", { style: { display: "grid", gridTemplateColumns: `repeat(${columns}, 1fr)`, gap, ...style }, ...rest, children });
3763
+ var Divider = ({ style }) => /* @__PURE__ */ jsx3("hr", { style: { border: "none", borderTop: "1px solid #e2e8f0", margin: "8px 0", ...style } });
3764
+ var Spacer = ({ size = 16 }) => /* @__PURE__ */ jsx3("div", { style: { height: size, flexShrink: 0 } });
3765
+ var Text = ({ children, size, weight, color, style, ...rest }) => /* @__PURE__ */ jsx3("span", { style: { fontSize: size, fontWeight: weight, color, ...style }, ...rest, children });
3766
+ var Heading = ({ children, level = 2, style, ...rest }) => {
3767
+ const lvl = Math.min(Math.max(Number(level), 1), 6);
3768
+ const s = { margin: "0 0 8px", ...style };
3769
+ const c = children;
3770
+ if (lvl === 1) return /* @__PURE__ */ jsx3("h1", { style: s, ...rest, children: c });
3771
+ if (lvl === 2) return /* @__PURE__ */ jsx3("h2", { style: s, ...rest, children: c });
3772
+ if (lvl === 3) return /* @__PURE__ */ jsx3("h3", { style: s, ...rest, children: c });
3773
+ if (lvl === 4) return /* @__PURE__ */ jsx3("h4", { style: s, ...rest, children: c });
3774
+ if (lvl === 5) return /* @__PURE__ */ jsx3("h5", { style: s, ...rest, children: c });
3775
+ return /* @__PURE__ */ jsx3("h6", { style: s, ...rest, children: c });
3776
+ };
3777
+ var Field = ({ label, value, children, style }) => /* @__PURE__ */ jsxs2("div", { style: { marginBottom: 8, ...style }, children: [
3778
+ label ? /* @__PURE__ */ jsx3("div", { style: { fontSize: 12, color: "#718096", marginBottom: 2 }, children: label }) : null,
3779
+ /* @__PURE__ */ jsx3("div", { style: { fontSize: 14 }, children: children ?? value ?? "\u2014" })
3780
+ ] });
3781
+ var Badge = ({ children, variant = "default", style }) => {
3782
+ const colors = {
3783
+ default: { bg: "#edf2f7", fg: "#4a5568" },
3784
+ success: { bg: "#c6f6d5", fg: "#276749" },
3785
+ warning: { bg: "#fefcbf", fg: "#975a16" },
3786
+ error: { bg: "#fed7d7", fg: "#9b2c2c" },
3787
+ info: { bg: "#bee3f8", fg: "#2a4365" }
3788
+ };
3789
+ const c = colors[variant] ?? colors.default;
3790
+ return /* @__PURE__ */ jsx3("span", { style: { display: "inline-block", padding: "2px 8px", borderRadius: 9999, fontSize: 12, fontWeight: 500, background: c.bg, color: c.fg, ...style }, children });
3791
+ };
3792
+ var ImageAtom = ({ src, alt, width, height, style, ...rest }) => /* @__PURE__ */ jsx3("img", { src, alt: alt ?? "", width, height, style: { maxWidth: "100%", ...style }, ...rest });
3793
+ var Button = ({ children, onClick, variant = "primary", disabled, style, ...rest }) => {
3794
+ const styles = {
3795
+ primary: { background: "#3182ce", color: "#fff", border: "none" },
3796
+ secondary: { background: "#edf2f7", color: "#4a5568", border: "1px solid #e2e8f0" },
3797
+ danger: { background: "#e53e3e", color: "#fff", border: "none" },
3798
+ ghost: { background: "transparent", color: "#4a5568", border: "none" }
3799
+ };
3800
+ const base = styles[variant] ?? styles.primary;
3801
+ return /* @__PURE__ */ jsx3(
3802
+ "button",
3803
+ {
3804
+ onClick,
3805
+ disabled,
3806
+ style: { padding: "6px 16px", borderRadius: 6, fontSize: 14, fontWeight: 500, cursor: disabled ? "not-allowed" : "pointer", opacity: disabled ? 0.5 : 1, ...base, ...style },
3807
+ ...rest,
3808
+ children
3809
+ }
3810
+ );
3811
+ };
3812
+ var LinkAtom = ({ children, href, style, ...rest }) => /* @__PURE__ */ jsx3("a", { href, style: { color: "#3182ce", textDecoration: "underline", ...style }, ...rest, children });
3813
+ var TextInput = ({ value, onChange, placeholder, label, style, ...rest }) => /* @__PURE__ */ jsxs2("div", { style: { marginBottom: 8 }, children: [
3814
+ label ? /* @__PURE__ */ jsx3("label", { style: { display: "block", fontSize: 12, color: "#718096", marginBottom: 2 }, children: label }) : null,
3815
+ /* @__PURE__ */ jsx3(
3816
+ "input",
3817
+ {
3818
+ type: "text",
3819
+ value: value ?? "",
3820
+ onChange,
3821
+ placeholder,
3822
+ style: { width: "100%", padding: "6px 10px", border: "1px solid #e2e8f0", borderRadius: 6, fontSize: 14, ...style },
3823
+ ...rest
3824
+ }
3825
+ )
3826
+ ] });
3827
+ var SelectAtom = ({ value, onChange, options, label, placeholder, style }) => /* @__PURE__ */ jsxs2("div", { style: { marginBottom: 8 }, children: [
3828
+ label ? /* @__PURE__ */ jsx3("label", { style: { display: "block", fontSize: 12, color: "#718096", marginBottom: 2 }, children: label }) : null,
3829
+ /* @__PURE__ */ jsxs2(
3830
+ "select",
3831
+ {
3832
+ value: value ?? "",
3833
+ onChange,
3834
+ style: { width: "100%", padding: "6px 10px", border: "1px solid #e2e8f0", borderRadius: 6, fontSize: 14, ...style },
3835
+ children: [
3836
+ placeholder ? /* @__PURE__ */ jsx3("option", { value: "", children: placeholder }) : null,
3837
+ Array.isArray(options) && options.map((opt) => {
3838
+ const v = typeof opt === "string" ? opt : opt.value;
3839
+ const l = typeof opt === "string" ? opt : opt.label;
3840
+ return /* @__PURE__ */ jsx3("option", { value: v, children: l }, v);
3841
+ })
3842
+ ]
3843
+ }
3844
+ )
3845
+ ] });
3846
+ var Card = ({ children, title, style, ...rest }) => /* @__PURE__ */ jsxs2("div", { style: { border: "1px solid #e2e8f0", borderRadius: 8, padding: 16, background: "#fff", ...style }, ...rest, children: [
3847
+ title ? /* @__PURE__ */ jsx3("div", { style: { fontWeight: 600, fontSize: 16, marginBottom: 12 }, children: title }) : null,
3848
+ children
3849
+ ] });
3850
+ var Section = ({ children, title, style, ...rest }) => /* @__PURE__ */ jsxs2("section", { style: { marginBottom: 24, ...style }, ...rest, children: [
3851
+ title ? /* @__PURE__ */ jsx3("h3", { style: { fontSize: 18, fontWeight: 600, marginBottom: 8 }, children: title }) : null,
3852
+ children
3853
+ ] });
3854
+ var Show = ({ when: when2, children, fallback }) => when2 ? /* @__PURE__ */ jsx3(Fragment2, { children }) : /* @__PURE__ */ jsx3(Fragment2, { children: fallback ?? null });
3855
+ var Each = ({ items, children, renderItem }) => {
3856
+ if (!Array.isArray(items)) return null;
3857
+ if (typeof renderItem === "function") return /* @__PURE__ */ jsx3(Fragment2, { children: items.map((item, i) => renderItem(item, i)) });
3858
+ return /* @__PURE__ */ jsx3(Fragment2, { children });
3859
+ };
3860
+ var builtinAtoms = {
3861
+ Stack,
3862
+ Row,
3863
+ Column,
3864
+ Grid,
3865
+ Divider,
3866
+ Spacer,
3867
+ Text,
3868
+ Heading,
3869
+ Field,
3870
+ Badge,
3871
+ Image: ImageAtom,
3872
+ Button,
3873
+ Link: LinkAtom,
3874
+ TextInput,
3875
+ Select: SelectAtom,
3876
+ Card,
3877
+ Section,
3878
+ Show,
3879
+ Each
3880
+ };
3881
+
3882
+ // src/player/DevPlayer.tsx
3883
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
3884
+ var S = {
3885
+ shell: {
3886
+ display: "flex",
3887
+ flexDirection: "column",
3888
+ height: "100%",
3889
+ minHeight: "100vh",
3890
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
3891
+ background: "#f7fafc",
3892
+ color: "#1a202c"
3893
+ },
3894
+ toolbar: {
3895
+ display: "flex",
3896
+ alignItems: "center",
3897
+ gap: 12,
3898
+ padding: "8px 16px",
3899
+ background: "#1a202c",
3900
+ color: "#e2e8f0",
3901
+ fontSize: 13,
3902
+ flexShrink: 0
3903
+ },
3904
+ toolbarTitle: { fontWeight: 600, fontSize: 14 },
3905
+ toolbarBadge: {
3906
+ display: "inline-block",
3907
+ padding: "1px 8px",
3908
+ borderRadius: 4,
3909
+ background: "#2d3748",
3910
+ color: "#a0aec0",
3911
+ fontSize: 11,
3912
+ fontFamily: "monospace"
3913
+ },
3914
+ toolbarBtn: {
3915
+ background: "none",
3916
+ border: "1px solid #4a5568",
3917
+ borderRadius: 4,
3918
+ color: "#a0aec0",
3919
+ padding: "2px 10px",
3920
+ fontSize: 12,
3921
+ cursor: "pointer"
3922
+ },
3923
+ toolbarBtnActive: {
3924
+ background: "#2b6cb0",
3925
+ borderColor: "#2b6cb0",
3926
+ color: "#fff"
3927
+ },
3928
+ body: { display: "flex", flex: 1, overflow: "hidden" },
3929
+ preview: { flex: 1, overflow: "auto", padding: 24 },
3930
+ sidebar: {
3931
+ width: 340,
3932
+ flexShrink: 0,
3933
+ borderLeft: "1px solid #e2e8f0",
3934
+ background: "#fff",
3935
+ overflow: "auto",
3936
+ fontSize: 13
3937
+ },
3938
+ sidebarSection: { padding: "12px 16px", borderBottom: "1px solid #f0f0f0" },
3939
+ sidebarHeading: {
3940
+ fontSize: 11,
3941
+ fontWeight: 700,
3942
+ textTransform: "uppercase",
3943
+ color: "#a0aec0",
3944
+ letterSpacing: "0.05em",
3945
+ marginBottom: 8
3946
+ },
3947
+ pre: {
3948
+ background: "#f7fafc",
3949
+ border: "1px solid #e2e8f0",
3950
+ borderRadius: 6,
3951
+ padding: "8px 12px",
3952
+ fontSize: 12,
3953
+ fontFamily: "monospace",
3954
+ whiteSpace: "pre-wrap",
3955
+ wordBreak: "break-word",
3956
+ maxHeight: 260,
3957
+ overflow: "auto"
3958
+ },
3959
+ eventRow: {
3960
+ display: "flex",
3961
+ gap: 8,
3962
+ padding: "4px 0",
3963
+ borderBottom: "1px solid #f7fafc",
3964
+ fontSize: 12,
3965
+ fontFamily: "monospace"
3966
+ },
3967
+ eventTime: { color: "#a0aec0", flexShrink: 0 },
3968
+ eventName: { color: "#3182ce", fontWeight: 500 },
3969
+ dot: (connected) => ({
3970
+ width: 8,
3971
+ height: 8,
3972
+ borderRadius: "50%",
3973
+ background: connected ? "#48bb78" : "#e53e3e",
3974
+ flexShrink: 0
3975
+ })
3976
+ };
3977
+ function useDevSocket(wsUrl, onReload) {
3978
+ const [connected, setConnected] = useState21(false);
3979
+ const wsRef = useRef25(null);
3980
+ useEffect22(() => {
3981
+ if (typeof window === "undefined") return;
3982
+ const url = wsUrl ?? `ws://${window.location.host}/__mm_dev`;
3983
+ let ws;
3984
+ let reconnectTimer;
3985
+ function connect() {
3986
+ try {
3987
+ ws = new WebSocket(url);
3988
+ wsRef.current = ws;
3989
+ ws.onopen = () => setConnected(true);
3990
+ ws.onclose = () => {
3991
+ setConnected(false);
3992
+ reconnectTimer = setTimeout(connect, 3e3);
3993
+ };
3994
+ ws.onmessage = (ev) => {
3995
+ try {
3996
+ const msg = JSON.parse(ev.data);
3997
+ if (msg.type === "workflow:compiled" || msg.type === "workflow:rebuild") {
3998
+ onReload?.();
3999
+ }
4000
+ } catch {
4001
+ }
4002
+ };
4003
+ } catch {
4004
+ reconnectTimer = setTimeout(connect, 3e3);
4005
+ }
4006
+ }
4007
+ connect();
4008
+ return () => {
4009
+ clearTimeout(reconnectTimer);
4010
+ wsRef.current?.close();
4011
+ wsRef.current = null;
4012
+ };
4013
+ }, [wsUrl, onReload]);
4014
+ return connected;
4015
+ }
4016
+ var DevPlayer = ({
4017
+ tree,
4018
+ scopes = {},
4019
+ atoms: userAtoms,
4020
+ title = "DevPlayer",
4021
+ bare = false,
4022
+ wsUrl,
4023
+ onReload,
4024
+ onEvent: externalOnEvent
4025
+ }) => {
4026
+ const [showSidebar, setShowSidebar] = useState21(true);
4027
+ const [events, setEvents] = useState21([]);
4028
+ const nextId = useRef25(0);
4029
+ const connected = useDevSocket(wsUrl, onReload);
4030
+ const mergedAtoms = useMemo18(
4031
+ () => ({ ...builtinAtoms, ...userAtoms }),
4032
+ [userAtoms]
4033
+ );
4034
+ const handleEvent = useCallback22(
4035
+ (name, payload) => {
4036
+ setEvents((prev) => {
4037
+ const entry = {
4038
+ id: nextId.current++,
4039
+ time: (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false }),
4040
+ name,
4041
+ payload
4042
+ };
4043
+ const next = [entry, ...prev];
4044
+ return next.length > 100 ? next.slice(0, 100) : next;
4045
+ });
4046
+ externalOnEvent?.(name, payload);
4047
+ },
4048
+ [externalOnEvent]
4049
+ );
4050
+ if (bare) {
4051
+ return /* @__PURE__ */ jsx4(
4052
+ ComponentTreeRenderer,
4053
+ {
4054
+ tree,
4055
+ scopes,
4056
+ atoms: mergedAtoms,
4057
+ onEvent: handleEvent
4058
+ }
4059
+ );
4060
+ }
4061
+ return /* @__PURE__ */ jsxs3("div", { style: S.shell, children: [
4062
+ /* @__PURE__ */ jsxs3("div", { style: S.toolbar, children: [
4063
+ /* @__PURE__ */ jsx4("div", { style: S.dot(connected), title: connected ? "HMR connected" : "HMR disconnected" }),
4064
+ /* @__PURE__ */ jsx4("span", { style: S.toolbarTitle, children: title }),
4065
+ /* @__PURE__ */ jsxs3("span", { style: S.toolbarBadge, children: [
4066
+ Array.isArray(tree) ? tree.length : 1,
4067
+ " node",
4068
+ Array.isArray(tree) && tree.length !== 1 ? "s" : ""
4069
+ ] }),
4070
+ /* @__PURE__ */ jsxs3("span", { style: S.toolbarBadge, children: [
4071
+ Object.keys(mergedAtoms).length,
4072
+ " atoms"
4073
+ ] }),
4074
+ /* @__PURE__ */ jsx4("div", { style: { flex: 1 } }),
4075
+ /* @__PURE__ */ jsx4(
4076
+ "button",
4077
+ {
4078
+ style: { ...S.toolbarBtn, ...showSidebar ? S.toolbarBtnActive : {} },
4079
+ onClick: () => setShowSidebar((v) => !v),
4080
+ children: "Inspector"
4081
+ }
4082
+ )
4083
+ ] }),
4084
+ /* @__PURE__ */ jsxs3("div", { style: S.body, children: [
4085
+ /* @__PURE__ */ jsx4("div", { style: S.preview, children: /* @__PURE__ */ jsx4(
4086
+ ComponentTreeRenderer,
4087
+ {
4088
+ tree,
4089
+ scopes,
4090
+ atoms: mergedAtoms,
4091
+ onEvent: handleEvent
4092
+ }
4093
+ ) }),
4094
+ showSidebar && /* @__PURE__ */ jsxs3("div", { style: S.sidebar, children: [
4095
+ /* @__PURE__ */ jsxs3("div", { style: S.sidebarSection, children: [
4096
+ /* @__PURE__ */ jsx4("div", { style: S.sidebarHeading, children: "Scopes" }),
4097
+ /* @__PURE__ */ jsx4("pre", { style: S.pre, children: JSON.stringify(scopes, null, 2) })
4098
+ ] }),
4099
+ /* @__PURE__ */ jsxs3("div", { style: S.sidebarSection, children: [
4100
+ /* @__PURE__ */ jsxs3("div", { style: S.sidebarHeading, children: [
4101
+ "Atoms (",
4102
+ Object.keys(mergedAtoms).length,
4103
+ ")"
4104
+ ] }),
4105
+ /* @__PURE__ */ jsx4("div", { style: { display: "flex", flexWrap: "wrap", gap: 4 }, children: Object.keys(mergedAtoms).sort().map((name) => /* @__PURE__ */ jsx4(
4106
+ "span",
4107
+ {
4108
+ style: {
4109
+ display: "inline-block",
4110
+ padding: "1px 6px",
4111
+ borderRadius: 3,
4112
+ background: userAtoms?.[name] ? "#ebf8ff" : "#f7fafc",
4113
+ border: `1px solid ${userAtoms?.[name] ? "#90cdf4" : "#e2e8f0"}`,
4114
+ fontSize: 11,
4115
+ fontFamily: "monospace",
4116
+ color: userAtoms?.[name] ? "#2b6cb0" : "#718096"
4117
+ },
4118
+ children: name
4119
+ },
4120
+ name
4121
+ )) })
4122
+ ] }),
4123
+ /* @__PURE__ */ jsxs3("div", { style: S.sidebarSection, children: [
4124
+ /* @__PURE__ */ jsxs3("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 8 }, children: [
4125
+ /* @__PURE__ */ jsxs3("div", { style: S.sidebarHeading, children: [
4126
+ "Events (",
4127
+ events.length,
4128
+ ")"
4129
+ ] }),
4130
+ events.length > 0 && /* @__PURE__ */ jsx4(
4131
+ "button",
4132
+ {
4133
+ style: { background: "none", border: "none", color: "#a0aec0", fontSize: 11, cursor: "pointer" },
4134
+ onClick: () => setEvents([]),
4135
+ children: "Clear"
4136
+ }
4137
+ )
4138
+ ] }),
4139
+ events.length === 0 && /* @__PURE__ */ jsx4("div", { style: { color: "#a0aec0", fontSize: 12, fontStyle: "italic" }, children: "No events yet" }),
4140
+ events.slice(0, 50).map((e) => /* @__PURE__ */ jsxs3("div", { style: S.eventRow, children: [
4141
+ /* @__PURE__ */ jsx4("span", { style: S.eventTime, children: e.time }),
4142
+ /* @__PURE__ */ jsx4("span", { style: S.eventName, children: e.name }),
4143
+ e.payload !== void 0 && /* @__PURE__ */ jsx4("span", { style: { color: "#718096", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: JSON.stringify(e.payload) })
4144
+ ] }, e.id))
4145
+ ] }),
4146
+ /* @__PURE__ */ jsxs3("div", { style: S.sidebarSection, children: [
4147
+ /* @__PURE__ */ jsx4("div", { style: S.sidebarHeading, children: "Tree (JSON)" }),
4148
+ /* @__PURE__ */ jsx4("pre", { style: { ...S.pre, maxHeight: 400 }, children: JSON.stringify(tree, null, 2) })
4149
+ ] })
4150
+ ] })
4151
+ ] })
4152
+ ] });
4153
+ };
4154
+
3602
4155
  // src/atoms/index.ts
3603
4156
  function stub(displayName) {
3604
4157
  const Component = () => {
@@ -3609,28 +4162,28 @@ function stub(displayName) {
3609
4162
  Component.displayName = displayName;
3610
4163
  return Component;
3611
4164
  }
3612
- var Stack = stub("Stack");
3613
- var Row = stub("Row");
3614
- var Column = stub("Column");
3615
- var Grid = stub("Grid");
3616
- var Divider = stub("Divider");
3617
- var Spacer = stub("Spacer");
3618
- var Text = stub("Text");
3619
- var Heading = stub("Heading");
3620
- var Field = stub("Field");
4165
+ var Stack2 = stub("Stack");
4166
+ var Row2 = stub("Row");
4167
+ var Column2 = stub("Column");
4168
+ var Grid2 = stub("Grid");
4169
+ var Divider2 = stub("Divider");
4170
+ var Spacer2 = stub("Spacer");
4171
+ var Text2 = stub("Text");
4172
+ var Heading2 = stub("Heading");
4173
+ var Field2 = stub("Field");
3621
4174
  var Image = stub("Image");
3622
- var Badge = stub("Badge");
4175
+ var Badge2 = stub("Badge");
3623
4176
  var Icon = stub("Icon");
3624
- var Button = stub("Button");
4177
+ var Button2 = stub("Button");
3625
4178
  var Link = stub("Link");
3626
- var Show = stub("Show");
3627
- var Each = stub("Each");
3628
- var Card = stub("Card");
4179
+ var Show2 = stub("Show");
4180
+ var Each2 = stub("Each");
4181
+ var Card2 = stub("Card");
3629
4182
  var Tabs = stub("Tabs");
3630
4183
  var Accordion = stub("Accordion");
3631
- var Section = stub("Section");
4184
+ var Section2 = stub("Section");
3632
4185
  var Modal = stub("Modal");
3633
- var TextInput = stub("TextInput");
4186
+ var TextInput2 = stub("TextInput");
3634
4187
  var Select = stub("Select");
3635
4188
  var Markdown = stub("Markdown");
3636
4189
  var ScrollArea = stub("ScrollArea");
@@ -3730,7 +4283,7 @@ function djb2Hash(str) {
3730
4283
  }
3731
4284
 
3732
4285
  // src/authoring.ts
3733
- function useState21(_defaultOrKey) {
4286
+ function useState22(_defaultOrKey) {
3734
4287
  return [void 0, () => {
3735
4288
  }];
3736
4289
  }
@@ -3741,10 +4294,10 @@ function defineWorkspace(config) {
3741
4294
  }
3742
4295
 
3743
4296
  // src/hooks/useModule.ts
3744
- import { useMemo as useMemo17 } from "react";
4297
+ import { useMemo as useMemo19 } from "react";
3745
4298
  function useModule(slug, config = {}, options = {}) {
3746
4299
  const { enabled = true } = options;
3747
- return useMemo17(() => ({
4300
+ return useMemo19(() => ({
3748
4301
  slug,
3749
4302
  config,
3750
4303
  isLoaded: enabled
@@ -3752,7 +4305,7 @@ function useModule(slug, config = {}, options = {}) {
3752
4305
  }
3753
4306
 
3754
4307
  // src/hooks/useModuleConfig.ts
3755
- import { useCallback as useCallback21, useMemo as useMemo18, useState as useState22 } from "react";
4308
+ import { useCallback as useCallback23, useMemo as useMemo20, useState as useState23 } from "react";
3756
4309
  var installedModulesStore = [];
3757
4310
  var configDefaultsStore = /* @__PURE__ */ new Map();
3758
4311
  function setInstalledModules(modules) {
@@ -3768,7 +4321,7 @@ function getInstalledModules() {
3768
4321
  return installedModulesStore;
3769
4322
  }
3770
4323
  function useModuleConfig(moduleSlug) {
3771
- return useMemo18(() => {
4324
+ return useMemo20(() => {
3772
4325
  const installed = getInstalledModule(moduleSlug);
3773
4326
  const defaults = configDefaultsStore.get(moduleSlug) ?? {};
3774
4327
  const persisted = persistedConfigStore.get(moduleSlug) ?? {};
@@ -3816,8 +4369,8 @@ async function updateDefinitionConfig(values, definitionId) {
3816
4369
  }
3817
4370
  function useModuleConfigWithMutation(moduleSlug) {
3818
4371
  const config = useModuleConfig(moduleSlug);
3819
- const [isSaving, setIsSaving] = useState22(false);
3820
- const updateConfig = useCallback21(async (values) => {
4372
+ const [isSaving, setIsSaving] = useState23(false);
4373
+ const updateConfig = useCallback23(async (values) => {
3821
4374
  setIsSaving(true);
3822
4375
  try {
3823
4376
  return await updateDefinitionConfig(values);
@@ -6020,7 +6573,7 @@ function describeModel(def) {
6020
6573
  }
6021
6574
 
6022
6575
  // src/hooks/usePlayer.ts
6023
- import { useCallback as useCallback22, useEffect as useEffect22, useMemo as useMemo19, useRef as useRef25, useState as useState23 } from "react";
6576
+ import { useCallback as useCallback24, useEffect as useEffect23, useMemo as useMemo21, useRef as useRef26, useState as useState24 } from "react";
6024
6577
  import {
6025
6578
  StateMachine as StateMachine2,
6026
6579
  EventBus as EventBus2,
@@ -6067,18 +6620,18 @@ function computePlayerState(sm) {
6067
6620
  };
6068
6621
  }
6069
6622
  function usePlayer(config) {
6070
- const configRef = useRef25(config);
6623
+ const configRef = useRef26(config);
6071
6624
  configRef.current = config;
6072
- useEffect22(() => {
6625
+ useEffect23(() => {
6073
6626
  if (config.debug) setPlayerDebug(true);
6074
6627
  }, [config.debug]);
6075
- const evaluator = useMemo19(() => {
6628
+ const evaluator = useMemo21(() => {
6076
6629
  return createEvaluator2({
6077
6630
  functions: config.functions ?? [],
6078
6631
  failurePolicy: WEB_FAILURE_POLICIES2.EVENT_REACTION
6079
6632
  });
6080
6633
  }, [config.definition.id]);
6081
- const engine = useMemo19(() => {
6634
+ const engine = useMemo21(() => {
6082
6635
  const actionHandlers = /* @__PURE__ */ new Map();
6083
6636
  if (config.actionHandlers) {
6084
6637
  for (const [type, handler] of Object.entries(config.actionHandlers)) {
@@ -6132,8 +6685,8 @@ function usePlayer(config) {
6132
6685
  return { sm: sm2, eventBus: eventBus2, dispatcher };
6133
6686
  }, [config.definition.id, evaluator]);
6134
6687
  const { sm, eventBus } = engine;
6135
- const [playerState, setPlayerState] = useState23(() => computePlayerState(sm));
6136
- useEffect22(() => {
6688
+ const [playerState, setPlayerState] = useState24(() => computePlayerState(sm));
6689
+ useEffect23(() => {
6137
6690
  const stateDef = sm.getCurrentStateDefinition();
6138
6691
  if (!stateDef?.on_event?.length) return;
6139
6692
  const unsubs = [];
@@ -6197,7 +6750,7 @@ function usePlayer(config) {
6197
6750
  for (const unsub of unsubs) unsub();
6198
6751
  };
6199
6752
  }, [sm, eventBus, evaluator, engine.dispatcher, playerState.currentState]);
6200
- useEffect22(() => {
6753
+ useEffect23(() => {
6201
6754
  const unsub = sm.on((event) => {
6202
6755
  if (event.type === "transition" || event.type === "state_enter") {
6203
6756
  setPlayerState(computePlayerState(sm));
@@ -6213,7 +6766,7 @@ function usePlayer(config) {
6213
6766
  });
6214
6767
  return unsub;
6215
6768
  }, [sm]);
6216
- const transition2 = useCallback22(
6769
+ const transition2 = useCallback24(
6217
6770
  async (name, data) => {
6218
6771
  playerLog({
6219
6772
  level: "info",
@@ -6240,20 +6793,20 @@ function usePlayer(config) {
6240
6793
  },
6241
6794
  [sm]
6242
6795
  );
6243
- const setField2 = useCallback22(
6796
+ const setField2 = useCallback24(
6244
6797
  (field2, value) => {
6245
6798
  sm.setField(field2, value);
6246
6799
  setPlayerState(computePlayerState(sm));
6247
6800
  },
6248
6801
  [sm]
6249
6802
  );
6250
- const setMemory = useCallback22(
6803
+ const setMemory = useCallback24(
6251
6804
  (key, value) => {
6252
6805
  sm.setMemory(key, value);
6253
6806
  },
6254
6807
  [sm]
6255
6808
  );
6256
- const publishEvent = useCallback22(
6809
+ const publishEvent = useCallback24(
6257
6810
  (topic, payload) => {
6258
6811
  playerLog({
6259
6812
  level: "debug",
@@ -6279,11 +6832,11 @@ function usePlayer(config) {
6279
6832
  }
6280
6833
 
6281
6834
  // src/hooks/useDomainSubscription.ts
6282
- import { useEffect as useEffect23, useRef as useRef26 } from "react";
6835
+ import { useEffect as useEffect24, useRef as useRef27 } from "react";
6283
6836
  function useDomainSubscription(eventBus, transport, config) {
6284
- const configRef = useRef26(config);
6837
+ const configRef = useRef27(config);
6285
6838
  configRef.current = config;
6286
- useEffect23(() => {
6839
+ useEffect24(() => {
6287
6840
  if (!transport || config.enabled === false) return;
6288
6841
  const unsub = transport.subscribe(
6289
6842
  {
@@ -6336,11 +6889,11 @@ function useDomainSubscription(eventBus, transport, config) {
6336
6889
  }
6337
6890
 
6338
6891
  // src/hooks/useExperienceState.ts
6339
- import { useCallback as useCallback23, useRef as useRef27 } from "react";
6892
+ import { useCallback as useCallback25, useRef as useRef28 } from "react";
6340
6893
  function useExperienceState(player, selector) {
6341
- const selectorRef = useRef27(selector);
6894
+ const selectorRef = useRef28(selector);
6342
6895
  selectorRef.current = selector;
6343
- const getSnapshot = useCallback23(() => {
6896
+ const getSnapshot = useCallback25(() => {
6344
6897
  return selectorRef.current({
6345
6898
  currentState: player.currentState,
6346
6899
  stateData: player.stateData,
@@ -6356,20 +6909,20 @@ function useStateField(player, field2, defaultValue) {
6356
6909
  }
6357
6910
 
6358
6911
  // src/hooks/useComputed.ts
6359
- import { useMemo as useMemo20, useRef as useRef28 } from "react";
6912
+ import { useMemo as useMemo22, useRef as useRef29 } from "react";
6360
6913
  function useComputed(_name, compute, options) {
6361
6914
  const mode = options?.mode ?? "read-time";
6362
6915
  const deps = options?.deps ?? [];
6363
- const computeRef = useRef28(compute);
6916
+ const computeRef = useRef29(compute);
6364
6917
  computeRef.current = compute;
6365
6918
  if (mode === "read-time") {
6366
- return useMemo20(() => computeRef.current(), [
6919
+ return useMemo22(() => computeRef.current(), [
6367
6920
  // We intentionally depend on deps.join to recompute when tracked fields change
6368
6921
  // The actual dependency tracking happens at the compiler level
6369
6922
  deps.join(",")
6370
6923
  ]);
6371
6924
  }
6372
- return useMemo20(() => computeRef.current(), [deps.join(",")]);
6925
+ return useMemo22(() => computeRef.current(), [deps.join(",")]);
6373
6926
  }
6374
6927
  function useComputedWithMeta(name, compute, options) {
6375
6928
  const value = useComputed(name, compute, options);
@@ -6385,10 +6938,10 @@ function useComputedWithMeta(name, compute, options) {
6385
6938
 
6386
6939
  // src/components/PlayerProvider.tsx
6387
6940
  import { createContext as createContext3, useContext as useContext3 } from "react";
6388
- import { jsx as jsx2 } from "react/jsx-runtime";
6941
+ import { jsx as jsx5 } from "react/jsx-runtime";
6389
6942
  var PlayerContext = createContext3(null);
6390
6943
  function PlayerProvider({ player, children }) {
6391
- return /* @__PURE__ */ jsx2(PlayerContext.Provider, { value: player, children });
6944
+ return /* @__PURE__ */ jsx5(PlayerContext.Provider, { value: player, children });
6392
6945
  }
6393
6946
  function usePlayerContext() {
6394
6947
  const ctx = useContext3(PlayerContext);
@@ -6402,8 +6955,8 @@ function usePlayerContextSafe() {
6402
6955
  }
6403
6956
 
6404
6957
  // src/components/ExperienceWorkflowBridge.tsx
6405
- import { useMemo as useMemo21 } from "react";
6406
- import { jsx as jsx3, jsxs } from "react/jsx-runtime";
6958
+ import { useMemo as useMemo23 } from "react";
6959
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
6407
6960
  function ExperienceWorkflowBridgeInner({
6408
6961
  definition,
6409
6962
  initialData,
@@ -6420,12 +6973,12 @@ function ExperienceWorkflowBridgeInner({
6420
6973
  actionHandlers,
6421
6974
  debug
6422
6975
  });
6423
- const viewConfig = useMemo21(() => {
6976
+ const viewConfig = useMemo23(() => {
6424
6977
  if (!definition.state_views) return void 0;
6425
6978
  return definition.state_views[player.currentState];
6426
6979
  }, [definition.state_views, player.currentState]);
6427
- return /* @__PURE__ */ jsxs(PlayerProvider, { player, children: [
6428
- /* @__PURE__ */ jsx3(
6980
+ return /* @__PURE__ */ jsxs4(PlayerProvider, { player, children: [
6981
+ /* @__PURE__ */ jsx6(
6429
6982
  DomainSubscriptionBridge,
6430
6983
  {
6431
6984
  player,
@@ -6451,12 +7004,12 @@ function DomainSubscriptionBridge({
6451
7004
  return null;
6452
7005
  }
6453
7006
  function ExperienceWorkflowBridge(props) {
6454
- return /* @__PURE__ */ jsx3(ExperienceWorkflowBridgeInner, { ...props });
7007
+ return /* @__PURE__ */ jsx6(ExperienceWorkflowBridgeInner, { ...props });
6455
7008
  }
6456
7009
 
6457
7010
  // src/components/atoms/index.tsx
6458
- import React from "react";
6459
- import { Fragment, jsx as jsx4 } from "react/jsx-runtime";
7011
+ import React3 from "react";
7012
+ import { Fragment as Fragment3, jsx as jsx7 } from "react/jsx-runtime";
6460
7013
 
6461
7014
  // src/loader/experience-workflow-loader.ts
6462
7015
  function validateExperienceWorkflow(def) {
@@ -7508,22 +8061,24 @@ export {
7508
8061
  Accordion,
7509
8062
  AnimatedBox,
7510
8063
  BUILT_IN_CONSTRAINTS,
7511
- Badge,
8064
+ Badge2 as Badge,
7512
8065
  Blueprint,
7513
8066
  BrowserPlayer,
7514
- Button,
8067
+ Button2 as Button,
7515
8068
  Canvas3D,
7516
- Card,
8069
+ Card2 as Card,
7517
8070
  Chart,
7518
- Column,
8071
+ Column2 as Column,
8072
+ ComponentTreeRenderer,
7519
8073
  DataGrid,
7520
- Divider,
7521
- Each,
8074
+ DevPlayer,
8075
+ Divider2 as Divider,
8076
+ Each2 as Each,
7522
8077
  ExperienceWorkflowBridge,
7523
- Field,
8078
+ Field2 as Field,
7524
8079
  FieldBuilder,
7525
- Grid,
7526
- Heading,
8080
+ Grid2 as Grid,
8081
+ Heading2 as Heading,
7527
8082
  Icon,
7528
8083
  Image,
7529
8084
  Link,
@@ -7539,20 +8094,20 @@ export {
7539
8094
  RoleGuard,
7540
8095
  Route,
7541
8096
  Router,
7542
- Row,
8097
+ Row2 as Row,
7543
8098
  RuntimeContext,
7544
8099
  ScrollArea,
7545
- Section,
8100
+ Section2 as Section,
7546
8101
  Select,
7547
8102
  ServerGrid,
7548
- Show,
8103
+ Show2 as Show,
7549
8104
  Slot,
7550
- Spacer,
7551
- Stack,
8105
+ Spacer2 as Spacer,
8106
+ Stack2 as Stack,
7552
8107
  StateBuilder,
7553
8108
  Tabs,
7554
- Text,
7555
- TextInput,
8109
+ Text2 as Text,
8110
+ TextInput2 as TextInput,
7556
8111
  TransitionBuilder,
7557
8112
  TypedTransitionBuilder,
7558
8113
  WorkflowProvider,
@@ -7565,6 +8120,7 @@ export {
7565
8120
  applyMixins,
7566
8121
  approval,
7567
8122
  assertModelValid,
8123
+ builtinAtoms,
7568
8124
  cedar,
7569
8125
  compose,
7570
8126
  computeVisibility,
@@ -7732,7 +8288,7 @@ export {
7732
8288
  useVisibility,
7733
8289
  useWhileIn,
7734
8290
  useWorkflow,
7735
- useState21 as useWorkflowState,
8291
+ useState22 as useWorkflowState,
7736
8292
  userAction,
7737
8293
  userChoice,
7738
8294
  validate,