@fluid-app/portal-sdk 0.1.369 → 0.1.371

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 (111) hide show
  1. package/dist/{CardWidget-CqdJHxX0.cjs → CardWidget-BWwI1G0Z.cjs} +2 -2
  2. package/dist/{CardWidget-CqdJHxX0.cjs.map → CardWidget-BWwI1G0Z.cjs.map} +1 -1
  3. package/dist/{CardWidget-DCrXorb0.cjs → CardWidget-aJYbzWG9.cjs} +2 -2
  4. package/dist/{CardWidget-DdV1HDy0.mjs → CardWidget-cIc9cOG9.mjs} +2 -2
  5. package/dist/{CardWidget-DdV1HDy0.mjs.map → CardWidget-cIc9cOG9.mjs.map} +1 -1
  6. package/dist/{ContainerWidget-CYIOGpgy.cjs → ContainerWidget-C2LMzXVj.cjs} +3 -3
  7. package/dist/{ContainerWidget-CZTRim0A.cjs → ContainerWidget-bMMdFhLg.cjs} +2 -2
  8. package/dist/{ContainerWidget-CZTRim0A.cjs.map → ContainerWidget-bMMdFhLg.cjs.map} +1 -1
  9. package/dist/{ContainerWidget-BKaiiPlW.mjs → ContainerWidget-mSWihekF.mjs} +2 -2
  10. package/dist/{ContainerWidget-BKaiiPlW.mjs.map → ContainerWidget-mSWihekF.mjs.map} +1 -1
  11. package/dist/{EmbedWidget-B18Qzd0T.cjs → EmbedWidget-CFqodi8C.cjs} +2 -1
  12. package/dist/{EmbedWidget-CoZgo8aI.cjs → EmbedWidget-D1lbYjuL.cjs} +300 -3
  13. package/dist/EmbedWidget-D1lbYjuL.cjs.map +1 -0
  14. package/dist/{EmbedWidget-BJY7l4pI.mjs → EmbedWidget-p_Ybl0em.mjs} +300 -3
  15. package/dist/EmbedWidget-p_Ybl0em.mjs.map +1 -0
  16. package/dist/{FluidProvider-iStLA04k.cjs → FluidProvider-C6d1TUVm.cjs} +10 -12
  17. package/dist/{FluidProvider-iStLA04k.cjs.map → FluidProvider-C6d1TUVm.cjs.map} +1 -1
  18. package/dist/{FluidProvider-DIhrcma3.mjs → FluidProvider-C80gc4Yi.mjs} +10 -12
  19. package/dist/{FluidProvider-DIhrcma3.mjs.map → FluidProvider-C80gc4Yi.mjs.map} +1 -1
  20. package/dist/{LayoutWidget-xw1zY6cc.cjs → LayoutWidget-BqUbneWw.cjs} +2 -2
  21. package/dist/{LayoutWidget-xw1zY6cc.cjs.map → LayoutWidget-BqUbneWw.cjs.map} +1 -1
  22. package/dist/{LayoutWidget-VU6uFW3-.cjs → LayoutWidget-C1BzDeQI.cjs} +2 -2
  23. package/dist/{LayoutWidget-C0TbnxQW.mjs → LayoutWidget-D3qYKt9F.mjs} +2 -2
  24. package/dist/{LayoutWidget-C0TbnxQW.mjs.map → LayoutWidget-D3qYKt9F.mjs.map} +1 -1
  25. package/dist/{MessagingScreen-BFpKQppV.mjs → MessagingScreen-D3si8TPx.mjs} +7 -7
  26. package/dist/{MessagingScreen-BOAnKE3v.mjs → MessagingScreen-DKzYThAY.mjs} +2 -2
  27. package/dist/{MessagingScreen-BOAnKE3v.mjs.map → MessagingScreen-DKzYThAY.mjs.map} +1 -1
  28. package/dist/{MessagingScreen-y_A92ivV.cjs → MessagingScreen-DqxRu2x3.cjs} +2 -2
  29. package/dist/{MessagingScreen-y_A92ivV.cjs.map → MessagingScreen-DqxRu2x3.cjs.map} +1 -1
  30. package/dist/{MessagingScreen-C5Pejtlt.cjs → MessagingScreen-PZyO11S1.cjs} +7 -7
  31. package/dist/{OrdersScreen-BzibsZC0.mjs → OrdersScreen-B2htbQ2Q.mjs} +2 -2
  32. package/dist/{OrdersScreen-BzibsZC0.mjs.map → OrdersScreen-B2htbQ2Q.mjs.map} +1 -1
  33. package/dist/{OrdersScreen-BlYerRr0.cjs → OrdersScreen-BuX5aWgx.cjs} +7 -7
  34. package/dist/{OrdersScreen-wtdmNSwV.mjs → OrdersScreen-Cgjfo2Fs.mjs} +7 -7
  35. package/dist/{OrdersScreen-B_jWMXAy.cjs → OrdersScreen-CpNvxRDC.cjs} +2 -2
  36. package/dist/{OrdersScreen-B_jWMXAy.cjs.map → OrdersScreen-CpNvxRDC.cjs.map} +1 -1
  37. package/dist/{ProfileScreen-B5bNfcEX.mjs → ProfileScreen-BCwdwO_p.mjs} +3 -3
  38. package/dist/{ProfileScreen-B5bNfcEX.mjs.map → ProfileScreen-BCwdwO_p.mjs.map} +1 -1
  39. package/dist/{ProfileScreen-CUEECEVi.mjs → ProfileScreen-D7UA604p.mjs} +8 -8
  40. package/dist/{ProfileScreen-BF7Xp0EB.cjs → ProfileScreen-DlIXDIeu.cjs} +3 -3
  41. package/dist/{ProfileScreen-BF7Xp0EB.cjs.map → ProfileScreen-DlIXDIeu.cjs.map} +1 -1
  42. package/dist/{ProfileScreen-DXaE0EJ2.cjs → ProfileScreen-MypXufrO.cjs} +8 -8
  43. package/dist/{ScreenRenderer-CKu-Jc1I.mjs → ScreenRenderer-CcT_j-WQ.mjs} +1 -4
  44. package/dist/{ScreenRenderer-CKu-Jc1I.mjs.map → ScreenRenderer-CcT_j-WQ.mjs.map} +1 -1
  45. package/dist/{ScreenRenderer-CZTdJd2G.cjs → ScreenRenderer-Ce8MJPnR.cjs} +1 -4
  46. package/dist/{ScreenRenderer-CZTdJd2G.cjs.map → ScreenRenderer-Ce8MJPnR.cjs.map} +1 -1
  47. package/dist/{ShopScreen-CTdqSSs6.cjs → ShopScreen-29SZwMWF.cjs} +2 -2
  48. package/dist/{ShopScreen-CTdqSSs6.cjs.map → ShopScreen-29SZwMWF.cjs.map} +1 -1
  49. package/dist/{ShopScreen-CIXdmZvI.cjs → ShopScreen-BC9NDysQ.cjs} +7 -7
  50. package/dist/{ShopScreen-CUQtjHcp.mjs → ShopScreen-BKVNW6ya.mjs} +7 -7
  51. package/dist/{ShopScreen-ChWVG5vG.mjs → ShopScreen-CgN-6gic.mjs} +2 -2
  52. package/dist/{ShopScreen-ChWVG5vG.mjs.map → ShopScreen-CgN-6gic.mjs.map} +1 -1
  53. package/dist/{SubscriptionsScreen-CXrorIz1.mjs → SubscriptionsScreen-CPiLzWhm.mjs} +8 -8
  54. package/dist/{SubscriptionsScreen-C8Oc4iYz.cjs → SubscriptionsScreen-Dz6Y_1oD.cjs} +3 -3
  55. package/dist/{SubscriptionsScreen-C8Oc4iYz.cjs.map → SubscriptionsScreen-Dz6Y_1oD.cjs.map} +1 -1
  56. package/dist/{SubscriptionsScreen-CwH8QyDm.mjs → SubscriptionsScreen-M2WaVHH7.mjs} +3 -3
  57. package/dist/{SubscriptionsScreen-CwH8QyDm.mjs.map → SubscriptionsScreen-M2WaVHH7.mjs.map} +1 -1
  58. package/dist/{SubscriptionsScreen-_X2bwjKO.cjs → SubscriptionsScreen-dN42J-MR.cjs} +8 -8
  59. package/dist/{authoring-BlXhd4Sj.d.cts → authoring--rXPyZca.d.cts} +2 -2
  60. package/dist/{authoring-BlXhd4Sj.d.cts.map → authoring--rXPyZca.d.cts.map} +1 -1
  61. package/dist/{authoring-BMuHXNFy.d.mts → authoring-V0sXg_j4.d.mts} +2 -2
  62. package/dist/{authoring-BMuHXNFy.d.mts.map → authoring-V0sXg_j4.d.mts.map} +1 -1
  63. package/dist/index.cjs +23 -25
  64. package/dist/index.cjs.map +1 -1
  65. package/dist/index.d.cts +19 -8
  66. package/dist/index.d.cts.map +1 -1
  67. package/dist/index.d.mts +19 -9
  68. package/dist/index.d.mts.map +1 -1
  69. package/dist/index.mjs +23 -25
  70. package/dist/index.mjs.map +1 -1
  71. package/dist/preview/preview-entry.cjs +7 -7
  72. package/dist/preview/preview-entry.d.cts +1 -1
  73. package/dist/preview/preview-entry.d.mts +1 -1
  74. package/dist/preview/preview-entry.mjs +7 -7
  75. package/dist/{use-portal-card-add-3ds-flow-DJoxmO7y.cjs → use-portal-card-add-3ds-flow-C0YUg213.cjs} +2 -2
  76. package/dist/{use-portal-card-add-3ds-flow-DJoxmO7y.cjs.map → use-portal-card-add-3ds-flow-C0YUg213.cjs.map} +1 -1
  77. package/dist/{use-portal-card-add-3ds-flow-CKkPV6zg.mjs → use-portal-card-add-3ds-flow-DKXraYw-.mjs} +2 -2
  78. package/dist/{use-portal-card-add-3ds-flow-CKkPV6zg.mjs.map → use-portal-card-add-3ds-flow-DKXraYw-.mjs.map} +1 -1
  79. package/dist/vite/builder-preview-entry.cjs +573 -0
  80. package/dist/vite/builder-preview-entry.cjs.map +1 -0
  81. package/dist/vite/builder-preview-entry.d.cts +11 -0
  82. package/dist/vite/builder-preview-entry.d.cts.map +1 -0
  83. package/dist/vite/builder-preview-entry.d.mts +11 -0
  84. package/dist/vite/builder-preview-entry.d.mts.map +1 -0
  85. package/dist/vite/builder-preview-entry.mjs +571 -0
  86. package/dist/vite/builder-preview-entry.mjs.map +1 -0
  87. package/dist/vite/index.cjs +16 -28
  88. package/dist/vite/index.cjs.map +1 -1
  89. package/dist/vite/index.d.cts.map +1 -1
  90. package/dist/vite/index.d.mts.map +1 -1
  91. package/dist/vite/index.mjs +16 -28
  92. package/dist/vite/index.mjs.map +1 -1
  93. package/dist/{widget-package-descriptor-BnVCE5Fz.d.cts → widget-package-descriptor-ByCz_FNh.d.cts} +177 -9
  94. package/dist/widget-package-descriptor-ByCz_FNh.d.cts.map +1 -0
  95. package/dist/{widget-package-descriptor-Dt8BkF85.d.mts → widget-package-descriptor-CPIPAdUO.d.mts} +177 -9
  96. package/dist/widget-package-descriptor-CPIPAdUO.d.mts.map +1 -0
  97. package/dist/widget-package-utils-BWn56ZFw.cjs +1553 -0
  98. package/dist/widget-package-utils-BWn56ZFw.cjs.map +1 -0
  99. package/dist/widget-package-utils-BdS0B0pI.mjs +1486 -0
  100. package/dist/widget-package-utils-BdS0B0pI.mjs.map +1 -0
  101. package/dist/widgets/authoring.d.cts +1 -1
  102. package/dist/widgets/authoring.d.mts +1 -1
  103. package/package.json +17 -21
  104. package/dist/EmbedWidget-BJY7l4pI.mjs.map +0 -1
  105. package/dist/EmbedWidget-CoZgo8aI.cjs.map +0 -1
  106. package/dist/widget-package-descriptor-BnVCE5Fz.d.cts.map +0 -1
  107. package/dist/widget-package-descriptor-Dt8BkF85.d.mts.map +0 -1
  108. package/dist/widget-package-utils-BkrdrNr7.mjs +0 -582
  109. package/dist/widget-package-utils-BkrdrNr7.mjs.map +0 -1
  110. package/dist/widget-package-utils-C00ijCm-.cjs +0 -650
  111. package/dist/widget-package-utils-C00ijCm-.cjs.map +0 -1
@@ -0,0 +1,573 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ require("../chunk-9hOWP6kD.cjs");
3
+ const require_src = require("../src-DCYVQ8hc.cjs");
4
+ const require_authoring = require("../authoring-BBlBGYC5.cjs");
5
+ let react = require("react");
6
+ let react_jsx_runtime = require("react/jsx-runtime");
7
+ let lucide_react = require("lucide-react");
8
+ let react_dom_client = require("react-dom/client");
9
+ //#region ../preview/src/components/WidgetSidebar.tsx
10
+ function WidgetSidebar({ widgets, selectedIndex, onSelect }) {
11
+ const [isDark, setIsDark] = (0, react.useState)(() => document.documentElement.getAttribute("data-theme-mode") === "dark");
12
+ const toggleTheme = (0, react.useCallback)(() => {
13
+ const next = !isDark;
14
+ setIsDark(next);
15
+ document.documentElement.setAttribute("data-theme-mode", next ? "dark" : "light");
16
+ }, [isDark]);
17
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("aside", {
18
+ className: "flex flex-col overflow-y-auto border-r border-zinc-200 bg-zinc-50 p-4 dark:border-zinc-700 dark:bg-zinc-900",
19
+ children: [
20
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
21
+ className: "mb-4 flex items-center justify-between border-b border-zinc-200 pb-3 dark:border-zinc-700",
22
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
23
+ className: "text-foreground text-[15px] font-bold",
24
+ children: "Custom Widget Preview"
25
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
26
+ onClick: toggleTheme,
27
+ className: "text-muted-foreground hover:text-foreground flex cursor-pointer items-center rounded-md border-none bg-zinc-200 p-1.5 transition-colors dark:bg-zinc-700",
28
+ title: isDark ? "Switch to light mode" : "Switch to dark mode",
29
+ children: isDark ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Sun, { className: "size-3.5" }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Moon, { className: "size-3.5" })
30
+ })]
31
+ }),
32
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
33
+ className: "text-muted-foreground mb-2 text-[11px] font-semibold tracking-wider uppercase",
34
+ children: "Widgets"
35
+ }),
36
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.ScrollArea, {
37
+ className: "min-h-0 flex-1",
38
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
39
+ className: "flex flex-col gap-0.5",
40
+ children: widgets.map((w, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
41
+ onClick: () => onSelect(i),
42
+ className: `w-full cursor-pointer rounded-lg border px-3 py-2.5 text-left transition-colors ${i === selectedIndex ? "border-zinc-200 bg-white shadow-sm dark:border-zinc-600 dark:bg-zinc-800" : "border-transparent bg-transparent hover:bg-zinc-100 dark:hover:bg-zinc-800"}`,
43
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
44
+ className: "text-foreground block text-[13px] font-medium",
45
+ children: w.displayName
46
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
47
+ className: "text-muted-foreground mt-0.5 block text-[11px]",
48
+ children: w.type
49
+ })]
50
+ }, w.type))
51
+ })
52
+ })
53
+ ]
54
+ });
55
+ }
56
+ //#endregion
57
+ //#region ../preview/src/components/PreviewCanvas.tsx
58
+ /** Catches render errors in widget code so the rest of the preview stays usable. */
59
+ var WidgetErrorBoundary = class extends react.Component {
60
+ state = { error: null };
61
+ static getDerivedStateFromError(error) {
62
+ return { error };
63
+ }
64
+ componentDidCatch(error, info) {
65
+ console.error("[builder-preview] Widget render error:", error, info);
66
+ }
67
+ render() {
68
+ if (this.state.error) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
69
+ className: "rounded-lg border border-red-200 bg-red-50 p-6 dark:border-red-900 dark:bg-red-950",
70
+ children: [
71
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
72
+ className: "mb-3 flex items-center gap-2",
73
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.AlertCircle, { className: "size-4 shrink-0 text-red-600 dark:text-red-400" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
74
+ className: "text-sm font-semibold text-red-800 dark:text-red-300",
75
+ children: "Widget render error"
76
+ })]
77
+ }),
78
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
79
+ className: "mb-4 font-mono text-[13px] break-words whitespace-pre-wrap text-red-700 dark:text-red-400",
80
+ children: this.state.error.message
81
+ }),
82
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.Button, {
83
+ variant: "outline",
84
+ size: "sm",
85
+ className: "border-red-200 text-red-800 hover:bg-red-100 dark:border-red-800 dark:text-red-300 dark:hover:bg-red-900",
86
+ onClick: () => {
87
+ this.setState({ error: null });
88
+ this.props.onRetry();
89
+ },
90
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.RotateCcw, { className: "mr-1.5 size-3" }), "Retry"]
91
+ })
92
+ ]
93
+ });
94
+ return this.props.children;
95
+ }
96
+ };
97
+ function PreviewCanvas({ widgetType, displayName, description, component: Component, props, onRetry }) {
98
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("main", {
99
+ className: "flex flex-col overflow-hidden bg-zinc-100 dark:bg-zinc-800",
100
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
101
+ className: "border-b border-zinc-200 px-6 py-3.5 dark:border-zinc-700",
102
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
103
+ className: "text-foreground text-base font-semibold",
104
+ children: displayName
105
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
106
+ className: "text-muted-foreground mt-0.5 text-xs",
107
+ children: description
108
+ })]
109
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.ScrollArea, {
110
+ className: "min-h-0 flex-1",
111
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
112
+ className: "min-h-full p-6",
113
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WidgetErrorBoundary, {
114
+ onRetry: onRetry ?? (() => {}),
115
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, { ...props })
116
+ }, widgetType)
117
+ })
118
+ })]
119
+ });
120
+ }
121
+ //#endregion
122
+ //#region ../preview/src/components/ScrubNumberField.tsx
123
+ function ScrubNumberField({ label, value, min, max, step, onChange, shaded }) {
124
+ const [isDragging, setIsDragging] = (0, react.useState)(false);
125
+ const [isEditing, setIsEditing] = (0, react.useState)(false);
126
+ const dragRef = (0, react.useRef)({
127
+ x: 0,
128
+ startValue: 0
129
+ });
130
+ const containerRef = (0, react.useRef)(null);
131
+ const range = max - min;
132
+ const pct = range > 0 ? Math.min(100, Math.max(0, (value - min) / range * 100)) : 0;
133
+ const isOutOfRange = value < min || value > max;
134
+ const handlePointerDown = (0, react.useCallback)((e) => {
135
+ if (isEditing) return;
136
+ e.preventDefault();
137
+ containerRef.current?.setPointerCapture(e.pointerId);
138
+ dragRef.current = {
139
+ x: e.clientX,
140
+ startValue: value
141
+ };
142
+ setIsDragging(true);
143
+ }, [value, isEditing]);
144
+ const handlePointerMove = (0, react.useCallback)((e) => {
145
+ if (!isDragging) return;
146
+ const dx = e.clientX - dragRef.current.x;
147
+ const pxPerUnit = 300 / (range || 1);
148
+ const rawVal = dragRef.current.startValue + dx / pxPerUnit;
149
+ const rounded = Math.round(rawVal / step) * step;
150
+ onChange(Number(rounded.toFixed(step < 1 ? 2 : 0)));
151
+ }, [
152
+ isDragging,
153
+ step,
154
+ range,
155
+ onChange
156
+ ]);
157
+ const handlePointerUp = (0, react.useCallback)((e) => {
158
+ if (isDragging) {
159
+ containerRef.current?.releasePointerCapture(e.pointerId);
160
+ setIsDragging(false);
161
+ }
162
+ }, [isDragging]);
163
+ const handleValueClick = (0, react.useCallback)((e) => {
164
+ e.stopPropagation();
165
+ setIsEditing(true);
166
+ }, []);
167
+ const commitInput = (0, react.useCallback)((raw) => {
168
+ const parsed = Number(raw) || 0;
169
+ onChange(Math.min(max, Math.max(min, parsed)));
170
+ }, [
171
+ onChange,
172
+ min,
173
+ max
174
+ ]);
175
+ const handleInputBlur = (0, react.useCallback)((e) => {
176
+ setIsEditing(false);
177
+ commitInput(e.target.value);
178
+ }, [commitInput]);
179
+ const handleInputKeyDown = (0, react.useCallback)((e) => {
180
+ if (e.key === "Enter") {
181
+ setIsEditing(false);
182
+ commitInput(e.target.value);
183
+ }
184
+ if (e.key === "Escape") setIsEditing(false);
185
+ }, [commitInput]);
186
+ const rowBg = shaded ? "bg-zinc-200/80 dark:bg-zinc-700/80" : "bg-zinc-100 dark:bg-zinc-800";
187
+ const fillBg = shaded ? "bg-zinc-300 dark:bg-zinc-500" : "bg-zinc-300/80 dark:bg-zinc-600";
188
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
189
+ ref: containerRef,
190
+ className: `bp-scrub-row relative min-h-10 overflow-hidden rounded-lg ${rowBg}`,
191
+ onPointerDown: handlePointerDown,
192
+ onPointerMove: handlePointerMove,
193
+ onPointerUp: handlePointerUp,
194
+ onPointerCancel: handlePointerUp,
195
+ style: {
196
+ cursor: isEditing ? "text" : "ew-resize",
197
+ touchAction: "none"
198
+ },
199
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
200
+ className: `pointer-events-none absolute top-0 left-0 h-full transition-[width] duration-[50ms] ease-out ${fillBg}`,
201
+ style: { width: `${pct}%` }
202
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
203
+ className: "relative flex min-h-10 w-full items-center justify-between px-3.5",
204
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
205
+ className: "text-foreground relative z-[1] text-[13px] font-medium whitespace-nowrap",
206
+ children: label
207
+ }), isEditing ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
208
+ type: "number",
209
+ defaultValue: value,
210
+ onBlur: handleInputBlur,
211
+ onKeyDown: handleInputKeyDown,
212
+ className: "bp-number-input text-foreground focus:border-primary relative z-[1] w-[72px] shrink-0 rounded-md border border-zinc-300 bg-zinc-100 px-2 py-1 text-right font-mono text-[13px] outline-none dark:border-zinc-600 dark:bg-zinc-800",
213
+ autoFocus: true,
214
+ step,
215
+ onPointerDown: (e) => e.stopPropagation(),
216
+ style: { cursor: "text" }
217
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
218
+ className: `relative z-[1] min-w-12 shrink-0 cursor-text rounded px-2 py-0.5 pr-3.5 text-right font-mono text-[13px] whitespace-nowrap transition-colors hover:bg-black/5 dark:hover:bg-white/10 ${isOutOfRange ? "text-amber-500" : "text-muted-foreground"}`,
219
+ role: "button",
220
+ tabIndex: 0,
221
+ onClick: handleValueClick,
222
+ onKeyDown: (e) => {
223
+ if (e.key === "Enter" || e.key === " ") {
224
+ e.preventDefault();
225
+ e.stopPropagation();
226
+ setIsEditing(true);
227
+ }
228
+ },
229
+ onPointerDown: (e) => e.stopPropagation(),
230
+ children: step < 1 ? value.toFixed(2) : Math.round(value)
231
+ })]
232
+ })]
233
+ });
234
+ }
235
+ //#endregion
236
+ //#region ../preview/src/components/FieldRow.tsx
237
+ function FieldRow({ field, value, onChange, shaded }) {
238
+ const rowClass = `flex items-center justify-between px-3.5 min-h-10 rounded-lg relative transition-colors ${shaded ? "bg-zinc-200/80 hover:bg-zinc-200 dark:bg-zinc-700/80 dark:hover:bg-zinc-700" : "bg-zinc-100 hover:bg-zinc-200/60 dark:bg-zinc-800 dark:hover:bg-zinc-700/60"}`;
239
+ if (field.type === "boolean") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
240
+ className: `${rowClass} cursor-pointer`,
241
+ role: "button",
242
+ tabIndex: 0,
243
+ onClick: () => onChange(!value),
244
+ onKeyDown: (e) => {
245
+ if (e.key === "Enter" || e.key === " ") {
246
+ e.preventDefault();
247
+ onChange(!value);
248
+ }
249
+ },
250
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
251
+ className: "text-muted-foreground mr-3 shrink-0 text-[13px] font-medium whitespace-nowrap",
252
+ children: field.label
253
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
254
+ className: `flex h-5 w-9 shrink-0 items-center rounded-full p-0.5 transition-colors ${value ? "justify-end bg-zinc-900 dark:bg-indigo-500" : "justify-start bg-zinc-300 dark:bg-zinc-500"}`,
255
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "size-4 rounded-full bg-white shadow-sm" })
256
+ })]
257
+ });
258
+ if (field.type === "select" && field.options) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
259
+ className: rowClass,
260
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
261
+ className: "text-muted-foreground mr-3 shrink-0 text-[13px] font-medium whitespace-nowrap",
262
+ children: field.label
263
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
264
+ className: "flex items-center gap-1.5",
265
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
266
+ value: String(value ?? ""),
267
+ onChange: (e) => {
268
+ const raw = e.target.value;
269
+ onChange(typeof value === "number" ? Number(raw) : raw);
270
+ },
271
+ className: "bp-select text-foreground cursor-pointer rounded-md bg-transparent px-2 py-1 pr-5 text-[13px] font-normal transition-colors outline-none focus:bg-zinc-200 dark:focus:bg-zinc-700",
272
+ children: field.options.map((opt) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
273
+ value: opt.value,
274
+ children: opt.label
275
+ }, opt.value))
276
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
277
+ className: "text-muted-foreground pointer-events-none -ml-4 shrink-0",
278
+ width: "10",
279
+ height: "10",
280
+ viewBox: "0 0 24 24",
281
+ fill: "none",
282
+ stroke: "currentColor",
283
+ strokeWidth: "2.5",
284
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M6 9l6 6 6-6" })
285
+ })]
286
+ })]
287
+ });
288
+ if (field.type === "number") {
289
+ const num = Number(value ?? 0);
290
+ const step = field.step ?? 1;
291
+ if (field.min != null && field.max != null) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScrubNumberField, {
292
+ label: field.label,
293
+ value: num,
294
+ min: field.min,
295
+ max: field.max,
296
+ step,
297
+ onChange: (v) => onChange(v),
298
+ shaded
299
+ });
300
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
301
+ className: rowClass,
302
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
303
+ className: "text-muted-foreground mr-3 shrink-0 text-[13px] font-medium whitespace-nowrap",
304
+ children: field.label
305
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
306
+ type: "number",
307
+ value: num,
308
+ onChange: (e) => onChange(e.target.value ? Number(e.target.value) : 0),
309
+ step,
310
+ className: "bp-number-input text-foreground focus:border-primary w-[72px] shrink-0 rounded-md border border-zinc-300 bg-transparent px-2 py-1 text-right font-mono text-[13px] outline-none dark:border-zinc-600"
311
+ })]
312
+ });
313
+ }
314
+ if (field.type === "color" || field.type === "colorPicker" || field.type === "text" && /color|tint|background|fill/i.test(field.label + field.key)) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ColorField, {
315
+ field,
316
+ value,
317
+ onChange,
318
+ rowClass
319
+ });
320
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
321
+ className: rowClass,
322
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
323
+ className: "text-muted-foreground mr-3 shrink-0 text-[13px] font-medium whitespace-nowrap",
324
+ children: field.label
325
+ }), field.type === "textarea" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
326
+ value: String(value ?? ""),
327
+ onChange: (e) => onChange(e.target.value),
328
+ className: "text-foreground min-h-14 w-[55%] min-w-20 resize-y rounded-md bg-transparent px-2 py-1 text-right text-[13px] transition-colors outline-none focus:bg-zinc-200 dark:focus:bg-zinc-700"
329
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
330
+ type: "text",
331
+ value: String(value ?? ""),
332
+ onChange: (e) => onChange(e.target.value),
333
+ className: "text-foreground w-[55%] min-w-20 rounded-md bg-transparent px-2 py-1 text-right text-[13px] transition-colors outline-none focus:bg-zinc-200 dark:focus:bg-zinc-700"
334
+ })]
335
+ });
336
+ }
337
+ /**
338
+ * Color field with local state for the picker.
339
+ * The native <input type="color"> fires onChange on every pixel drag.
340
+ * We use local state for the live swatch preview and only commit to
341
+ * the parent on text input change or when the picker closes (change event
342
+ * on the hidden input fires on mouseup/close).
343
+ */
344
+ function ColorField({ field, value, onChange, rowClass }) {
345
+ const pickerRef = (0, react.useRef)(null);
346
+ const colorVal = String(value ?? "#000000");
347
+ const normalized = /^#?[0-9a-fA-F]{3,8}$/.test(colorVal) ? colorVal.startsWith("#") ? colorVal : `#${colorVal}` : "#000000";
348
+ const [localColor, setLocalColor] = (0, react.useState)(normalized);
349
+ const isDragging = (0, react.useRef)(false);
350
+ if (!isDragging.current && localColor !== normalized) setLocalColor(normalized);
351
+ const handleTextChange = (0, react.useCallback)((e) => {
352
+ onChange(e.target.value);
353
+ }, [onChange]);
354
+ const handlePickerInput = (0, react.useCallback)((e) => {
355
+ isDragging.current = true;
356
+ setLocalColor(e.target.value);
357
+ }, []);
358
+ const handlePickerChange = (0, react.useCallback)((e) => {
359
+ isDragging.current = false;
360
+ onChange(e.target.value);
361
+ }, [onChange]);
362
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
363
+ className: rowClass,
364
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
365
+ className: "text-muted-foreground mr-3 shrink-0 text-[13px] font-medium whitespace-nowrap",
366
+ children: field.label
367
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
368
+ className: "flex items-center gap-1.5",
369
+ children: [
370
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
371
+ type: "text",
372
+ value: colorVal,
373
+ onChange: handleTextChange,
374
+ className: "text-foreground w-20 rounded-md bg-transparent px-2 py-1 text-right text-[13px] transition-colors outline-none focus:bg-zinc-200 dark:focus:bg-zinc-700"
375
+ }),
376
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
377
+ className: "h-[22px] w-[22px] shrink-0 cursor-pointer rounded border-2 border-zinc-300 transition-colors hover:border-zinc-400 focus:border-zinc-400 focus:outline-none dark:border-zinc-600 dark:hover:border-zinc-500 dark:focus:border-zinc-500",
378
+ style: { background: localColor },
379
+ role: "button",
380
+ tabIndex: 0,
381
+ "aria-label": "Pick color",
382
+ onClick: () => pickerRef.current?.click(),
383
+ onKeyDown: (e) => {
384
+ if (e.key === "Enter" || e.key === " ") {
385
+ e.preventDefault();
386
+ pickerRef.current?.click();
387
+ }
388
+ }
389
+ }),
390
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
391
+ ref: pickerRef,
392
+ type: "color",
393
+ value: localColor,
394
+ onInput: handlePickerInput,
395
+ onChange: handlePickerChange,
396
+ className: "pointer-events-none absolute size-0 opacity-0"
397
+ })
398
+ ]
399
+ })]
400
+ });
401
+ }
402
+ //#endregion
403
+ //#region ../preview/src/components/CopyJsonButton.tsx
404
+ function CopyJsonButton({ widgetType, props }) {
405
+ const [copied, setCopied] = (0, react.useState)(false);
406
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
407
+ onClick: (0, react.useCallback)(() => {
408
+ const json = JSON.stringify({
409
+ type: widgetType,
410
+ props
411
+ }, null, 2);
412
+ navigator.clipboard.writeText(json).then(() => {
413
+ setCopied(true);
414
+ setTimeout(() => setCopied(false), 2e3);
415
+ }, () => {});
416
+ }, [widgetType, props]),
417
+ className: "text-muted-foreground hover:text-foreground flex cursor-pointer items-center rounded border-none bg-transparent p-1 transition-colors",
418
+ title: "Copy Current Widget JSON",
419
+ children: copied ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, { className: "size-3.5 text-green-500" }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Copy, { className: "size-3.5" })
420
+ });
421
+ }
422
+ //#endregion
423
+ //#region ../preview/src/components/PropertyPanel.tsx
424
+ function PropertyPanel({ displayName, widgetType, fields, props, onFieldChange, onReset }) {
425
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
426
+ className: "flex flex-col overflow-y-auto bg-zinc-100 p-3 dark:bg-zinc-800",
427
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("aside", {
428
+ className: "flex min-h-0 flex-1 flex-col overflow-y-auto rounded-[14px] border border-zinc-200 bg-white shadow-[0_4px_24px_rgba(0,0,0,0.06),0_1px_4px_rgba(0,0,0,0.03)] dark:border-zinc-700 dark:bg-zinc-900",
429
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
430
+ className: "flex items-center justify-between border-b border-zinc-200 px-[18px] py-4 dark:border-zinc-700",
431
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
432
+ className: "text-foreground text-[15px] font-bold",
433
+ children: displayName
434
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
435
+ className: "flex items-center gap-1",
436
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopyJsonButton, {
437
+ widgetType,
438
+ props
439
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
440
+ onClick: onReset,
441
+ className: "text-muted-foreground hover:text-foreground flex cursor-pointer items-center rounded border-none bg-transparent p-1 transition-colors",
442
+ title: "Reset",
443
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.RotateCcw, { className: "size-3.5" })
444
+ })]
445
+ })]
446
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
447
+ className: "flex flex-col gap-2.5 p-3.5",
448
+ children: fields.map((field, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FieldRow, {
449
+ field,
450
+ value: props[field.key],
451
+ onChange: (val) => onFieldChange(field.key, val),
452
+ shaded: i % 2 === 1
453
+ }, field.key))
454
+ })]
455
+ })
456
+ });
457
+ }
458
+ //#endregion
459
+ //#region ../preview/src/BuilderPreviewApp.tsx
460
+ const MemoizedSidebar = (0, react.memo)(WidgetSidebar);
461
+ const MemoizedCanvas = (0, react.memo)(PreviewCanvas);
462
+ const MemoizedPropertyPanel = (0, react.memo)(PropertyPanel);
463
+ /**
464
+ * Standalone widget preview page.
465
+ *
466
+ * Three-panel layout: widget list, live preview, property editor.
467
+ * No auth, no fluid-admin, no iframe — just `pnpm dev` and open /builder-preview.
468
+ */
469
+ function BuilderPreviewApp({ widgets }) {
470
+ const [selectedIndex, setSelectedIndex] = (0, react.useState)(0);
471
+ const selected = widgets[selectedIndex];
472
+ const [props, setProps] = (0, react.useState)(selected?.defaultProps ?? {});
473
+ const defaultPropsKey = selected ? JSON.stringify(selected.defaultProps) : "";
474
+ (0, react.useEffect)(() => {
475
+ if (selected) setProps(selected.defaultProps ?? {});
476
+ }, [selected?.type, defaultPropsKey]);
477
+ const handleSelectWidget = (0, react.useCallback)((index) => {
478
+ setSelectedIndex(index);
479
+ setProps(widgets[index]?.defaultProps ?? {});
480
+ }, [widgets]);
481
+ const handleFieldChange = (0, react.useCallback)((key, value) => {
482
+ setProps((prev) => ({
483
+ ...prev,
484
+ [key]: value
485
+ }));
486
+ }, []);
487
+ const handleReset = (0, react.useCallback)(() => {
488
+ setProps(selected?.defaultProps ?? {});
489
+ }, [selected]);
490
+ const fields = (0, react.useMemo)(() => selected?.propertySchema?.fields ?? [], [selected?.propertySchema?.fields]);
491
+ if (widgets.length === 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
492
+ className: "text-muted-foreground flex h-screen flex-col items-center justify-center gap-3",
493
+ children: [
494
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Puzzle, { className: "size-10 text-zinc-300 dark:text-zinc-600" }),
495
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
496
+ className: "text-foreground text-xl font-bold",
497
+ children: "Custom Widget Preview"
498
+ }),
499
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
500
+ className: "text-sm",
501
+ children: [
502
+ "No widgets found. Add widgets to",
503
+ " ",
504
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
505
+ className: "rounded bg-zinc-100 px-1.5 py-0.5 font-mono text-xs dark:bg-zinc-800",
506
+ children: "customWidgets"
507
+ }),
508
+ " ",
509
+ "in",
510
+ " ",
511
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
512
+ className: "rounded bg-zinc-100 px-1.5 py-0.5 font-mono text-xs dark:bg-zinc-800",
513
+ children: "src/portal.config.ts"
514
+ }),
515
+ ", or run:"
516
+ ]
517
+ }),
518
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
519
+ className: "text-foreground rounded-lg bg-zinc-100 px-4 py-2 font-mono text-sm dark:bg-zinc-800",
520
+ children: "fluid widget create my-widget"
521
+ })
522
+ ]
523
+ });
524
+ if (!selected) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: "No widget selected" });
525
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
526
+ className: "grid h-screen grid-cols-[220px_1fr_320px] overflow-hidden max-[900px]:grid-cols-1 max-[900px]:grid-rows-[auto_1fr_auto] min-[901px]:max-[1200px]:grid-cols-[180px_1fr_280px]",
527
+ children: [
528
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedSidebar, {
529
+ widgets,
530
+ selectedIndex,
531
+ onSelect: handleSelectWidget
532
+ }),
533
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedCanvas, {
534
+ widgetType: selected.type,
535
+ displayName: selected.displayName,
536
+ description: selected.description,
537
+ component: selected.component,
538
+ props,
539
+ onRetry: handleReset
540
+ }),
541
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedPropertyPanel, {
542
+ displayName: selected.displayName,
543
+ widgetType: selected.type,
544
+ fields,
545
+ props,
546
+ onFieldChange: handleFieldChange,
547
+ onReset: handleReset
548
+ })
549
+ ]
550
+ });
551
+ }
552
+ //#endregion
553
+ //#region src/vite/builder-preview-entry.tsx
554
+ function renderBuilderPreview(portalConfig) {
555
+ const sourcePackageExports = [];
556
+ const seenSourcePackageIds = /* @__PURE__ */ new Set();
557
+ for (const candidate of [
558
+ portalConfig.widgetPackage,
559
+ ...Array.isArray(portalConfig.widgetPackages) ? portalConfig.widgetPackages : [],
560
+ portalConfig.default
561
+ ]) {
562
+ if (!require_authoring.isSourceWidgetPackage(candidate) || seenSourcePackageIds.has(candidate.packageId)) continue;
563
+ seenSourcePackageIds.add(candidate.packageId);
564
+ sourcePackageExports.push(candidate);
565
+ }
566
+ const widgets = [...Array.isArray(portalConfig.customWidgets) ? portalConfig.customWidgets : [], ...require_authoring.sourceWidgetPackagesToManifests(sourcePackageExports)];
567
+ const root = document.getElementById("builder-preview-root");
568
+ if (root) (0, react_dom_client.createRoot)(root).render((0, react.createElement)(BuilderPreviewApp, { widgets }));
569
+ }
570
+ //#endregion
571
+ exports.renderBuilderPreview = renderBuilderPreview;
572
+
573
+ //# sourceMappingURL=builder-preview-entry.cjs.map