@petrarca/sonnet-playground 0.1.6 → 0.3.0
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/PlayAdvancedComponents-ZYK66UII.js +8 -0
- package/dist/PlayColorPalette-IWECRZUS.js +8 -0
- package/dist/PlayCoreComponents-F2OFSQZK.js +8 -0
- package/dist/PlayDataComponents-BA3NA225.js +8 -0
- package/dist/PlayFormComponents-MZC7CNES.js +8 -0
- package/dist/PlayFormWidgets-IWJJQ5XL.js +8 -0
- package/dist/PlayForms-FOF3XE6G.js +7 -0
- package/dist/PlayGraph-RHFIDAS3.js +7 -0
- package/dist/PlayJsonEditor-SYZYEJEA.js +7 -0
- package/dist/PlayJsonEditor-SYZYEJEA.js.map +1 -0
- package/dist/PlayShellApi-3T4FZPEV.js +8 -0
- package/dist/PlayShellApi-3T4FZPEV.js.map +1 -0
- package/dist/PlayTypography-T6SMPHUB.js +8 -0
- package/dist/PlayTypography-T6SMPHUB.js.map +1 -0
- package/dist/chunk-4S2ITDB3.js +322 -0
- package/dist/chunk-4S2ITDB3.js.map +1 -0
- package/dist/chunk-4Y4JFKAK.js +240 -0
- package/dist/chunk-4Y4JFKAK.js.map +1 -0
- package/dist/{chunk-QIETZUEN.js → chunk-6DZ3TSV4.js} +66 -71
- package/dist/chunk-6DZ3TSV4.js.map +1 -0
- package/dist/{chunk-CYNK2P2Q.js → chunk-7IBZEHLI.js} +14 -13
- package/dist/chunk-7IBZEHLI.js.map +1 -0
- package/dist/chunk-C2EZ2ECG.js +40 -0
- package/dist/chunk-C2EZ2ECG.js.map +1 -0
- package/dist/{chunk-A3IK3CVW.js → chunk-DA3BIB5N.js} +24 -25
- package/dist/{chunk-A3IK3CVW.js.map → chunk-DA3BIB5N.js.map} +1 -1
- package/dist/{chunk-TZGJH7YS.js → chunk-DKLALDHR.js} +325 -331
- package/dist/chunk-DKLALDHR.js.map +1 -0
- package/dist/chunk-DZB6WFHA.js +401 -0
- package/dist/chunk-DZB6WFHA.js.map +1 -0
- package/dist/{chunk-KAT24CQQ.js → chunk-FZ3ZC7VM.js} +8 -6
- package/dist/chunk-FZ3ZC7VM.js.map +1 -0
- package/dist/chunk-MT4ILA37.js +563 -0
- package/dist/chunk-MT4ILA37.js.map +1 -0
- package/dist/chunk-QCK2M4KD.js +907 -0
- package/dist/chunk-QCK2M4KD.js.map +1 -0
- package/dist/chunk-SBKZRIJC.js +316 -0
- package/dist/chunk-SBKZRIJC.js.map +1 -0
- package/dist/index.d.ts +10 -6
- package/dist/index.js +52 -16
- package/dist/index.js.map +1 -1
- package/dist/pages/index.d.ts +26 -11
- package/dist/pages/index.js +23 -11
- package/package.json +6 -5
- package/dist/PlayColorPalette-UFMTJTUB.js +0 -8
- package/dist/PlayCoreComponents-7QCDFQLT.js +0 -7
- package/dist/PlayDataComponents-GZSRTW4F.js +0 -7
- package/dist/PlayFormComponents-RJB6WZHD.js +0 -7
- package/dist/PlayFormWidgets-OFV7TJKH.js +0 -7
- package/dist/PlayForms-24XX5DC6.js +0 -7
- package/dist/PlayJsonEditor-4L5INQPU.js +0 -7
- package/dist/PlayTypography-ID6DLFZD.js +0 -8
- package/dist/chunk-5V27QDAY.js +0 -617
- package/dist/chunk-5V27QDAY.js.map +0 -1
- package/dist/chunk-CYNK2P2Q.js.map +0 -1
- package/dist/chunk-FTN2A5YL.js +0 -20
- package/dist/chunk-FTN2A5YL.js.map +0 -1
- package/dist/chunk-GYKEPHHA.js +0 -1154
- package/dist/chunk-GYKEPHHA.js.map +0 -1
- package/dist/chunk-KAT24CQQ.js.map +0 -1
- package/dist/chunk-P7I5IDXA.js +0 -432
- package/dist/chunk-P7I5IDXA.js.map +0 -1
- package/dist/chunk-QIETZUEN.js.map +0 -1
- package/dist/chunk-TZGJH7YS.js.map +0 -1
- /package/dist/{PlayColorPalette-UFMTJTUB.js.map → PlayAdvancedComponents-ZYK66UII.js.map} +0 -0
- /package/dist/{PlayCoreComponents-7QCDFQLT.js.map → PlayColorPalette-IWECRZUS.js.map} +0 -0
- /package/dist/{PlayDataComponents-GZSRTW4F.js.map → PlayCoreComponents-F2OFSQZK.js.map} +0 -0
- /package/dist/{PlayFormComponents-RJB6WZHD.js.map → PlayDataComponents-BA3NA225.js.map} +0 -0
- /package/dist/{PlayFormWidgets-OFV7TJKH.js.map → PlayFormComponents-MZC7CNES.js.map} +0 -0
- /package/dist/{PlayForms-24XX5DC6.js.map → PlayFormWidgets-IWJJQ5XL.js.map} +0 -0
- /package/dist/{PlayJsonEditor-4L5INQPU.js.map → PlayForms-FOF3XE6G.js.map} +0 -0
- /package/dist/{PlayTypography-ID6DLFZD.js.map → PlayGraph-RHFIDAS3.js.map} +0 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PlaygroundSection
|
|
3
|
+
} from "./chunk-C2EZ2ECG.js";
|
|
4
|
+
|
|
5
|
+
// src/pages/PlayAdvancedComponents.tsx
|
|
6
|
+
import { useState } from "react";
|
|
7
|
+
import {
|
|
8
|
+
TreeView,
|
|
9
|
+
Button,
|
|
10
|
+
Separator,
|
|
11
|
+
Stepper,
|
|
12
|
+
StepperContent,
|
|
13
|
+
StepperDescription,
|
|
14
|
+
StepperIndicator,
|
|
15
|
+
StepperItem,
|
|
16
|
+
StepperList,
|
|
17
|
+
StepperNext,
|
|
18
|
+
StepperPrev,
|
|
19
|
+
StepperSeparator,
|
|
20
|
+
StepperTitle,
|
|
21
|
+
StepperTrigger
|
|
22
|
+
} from "@petrarca/sonnet-ui";
|
|
23
|
+
import { useTreeExpansion } from "@petrarca/sonnet-core/hooks";
|
|
24
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
25
|
+
function PlayAdvancedComponents() {
|
|
26
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
27
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
28
|
+
/* @__PURE__ */ jsx("h1", { children: "Advanced Components" }),
|
|
29
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Multi-step workflows and hierarchical data structures." })
|
|
30
|
+
] }),
|
|
31
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
32
|
+
/* @__PURE__ */ jsx(
|
|
33
|
+
PlaygroundSection,
|
|
34
|
+
{
|
|
35
|
+
title: "Stepper",
|
|
36
|
+
description: "Dice UI Stepper \u2014 horizontal, controlled via built-in Prev/Next or external state.",
|
|
37
|
+
variant: "card",
|
|
38
|
+
children: /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
39
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
40
|
+
/* @__PURE__ */ jsx("h4", { className: "mb-4", children: "Interactive (built-in navigation)" }),
|
|
41
|
+
/* @__PURE__ */ jsxs(Stepper, { defaultValue: "step-1", className: "max-w-lg", children: [
|
|
42
|
+
/* @__PURE__ */ jsx(StepperList, { className: "gap-2", children: ["step-1", "step-2", "step-3"].map((value, i) => /* @__PURE__ */ jsxs(StepperItem, { value, children: [
|
|
43
|
+
/* @__PURE__ */ jsxs(StepperTrigger, { children: [
|
|
44
|
+
/* @__PURE__ */ jsx(StepperIndicator, {}),
|
|
45
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col min-w-16", children: [
|
|
46
|
+
/* @__PURE__ */ jsxs(StepperTitle, { children: [
|
|
47
|
+
"Step ",
|
|
48
|
+
i + 1
|
|
49
|
+
] }),
|
|
50
|
+
/* @__PURE__ */ jsx(StepperDescription, { children: "Description" })
|
|
51
|
+
] })
|
|
52
|
+
] }),
|
|
53
|
+
/* @__PURE__ */ jsx(StepperSeparator, {})
|
|
54
|
+
] }, value)) }),
|
|
55
|
+
/* @__PURE__ */ jsx(StepperContent, { value: "step-1", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Content for step 1." }) }),
|
|
56
|
+
/* @__PURE__ */ jsx(StepperContent, { value: "step-2", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Content for step 2." }) }),
|
|
57
|
+
/* @__PURE__ */ jsx(StepperContent, { value: "step-3", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Content for step 3." }) }),
|
|
58
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between max-w-lg", children: [
|
|
59
|
+
/* @__PURE__ */ jsx(StepperPrev, { asChild: true, children: /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", children: "Back" }) }),
|
|
60
|
+
/* @__PURE__ */ jsx(StepperNext, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "sm", children: "Next" }) })
|
|
61
|
+
] })
|
|
62
|
+
] })
|
|
63
|
+
] }),
|
|
64
|
+
/* @__PURE__ */ jsx(Separator, {}),
|
|
65
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
66
|
+
/* @__PURE__ */ jsx("h4", { className: "mb-4", children: "Non-interactive (controlled)" }),
|
|
67
|
+
/* @__PURE__ */ jsx(StepperControlled, {})
|
|
68
|
+
] })
|
|
69
|
+
] })
|
|
70
|
+
}
|
|
71
|
+
),
|
|
72
|
+
/* @__PURE__ */ jsx(
|
|
73
|
+
PlaygroundSection,
|
|
74
|
+
{
|
|
75
|
+
title: "TreeView",
|
|
76
|
+
description: "Generic accessible tree component with expand/collapse, keyboard navigation (ArrowUp/Down/Left/Right, Enter/Space), and optional row selection.",
|
|
77
|
+
variant: "card",
|
|
78
|
+
children: /* @__PURE__ */ jsx(TreeViewDemo, {})
|
|
79
|
+
}
|
|
80
|
+
)
|
|
81
|
+
] })
|
|
82
|
+
] });
|
|
83
|
+
}
|
|
84
|
+
var CONTROLLED_STEPS = [
|
|
85
|
+
{ value: "account", title: "Account", description: "Your details" },
|
|
86
|
+
{ value: "profile", title: "Profile", description: "About you" },
|
|
87
|
+
{ value: "review", title: "Review", description: "Confirm" }
|
|
88
|
+
];
|
|
89
|
+
function StepperControlled() {
|
|
90
|
+
const [step, setStep] = useState("account");
|
|
91
|
+
return /* @__PURE__ */ jsxs(
|
|
92
|
+
Stepper,
|
|
93
|
+
{
|
|
94
|
+
value: step,
|
|
95
|
+
onValueChange: setStep,
|
|
96
|
+
nonInteractive: true,
|
|
97
|
+
className: "max-w-lg",
|
|
98
|
+
children: [
|
|
99
|
+
/* @__PURE__ */ jsx(StepperList, { className: "gap-2", children: CONTROLLED_STEPS.map((s) => /* @__PURE__ */ jsxs(StepperItem, { value: s.value, children: [
|
|
100
|
+
/* @__PURE__ */ jsxs(StepperTrigger, { children: [
|
|
101
|
+
/* @__PURE__ */ jsx(StepperIndicator, {}),
|
|
102
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col min-w-16", children: [
|
|
103
|
+
/* @__PURE__ */ jsx(StepperTitle, { children: s.title }),
|
|
104
|
+
/* @__PURE__ */ jsx(StepperDescription, { children: s.description })
|
|
105
|
+
] })
|
|
106
|
+
] }),
|
|
107
|
+
/* @__PURE__ */ jsx(StepperSeparator, {})
|
|
108
|
+
] }, s.value)) }),
|
|
109
|
+
CONTROLLED_STEPS.map((s) => /* @__PURE__ */ jsx(StepperContent, { value: s.value, children: /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
|
|
110
|
+
"Content for ",
|
|
111
|
+
s.title,
|
|
112
|
+
"."
|
|
113
|
+
] }) }, s.value)),
|
|
114
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between max-w-lg", children: [
|
|
115
|
+
/* @__PURE__ */ jsx(
|
|
116
|
+
Button,
|
|
117
|
+
{
|
|
118
|
+
variant: "outline",
|
|
119
|
+
size: "sm",
|
|
120
|
+
disabled: step === CONTROLLED_STEPS[0].value,
|
|
121
|
+
onClick: () => {
|
|
122
|
+
const i = CONTROLLED_STEPS.findIndex((s) => s.value === step);
|
|
123
|
+
if (i > 0) setStep(CONTROLLED_STEPS[i - 1].value);
|
|
124
|
+
},
|
|
125
|
+
children: "Back"
|
|
126
|
+
}
|
|
127
|
+
),
|
|
128
|
+
/* @__PURE__ */ jsx(
|
|
129
|
+
Button,
|
|
130
|
+
{
|
|
131
|
+
size: "sm",
|
|
132
|
+
disabled: step === CONTROLLED_STEPS[CONTROLLED_STEPS.length - 1].value,
|
|
133
|
+
onClick: () => {
|
|
134
|
+
const i = CONTROLLED_STEPS.findIndex((s) => s.value === step);
|
|
135
|
+
if (i < CONTROLLED_STEPS.length - 1)
|
|
136
|
+
setStep(CONTROLLED_STEPS[i + 1].value);
|
|
137
|
+
},
|
|
138
|
+
children: "Next"
|
|
139
|
+
}
|
|
140
|
+
)
|
|
141
|
+
] })
|
|
142
|
+
]
|
|
143
|
+
}
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
var TREE_NODES = [
|
|
147
|
+
{
|
|
148
|
+
id: "fruits",
|
|
149
|
+
data: { label: "Fruits" },
|
|
150
|
+
hasChildren: true,
|
|
151
|
+
children: [
|
|
152
|
+
{
|
|
153
|
+
id: "citrus",
|
|
154
|
+
data: { label: "Citrus" },
|
|
155
|
+
hasChildren: true,
|
|
156
|
+
children: [
|
|
157
|
+
{ id: "lemon", data: { label: "Lemon" }, hasChildren: false },
|
|
158
|
+
{ id: "orange", data: { label: "Orange" }, hasChildren: false }
|
|
159
|
+
]
|
|
160
|
+
},
|
|
161
|
+
{ id: "apple", data: { label: "Apple" }, hasChildren: false },
|
|
162
|
+
{ id: "banana", data: { label: "Banana" }, hasChildren: false }
|
|
163
|
+
]
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
id: "vegetables",
|
|
167
|
+
data: { label: "Vegetables" },
|
|
168
|
+
hasChildren: true,
|
|
169
|
+
children: [
|
|
170
|
+
{ id: "carrot", data: { label: "Carrot" }, hasChildren: false },
|
|
171
|
+
{ id: "broccoli", data: { label: "Broccoli" }, hasChildren: false }
|
|
172
|
+
]
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
id: "grains",
|
|
176
|
+
data: { label: "Grains" },
|
|
177
|
+
hasChildren: false
|
|
178
|
+
}
|
|
179
|
+
];
|
|
180
|
+
function TreeViewDemo() {
|
|
181
|
+
const { expandedIds, onExpand, onCollapse } = useTreeExpansion();
|
|
182
|
+
const [selectedIds, setSelectedIds] = useState(/* @__PURE__ */ new Set());
|
|
183
|
+
const [lastClicked, setLastClicked] = useState(null);
|
|
184
|
+
const handleSelectionChange = (id, selected) => setSelectedIds((prev) => {
|
|
185
|
+
const next = new Set(prev);
|
|
186
|
+
if (selected) next.add(id);
|
|
187
|
+
else next.delete(id);
|
|
188
|
+
return next;
|
|
189
|
+
});
|
|
190
|
+
return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-8", children: [
|
|
191
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
192
|
+
/* @__PURE__ */ jsx("h4", { className: "mb-3", children: "Default (click to activate)" }),
|
|
193
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mb-3", children: "Keyboard: ArrowUp/Down to move, ArrowRight to expand, ArrowLeft to collapse or go to parent, Enter/Space to activate." }),
|
|
194
|
+
/* @__PURE__ */ jsx(
|
|
195
|
+
TreeView,
|
|
196
|
+
{
|
|
197
|
+
nodes: TREE_NODES,
|
|
198
|
+
expandedIds,
|
|
199
|
+
onExpand,
|
|
200
|
+
onCollapse,
|
|
201
|
+
onNodeClick: (node) => setLastClicked(node.id),
|
|
202
|
+
onNodeActivate: (node) => setLastClicked(node.id),
|
|
203
|
+
renderNode: (node) => /* @__PURE__ */ jsx("span", { className: "text-sm", children: node.data.label }),
|
|
204
|
+
className: "max-w-xs"
|
|
205
|
+
}
|
|
206
|
+
),
|
|
207
|
+
lastClicked && /* @__PURE__ */ jsxs("p", { className: "mt-3 text-xs text-muted-foreground", children: [
|
|
208
|
+
"Last activated: ",
|
|
209
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono", children: lastClicked })
|
|
210
|
+
] })
|
|
211
|
+
] }),
|
|
212
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
213
|
+
/* @__PURE__ */ jsx("h4", { className: "mb-3", children: "With row selection" }),
|
|
214
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mb-3", children: "Checkboxes appear when onSelectionChange is provided. State is independent of expand/collapse." }),
|
|
215
|
+
/* @__PURE__ */ jsx(
|
|
216
|
+
TreeView,
|
|
217
|
+
{
|
|
218
|
+
nodes: TREE_NODES,
|
|
219
|
+
expandedIds,
|
|
220
|
+
onExpand,
|
|
221
|
+
onCollapse,
|
|
222
|
+
selectedIds,
|
|
223
|
+
onSelectionChange: handleSelectionChange,
|
|
224
|
+
renderNode: (node) => /* @__PURE__ */ jsx("span", { className: "text-sm", children: node.data.label }),
|
|
225
|
+
className: "max-w-xs"
|
|
226
|
+
}
|
|
227
|
+
),
|
|
228
|
+
selectedIds.size > 0 && /* @__PURE__ */ jsxs("p", { className: "mt-3 text-xs text-muted-foreground", children: [
|
|
229
|
+
"Selected:",
|
|
230
|
+
" ",
|
|
231
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono", children: [...selectedIds].join(", ") })
|
|
232
|
+
] })
|
|
233
|
+
] })
|
|
234
|
+
] });
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export {
|
|
238
|
+
PlayAdvancedComponents
|
|
239
|
+
};
|
|
240
|
+
//# sourceMappingURL=chunk-4Y4JFKAK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/pages/PlayAdvancedComponents.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport {\n TreeView,\n type TreeNode,\n Button,\n Separator,\n Stepper,\n StepperContent,\n StepperDescription,\n StepperIndicator,\n StepperItem,\n StepperList,\n StepperNext,\n StepperPrev,\n StepperSeparator,\n StepperTitle,\n StepperTrigger,\n} from \"@petrarca/sonnet-ui\";\nimport { useTreeExpansion } from \"@petrarca/sonnet-core/hooks\";\nimport { PlaygroundSection } from \"../PlaygroundSection\";\n\n/**\n * PlayAdvancedComponents — Stepper and TreeView demos.\n *\n * Split from PlayCoreComponents to keep files manageable.\n */\nexport default function PlayAdvancedComponents() {\n return (\n <div className=\"space-y-6\">\n <div>\n <h1>Advanced Components</h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n Multi-step workflows and hierarchical data structures.\n </p>\n </div>\n\n <div className=\"space-y-6\">\n {/* Stepper */}\n <PlaygroundSection\n title=\"Stepper\"\n description=\"Dice UI Stepper — horizontal, controlled via built-in Prev/Next or external state.\"\n variant=\"card\"\n >\n <div className=\"space-y-6\">\n {/* Interactive — uses built-in StepperPrev / StepperNext */}\n <div>\n <h4 className=\"mb-4\">Interactive (built-in navigation)</h4>\n <Stepper defaultValue=\"step-1\" className=\"max-w-lg\">\n <StepperList className=\"gap-2\">\n {[\"step-1\", \"step-2\", \"step-3\"].map((value, i) => (\n <StepperItem key={value} value={value}>\n <StepperTrigger>\n <StepperIndicator />\n <div className=\"flex flex-col min-w-16\">\n <StepperTitle>Step {i + 1}</StepperTitle>\n <StepperDescription>Description</StepperDescription>\n </div>\n </StepperTrigger>\n <StepperSeparator />\n </StepperItem>\n ))}\n </StepperList>\n <StepperContent value=\"step-1\">\n <p className=\"text-sm text-muted-foreground\">\n Content for step 1.\n </p>\n </StepperContent>\n <StepperContent value=\"step-2\">\n <p className=\"text-sm text-muted-foreground\">\n Content for step 2.\n </p>\n </StepperContent>\n <StepperContent value=\"step-3\">\n <p className=\"text-sm text-muted-foreground\">\n Content for step 3.\n </p>\n </StepperContent>\n <div className=\"flex justify-between max-w-lg\">\n <StepperPrev asChild>\n <Button variant=\"outline\" size=\"sm\">\n Back\n </Button>\n </StepperPrev>\n <StepperNext asChild>\n <Button size=\"sm\">Next</Button>\n </StepperNext>\n </div>\n </Stepper>\n </div>\n\n <Separator />\n\n {/* Non-interactive — controlled externally */}\n <div>\n <h4 className=\"mb-4\">Non-interactive (controlled)</h4>\n <StepperControlled />\n </div>\n </div>\n </PlaygroundSection>\n\n {/* TreeView */}\n <PlaygroundSection\n title=\"TreeView\"\n description=\"Generic accessible tree component with expand/collapse, keyboard navigation (ArrowUp/Down/Left/Right, Enter/Space), and optional row selection.\"\n variant=\"card\"\n >\n <TreeViewDemo />\n </PlaygroundSection>\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Stepper — controlled demo\n// ---------------------------------------------------------------------------\n\nconst CONTROLLED_STEPS = [\n { value: \"account\", title: \"Account\", description: \"Your details\" },\n { value: \"profile\", title: \"Profile\", description: \"About you\" },\n { value: \"review\", title: \"Review\", description: \"Confirm\" },\n];\n\nfunction StepperControlled() {\n const [step, setStep] = useState(\"account\");\n return (\n <Stepper\n value={step}\n onValueChange={setStep}\n nonInteractive\n className=\"max-w-lg\"\n >\n <StepperList className=\"gap-2\">\n {CONTROLLED_STEPS.map((s) => (\n <StepperItem key={s.value} value={s.value}>\n <StepperTrigger>\n <StepperIndicator />\n <div className=\"flex flex-col min-w-16\">\n <StepperTitle>{s.title}</StepperTitle>\n <StepperDescription>{s.description}</StepperDescription>\n </div>\n </StepperTrigger>\n <StepperSeparator />\n </StepperItem>\n ))}\n </StepperList>\n {CONTROLLED_STEPS.map((s) => (\n <StepperContent key={s.value} value={s.value}>\n <p className=\"text-sm text-muted-foreground\">\n Content for {s.title}.\n </p>\n </StepperContent>\n ))}\n <div className=\"flex justify-between max-w-lg\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={step === CONTROLLED_STEPS[0].value}\n onClick={() => {\n const i = CONTROLLED_STEPS.findIndex((s) => s.value === step);\n if (i > 0) setStep(CONTROLLED_STEPS[i - 1].value);\n }}\n >\n Back\n </Button>\n <Button\n size=\"sm\"\n disabled={\n step === CONTROLLED_STEPS[CONTROLLED_STEPS.length - 1].value\n }\n onClick={() => {\n const i = CONTROLLED_STEPS.findIndex((s) => s.value === step);\n if (i < CONTROLLED_STEPS.length - 1)\n setStep(CONTROLLED_STEPS[i + 1].value);\n }}\n >\n Next\n </Button>\n </div>\n </Stepper>\n );\n}\n\n// ---------------------------------------------------------------------------\n// TreeView demo\n// ---------------------------------------------------------------------------\n\ninterface DemoData extends Record<string, unknown> {\n label: string;\n}\n\nconst TREE_NODES: TreeNode<DemoData>[] = [\n {\n id: \"fruits\",\n data: { label: \"Fruits\" },\n hasChildren: true,\n children: [\n {\n id: \"citrus\",\n data: { label: \"Citrus\" },\n hasChildren: true,\n children: [\n { id: \"lemon\", data: { label: \"Lemon\" }, hasChildren: false },\n { id: \"orange\", data: { label: \"Orange\" }, hasChildren: false },\n ],\n },\n { id: \"apple\", data: { label: \"Apple\" }, hasChildren: false },\n { id: \"banana\", data: { label: \"Banana\" }, hasChildren: false },\n ],\n },\n {\n id: \"vegetables\",\n data: { label: \"Vegetables\" },\n hasChildren: true,\n children: [\n { id: \"carrot\", data: { label: \"Carrot\" }, hasChildren: false },\n { id: \"broccoli\", data: { label: \"Broccoli\" }, hasChildren: false },\n ],\n },\n {\n id: \"grains\",\n data: { label: \"Grains\" },\n hasChildren: false,\n },\n];\n\nfunction TreeViewDemo() {\n const { expandedIds, onExpand, onCollapse } = useTreeExpansion();\n const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());\n const [lastClicked, setLastClicked] = useState<string | null>(null);\n\n const handleSelectionChange = (id: string, selected: boolean) =>\n setSelectedIds((prev) => {\n const next = new Set(prev);\n if (selected) next.add(id);\n else next.delete(id);\n return next;\n });\n\n return (\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-8\">\n {/* Without selection */}\n <div>\n <h4 className=\"mb-3\">Default (click to activate)</h4>\n <p className=\"text-sm text-muted-foreground mb-3\">\n Keyboard: ArrowUp/Down to move, ArrowRight to expand, ArrowLeft to\n collapse or go to parent, Enter/Space to activate.\n </p>\n <TreeView<DemoData>\n nodes={TREE_NODES}\n expandedIds={expandedIds}\n onExpand={onExpand}\n onCollapse={onCollapse}\n onNodeClick={(node) => setLastClicked(node.id)}\n onNodeActivate={(node) => setLastClicked(node.id)}\n renderNode={(node) => (\n <span className=\"text-sm\">{node.data.label}</span>\n )}\n className=\"max-w-xs\"\n />\n {lastClicked && (\n <p className=\"mt-3 text-xs text-muted-foreground\">\n Last activated: <span className=\"font-mono\">{lastClicked}</span>\n </p>\n )}\n </div>\n\n {/* With row selection */}\n <div>\n <h4 className=\"mb-3\">With row selection</h4>\n <p className=\"text-sm text-muted-foreground mb-3\">\n Checkboxes appear when onSelectionChange is provided. State is\n independent of expand/collapse.\n </p>\n <TreeView<DemoData>\n nodes={TREE_NODES}\n expandedIds={expandedIds}\n onExpand={onExpand}\n onCollapse={onCollapse}\n selectedIds={selectedIds}\n onSelectionChange={handleSelectionChange}\n renderNode={(node) => (\n <span className=\"text-sm\">{node.data.label}</span>\n )}\n className=\"max-w-xs\"\n />\n {selectedIds.size > 0 && (\n <p className=\"mt-3 text-xs text-muted-foreground\">\n Selected:{\" \"}\n <span className=\"font-mono\">{[...selectedIds].join(\", \")}</span>\n </p>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -405,22 +405,19 @@ function usePlayFormsState() {
|
|
|
405
405
|
const [dataCollapsed, setDataCollapsed] = useState(false);
|
|
406
406
|
const [lastDiff, setLastDiff] = useState(null);
|
|
407
407
|
const toggleDataPanel = useCallback(() => setDataCollapsed((v) => !v), []);
|
|
408
|
-
const loadSchemaPreset = useCallback(
|
|
409
|
-
(value)
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
},
|
|
422
|
-
[setSchemaText, setActiveSchema]
|
|
423
|
-
);
|
|
408
|
+
const loadSchemaPreset = useCallback((value) => {
|
|
409
|
+
if (!value || !sampleSchemas[value]) return;
|
|
410
|
+
const text = JSON.stringify(sampleSchemas[value], null, 2);
|
|
411
|
+
setSchemaText(text);
|
|
412
|
+
setActiveSchema(sampleSchemas[value]);
|
|
413
|
+
setSchemaError("");
|
|
414
|
+
setFormData({});
|
|
415
|
+
setDataText("{}");
|
|
416
|
+
const pairedUi = value === "row_layout" ? ROW_LAYOUT_UISCHEMA : {};
|
|
417
|
+
setUiSchemaText(JSON.stringify(pairedUi, null, 2));
|
|
418
|
+
setActiveUiSchema(pairedUi);
|
|
419
|
+
setUiSchemaError("");
|
|
420
|
+
}, []);
|
|
424
421
|
const loadUiSchemaPreset = useCallback(
|
|
425
422
|
(value) => {
|
|
426
423
|
if (!value) return;
|
|
@@ -480,6 +477,28 @@ function tryParseAndLoad(text, onSuccess, onError) {
|
|
|
480
477
|
onError("Invalid JSON - cannot load to form");
|
|
481
478
|
}
|
|
482
479
|
}
|
|
480
|
+
function PanelArrowButton({
|
|
481
|
+
label,
|
|
482
|
+
onClick,
|
|
483
|
+
mirrored = false
|
|
484
|
+
}) {
|
|
485
|
+
return /* @__PURE__ */ jsx(SimpleTooltip, { label, children: /* @__PURE__ */ jsx(
|
|
486
|
+
Button,
|
|
487
|
+
{
|
|
488
|
+
variant: "default",
|
|
489
|
+
size: "icon",
|
|
490
|
+
className: "absolute -right-5 top-1/2 -translate-y-1/2 z-[100]",
|
|
491
|
+
onClick,
|
|
492
|
+
children: /* @__PURE__ */ jsx(
|
|
493
|
+
ArrowRight,
|
|
494
|
+
{
|
|
495
|
+
size: 20,
|
|
496
|
+
className: mirrored ? "scale-x-[-1]" : void 0
|
|
497
|
+
}
|
|
498
|
+
)
|
|
499
|
+
}
|
|
500
|
+
) });
|
|
501
|
+
}
|
|
483
502
|
function SchemaEditorColumn({
|
|
484
503
|
state
|
|
485
504
|
}) {
|
|
@@ -603,19 +622,10 @@ function SchemaEditorColumn({
|
|
|
603
622
|
}
|
|
604
623
|
) }),
|
|
605
624
|
/* @__PURE__ */ jsx(
|
|
606
|
-
|
|
625
|
+
PanelArrowButton,
|
|
607
626
|
{
|
|
608
627
|
label: state.activeTab === "schema" ? "Load Schema to Form" : "Load UI Schema to Form",
|
|
609
|
-
|
|
610
|
-
Button,
|
|
611
|
-
{
|
|
612
|
-
variant: "default",
|
|
613
|
-
size: "icon",
|
|
614
|
-
className: "absolute -right-5 top-1/2 -translate-y-1/2 z-[100]",
|
|
615
|
-
onClick: state.activeTab === "schema" ? handleLoadSchemaToForm : handleLoadUiSchemaToForm,
|
|
616
|
-
children: /* @__PURE__ */ jsx(ArrowRight, { size: 20 })
|
|
617
|
-
}
|
|
618
|
-
)
|
|
628
|
+
onClick: state.activeTab === "schema" ? handleLoadSchemaToForm : handleLoadUiSchemaToForm
|
|
619
629
|
}
|
|
620
630
|
)
|
|
621
631
|
]
|
|
@@ -708,7 +718,7 @@ function FormColumn({
|
|
|
708
718
|
}
|
|
709
719
|
)
|
|
710
720
|
] }),
|
|
711
|
-
state.validationErrors.length > 0 && /* @__PURE__ */ jsx("div", { style: { marginTop: "4px" }, children: state.validationErrors.map((err, idx) => /* @__PURE__ */ jsx("p", { className: "text-xs text-
|
|
721
|
+
state.validationErrors.length > 0 && /* @__PURE__ */ jsx("div", { style: { marginTop: "4px" }, children: state.validationErrors.map((err, idx) => /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive", children: err }, idx)) })
|
|
712
722
|
] }),
|
|
713
723
|
/* @__PURE__ */ jsxs(
|
|
714
724
|
"div",
|
|
@@ -743,16 +753,14 @@ function FormColumn({
|
|
|
743
753
|
]
|
|
744
754
|
}
|
|
745
755
|
) }),
|
|
746
|
-
!state.dataCollapsed && /* @__PURE__ */ jsx(
|
|
747
|
-
|
|
756
|
+
!state.dataCollapsed && /* @__PURE__ */ jsx(
|
|
757
|
+
PanelArrowButton,
|
|
748
758
|
{
|
|
749
|
-
|
|
750
|
-
size: "icon",
|
|
751
|
-
className: "absolute -right-5 top-1/2 -translate-y-1/2 z-[100]",
|
|
759
|
+
label: "Load JSON Data into Form",
|
|
752
760
|
onClick: handleLoadDataToForm,
|
|
753
|
-
|
|
761
|
+
mirrored: true
|
|
754
762
|
}
|
|
755
|
-
)
|
|
763
|
+
)
|
|
756
764
|
]
|
|
757
765
|
}
|
|
758
766
|
);
|
|
@@ -842,44 +850,31 @@ function DataColumn({
|
|
|
842
850
|
}
|
|
843
851
|
function PlayForms() {
|
|
844
852
|
const state = usePlayFormsState();
|
|
845
|
-
return /* @__PURE__ */ jsxs(
|
|
846
|
-
"div",
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
{
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
display: "flex",
|
|
868
|
-
gap: "1.5rem"
|
|
869
|
-
},
|
|
870
|
-
children: [
|
|
871
|
-
/* @__PURE__ */ jsx(SchemaEditorColumn, { state }),
|
|
872
|
-
/* @__PURE__ */ jsx(FormColumn, { state }),
|
|
873
|
-
/* @__PURE__ */ jsx(DataColumn, { state })
|
|
874
|
-
]
|
|
875
|
-
}
|
|
876
|
-
)
|
|
877
|
-
]
|
|
878
|
-
}
|
|
879
|
-
);
|
|
853
|
+
return /* @__PURE__ */ jsxs("div", { className: "w-full flex flex-col gap-3 h-[calc(100vh-8rem)]", children: [
|
|
854
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
855
|
+
/* @__PURE__ */ jsx("h1", { children: "Forms Playground" }),
|
|
856
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mb-3", children: "Test and experiment with JsonSchemaFormRenderer. Edit the JSON Schema on the left, then load it into the form." })
|
|
857
|
+
] }),
|
|
858
|
+
/* @__PURE__ */ jsxs(
|
|
859
|
+
"div",
|
|
860
|
+
{
|
|
861
|
+
style: {
|
|
862
|
+
flex: 1,
|
|
863
|
+
minHeight: 0,
|
|
864
|
+
display: "flex",
|
|
865
|
+
gap: "1.5rem"
|
|
866
|
+
},
|
|
867
|
+
children: [
|
|
868
|
+
/* @__PURE__ */ jsx(SchemaEditorColumn, { state }),
|
|
869
|
+
/* @__PURE__ */ jsx(FormColumn, { state }),
|
|
870
|
+
/* @__PURE__ */ jsx(DataColumn, { state })
|
|
871
|
+
]
|
|
872
|
+
}
|
|
873
|
+
)
|
|
874
|
+
] });
|
|
880
875
|
}
|
|
881
876
|
|
|
882
877
|
export {
|
|
883
878
|
PlayForms
|
|
884
879
|
};
|
|
885
|
-
//# sourceMappingURL=chunk-
|
|
880
|
+
//# sourceMappingURL=chunk-6DZ3TSV4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/pages/PlayForms.tsx"],"sourcesContent":["/**\n * Playground page for testing JsonSchemaFormRenderer\n * Accessible at /playground/forms\n */\n\nimport { useState, useCallback } from \"react\";\nimport type { FormDiff } from \"@petrarca/sonnet-core/schema\";\nimport {\n SimpleStack,\n SimpleGroup,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Card,\n Badge,\n SimpleTooltip,\n Button,\n} from \"@petrarca/sonnet-ui\";\nimport {\n FormSelect,\n FormCheckbox,\n JsonSchemaFormRenderer,\n type UISchema,\n} from \"@petrarca/sonnet-forms\";\nimport { JsonEditor } from \"@petrarca/sonnet-ui/json-editor\";\nimport {\n ArrowRight,\n ChevronLeft,\n ChevronRight as ChevronRightIcon,\n} from \"lucide-react\";\nimport type { JsonSchema } from \"@petrarca/sonnet-core/schema\";\n\n// Sample schemas\nconst SAMPLE_SCHEMA: JsonSchema = {\n title: \"Practitioner\",\n type: \"object\",\n properties: {\n name: { type: \"string\", title: \"Full Name\" },\n npi: { type: \"string\", title: \"NPI\" },\n specialty: {\n type: \"string\",\n title: \"Specialty\",\n enum: [\"cardiology\", \"neurology\", \"oncology\", \"radiology\", \"general\"],\n },\n notes: {\n type: \"string\",\n title: \"Notes\",\n \"x-ui-widget\": \"textarea\",\n },\n years_experience: {\n type: \"integer\",\n title: \"Years of Experience\",\n minimum: 0,\n maximum: 60,\n },\n active: { type: \"boolean\", title: \"Active\" },\n },\n required: [\"name\", \"npi\"],\n};\n\n// Nested object (1:1)\nconst NESTED_OBJECT_SCHEMA: JsonSchema = {\n title: \"Patient\",\n type: \"object\",\n properties: {\n family_name: { type: \"string\", title: \"Family Name\" },\n given_name: { type: \"string\", title: \"Given Name\" },\n birth_date: { type: \"string\", title: \"Date of Birth\", format: \"date\" },\n contact: {\n type: \"object\",\n title: \"Contact\",\n properties: {\n phone: { type: \"string\", title: \"Phone\" },\n email: { type: \"string\", title: \"Email\", format: \"email\" },\n address: { type: \"string\", title: \"Address\" },\n city: { type: \"string\", title: \"City\" },\n country: {\n type: \"string\",\n title: \"Country\",\n enum: [\"DE\", \"AT\", \"CH\", \"US\", \"GB\"],\n },\n },\n required: [\"phone\"],\n },\n },\n required: [\"family_name\", \"given_name\"],\n};\n\n// Array of objects (1:n)\nconst ARRAY_OF_OBJECTS_SCHEMA: JsonSchema = {\n title: \"Medication Request\",\n type: \"object\",\n properties: {\n patient_id: { type: \"string\", title: \"Patient ID\" },\n prescriber: { type: \"string\", title: \"Prescriber\" },\n medications: {\n type: \"array\",\n title: \"Medications\",\n \"x-ui-options\": {\n addLabel: \"Add Medication\",\n emptyMessage: \"No medications added\",\n orderable: true,\n },\n items: {\n type: \"object\",\n properties: {\n drug_name: { type: \"string\", title: \"Drug Name\" },\n dose: { type: \"string\", title: \"Dose\" },\n route: {\n type: \"string\",\n title: \"Route\",\n enum: [\"oral\", \"IV\", \"subcutaneous\", \"topical\", \"inhaled\"],\n },\n frequency: { type: \"string\", title: \"Frequency\" },\n active: { type: \"boolean\", title: \"Active\" },\n },\n required: [\"drug_name\", \"dose\"],\n },\n minItems: 1,\n maxItems: 10,\n },\n },\n required: [\"patient_id\", \"prescriber\"],\n};\n\n// $ref with $defs\nconst REF_SCHEMA: JsonSchema = {\n title: \"Care Plan\",\n type: \"object\",\n $defs: {\n period: {\n type: \"object\",\n properties: {\n start: { type: \"string\", title: \"Start Date\", format: \"date\" },\n end: { type: \"string\", title: \"End Date\", format: \"date\" },\n },\n required: [\"start\"],\n },\n },\n properties: {\n patient_id: { type: \"string\", title: \"Patient ID\" },\n title: { type: \"string\", title: \"Plan Title\" },\n validity: {\n $ref: \"#/$defs/period\",\n title: \"Validity Period\",\n },\n activities: {\n type: \"array\",\n title: \"Activities\",\n \"x-ui-options\": {\n addLabel: \"Add Activity\",\n orderable: true,\n },\n items: {\n type: \"object\",\n properties: {\n description: { type: \"string\", title: \"Description\" },\n schedule: {\n $ref: \"#/$defs/period\",\n title: \"Schedule\",\n },\n },\n required: [\"description\"],\n },\n maxItems: 5,\n },\n },\n required: [\"patient_id\", \"title\"],\n};\n\n// Horizontal array layout -- inline grid rows\nconst HORIZONTAL_ARRAY_SCHEMA: JsonSchema = {\n title: \"Observation Panel\",\n type: \"object\",\n properties: {\n subject: { type: \"string\", title: \"Subject ID\" },\n observations: {\n type: \"array\",\n title: \"Observations\",\n \"x-ui-layout\": {\n direction: \"horizontal\",\n columns: \"1fr 1fr 1fr 80px\",\n gap: 8,\n compact: true,\n },\n \"x-ui-options\": {\n addLabel: \"Add Observation\",\n emptyMessage: \"No observations recorded\",\n orderable: true,\n },\n items: {\n type: \"object\",\n properties: {\n code: {\n type: \"string\",\n title: \"LOINC Code\",\n enum: [\"8310-5\", \"8867-4\", \"9279-1\", \"29463-7\"],\n },\n value: { type: \"string\", title: \"Value\" },\n unit: {\n type: \"string\",\n title: \"Unit\",\n enum: [\"Cel\", \"/min\", \"kg\", \"mmHg\", \"%\"],\n },\n abnormal: { type: \"boolean\", title: \"Abnormal\" },\n },\n required: [\"code\", \"value\"],\n },\n minItems: 0,\n maxItems: 20,\n },\n },\n required: [\"subject\"],\n};\n\n// Horizontal array layout -- full-height rows, no compact sizing\nconst HORIZONTAL_FULL_SCHEMA: JsonSchema = {\n title: \"Allergy List\",\n type: \"object\",\n properties: {\n patient_id: { type: \"string\", title: \"Patient ID\" },\n allergies: {\n type: \"array\",\n title: \"Allergies\",\n \"x-ui-layout\": {\n direction: \"horizontal\",\n columns: \"2fr 1fr 1fr\",\n gap: 12,\n },\n \"x-ui-options\": {\n addLabel: \"Add Allergy\",\n emptyMessage: \"No allergies recorded\",\n orderable: true,\n },\n items: {\n type: \"object\",\n properties: {\n substance: { type: \"string\", title: \"Substance\" },\n severity: {\n type: \"string\",\n title: \"Severity\",\n enum: [\"mild\", \"moderate\", \"severe\"],\n },\n reaction: { type: \"string\", title: \"Reaction\" },\n },\n required: [\"substance\"],\n },\n },\n },\n required: [\"patient_id\"],\n};\n\n// Mixed: flat fields + nested object + array with variants\nconst MIXED_SCHEMA: JsonSchema = {\n title: \"Healthcare Organization\",\n type: \"object\",\n properties: {\n name: { type: \"string\", title: \"Name\" },\n type: {\n type: \"string\",\n title: \"Type\",\n enum: [\"hospital\", \"clinic\", \"lab\", \"pharmacy\"],\n },\n active: { type: \"boolean\", title: \"Active\" },\n location: {\n type: \"object\",\n title: \"Location\",\n \"x-ui-options\": { variant: \"card\" },\n properties: {\n address: { type: \"string\", title: \"Address\" },\n city: { type: \"string\", title: \"City\" },\n postal_code: { type: \"string\", title: \"Postal Code\" },\n country: {\n type: \"string\",\n title: \"Country\",\n enum: [\"DE\", \"AT\", \"CH\", \"US\", \"GB\"],\n },\n },\n required: [\"address\", \"city\"],\n },\n contacts: {\n type: \"array\",\n title: \"Contacts\",\n \"x-ui-options\": {\n addLabel: \"Add Contact\",\n orderable: true,\n emptyMessage: \"No contacts defined\",\n },\n items: {\n type: \"object\",\n properties: {\n name: { type: \"string\", title: \"Name\" },\n role: {\n type: \"string\",\n title: \"Role\",\n enum: [\"admin\", \"clinical\", \"billing\", \"technical\"],\n },\n email: { type: \"string\", title: \"Email\", format: \"email\" },\n phone: { type: \"string\", title: \"Phone\" },\n },\n required: [\"name\", \"email\"],\n },\n minItems: 1,\n },\n },\n required: [\"name\", \"type\"],\n};\n\n// Row layout: fields grouped into multi-column rows via x-ui-layout.rows\nconst ROW_LAYOUT_SCHEMA: JsonSchema = {\n title: \"Practitioner Registration\",\n type: \"object\",\n properties: {\n given_name: { type: \"string\", title: \"Given Name\" },\n family_name: { type: \"string\", title: \"Family Name\" },\n npi: { type: \"string\", title: \"NPI\" },\n specialty: {\n type: \"string\",\n title: \"Specialty\",\n enum: [\"cardiology\", \"neurology\", \"oncology\", \"radiology\", \"general\"],\n },\n email: { type: \"string\", title: \"Email\", format: \"email\" },\n phone: { type: \"string\", title: \"Phone\" },\n start_date: { type: \"string\", title: \"Start Date\" },\n end_date: { type: \"string\", title: \"End Date\" },\n notes: { type: \"string\", title: \"Notes\", \"x-ui-widget\": \"textarea\" },\n active: { type: \"boolean\", title: \"Active\" },\n },\n required: [\"given_name\", \"family_name\", \"npi\"],\n};\n\n// x-ui-layout is a top-level meta-key, not a per-field UISchema.\n// The renderer reads it via index access so the cast is safe here.\nconst ROW_LAYOUT_UISCHEMA: Record<string, UISchema> = {\n \"x-ui-layout\": {\n rows: [\n { fields: [\"given_name\", \"family_name\"], columns: \"1fr 1fr\" },\n { fields: [\"npi\", \"specialty\"], columns: \"1fr 1fr\" },\n { fields: [\"email\", \"phone\"], columns: \"1fr 1fr\" },\n { fields: [\"start_date\", \"end_date\"], columns: \"1fr 1fr\" },\n ],\n } as unknown as UISchema,\n};\n\nconst sampleSchemas: Record<string, JsonSchema> = {\n flat: SAMPLE_SCHEMA,\n nested_object: NESTED_OBJECT_SCHEMA,\n array_of_objects: ARRAY_OF_OBJECTS_SCHEMA,\n ref_defs: REF_SCHEMA,\n mixed: MIXED_SCHEMA,\n horizontal_array: HORIZONTAL_ARRAY_SCHEMA,\n horizontal_full: HORIZONTAL_FULL_SCHEMA,\n row_layout: ROW_LAYOUT_SCHEMA,\n};\n\n// Sample UI Schemas\nconst sampleUiSchemas: Record<string, string> = {\n empty: \"{}\",\n hideLabels: JSON.stringify(\n {\n \"x-ui-globalOptions\": {\n label: false,\n },\n },\n null,\n 2,\n ),\n disableAll: JSON.stringify(\n {\n \"x-ui-globalOptions\": {\n disabled: true,\n },\n },\n null,\n 2,\n ),\n readonlyAll: JSON.stringify(\n {\n \"x-ui-globalOptions\": {\n readonly: true,\n },\n },\n null,\n 2,\n ),\n fieldOverride: JSON.stringify(\n {\n \"x-ui-globalOptions\": {\n disabled: true,\n },\n name: {\n \"x-ui-options\": {\n disabled: false, // Override: enable this field\n },\n },\n },\n null,\n 2,\n ),\n customWidget: JSON.stringify(\n {\n description: {\n \"x-ui-widget\": \"textarea\",\n \"x-ui-options\": {\n rows: 5,\n },\n },\n },\n null,\n 2,\n ),\n};\n\n// -- State hook ----------------------------------------------------------\n\nfunction usePlayFormsState() {\n const [schemaText, setSchemaText] = useState(\n JSON.stringify(SAMPLE_SCHEMA, null, 2),\n );\n const [uiSchemaText, setUiSchemaText] = useState(\"{}\");\n const [activeSchema, setActiveSchema] = useState<JsonSchema | null>(\n SAMPLE_SCHEMA,\n );\n const [activeUiSchema, setActiveUiSchema] = useState<\n Record<string, UISchema>\n >({});\n const [dataText, setDataText] = useState(\"{}\");\n const [formData, setFormData] = useState<Record<string, unknown>>({});\n const [validationErrors, setValidationErrors] = useState<string[]>([]);\n const [isValid, setIsValid] = useState(true);\n const [schemaError, setSchemaError] = useState(\"\");\n const [uiSchemaError, setUiSchemaError] = useState(\"\");\n const [dataError, setDataError] = useState(\"\");\n const [activeTab, setActiveTab] = useState(\"schema\");\n const [deferStateUpdates, setDeferStateUpdates] = useState(false);\n const [dataCollapsed, setDataCollapsed] = useState(false);\n const [lastDiff, setLastDiff] = useState<FormDiff | null>(null);\n const toggleDataPanel = useCallback(() => setDataCollapsed((v) => !v), []);\n\n const loadSchemaPreset = useCallback((value: string | null) => {\n if (!value || !sampleSchemas[value]) return;\n const text = JSON.stringify(sampleSchemas[value], null, 2);\n setSchemaText(text);\n setActiveSchema(sampleSchemas[value]);\n setSchemaError(\"\");\n setFormData({});\n setDataText(\"{}\");\n const pairedUi = value === \"row_layout\" ? ROW_LAYOUT_UISCHEMA : {};\n setUiSchemaText(JSON.stringify(pairedUi, null, 2));\n setActiveUiSchema(pairedUi);\n setUiSchemaError(\"\");\n }, []);\n\n const loadUiSchemaPreset = useCallback(\n (value: string | null) => {\n if (!value) return;\n setUiSchemaText(sampleUiSchemas[value]);\n setUiSchemaError(\"\");\n },\n [setUiSchemaText],\n );\n\n return {\n schemaText,\n uiSchemaText,\n activeSchema,\n activeUiSchema,\n dataText,\n formData,\n validationErrors,\n isValid,\n schemaError,\n uiSchemaError,\n dataError,\n activeTab,\n deferStateUpdates,\n dataCollapsed,\n lastDiff,\n setSchemaText,\n setUiSchemaText,\n setActiveSchema,\n setActiveUiSchema,\n setDataText,\n setFormData,\n setValidationErrors,\n setIsValid,\n setSchemaError,\n setUiSchemaError,\n setDataError,\n setActiveTab,\n setDeferStateUpdates,\n toggleDataPanel,\n setLastDiff,\n loadSchemaPreset,\n loadUiSchemaPreset,\n };\n}\n\n// -- JSON parse helpers --------------------------------------------------\n\nfunction tryParseAndSet(\n value: string,\n setError: (e: string) => void,\n errorMessage = \"Invalid JSON\",\n) {\n try {\n JSON.parse(value);\n setError(\"\");\n } catch {\n setError(errorMessage);\n }\n}\n\nfunction tryParseAndLoad<T>(\n text: string,\n onSuccess: (parsed: T) => void,\n onError: (msg: string) => void,\n) {\n try {\n onSuccess(JSON.parse(text));\n onError(\"\");\n } catch {\n onError(\"Invalid JSON - cannot load to form\");\n }\n}\n\n// -- Shared panel arrow button -------------------------------------------\n\ninterface PanelArrowButtonProps {\n label: string;\n onClick: () => void;\n mirrored?: boolean;\n}\n\nfunction PanelArrowButton({\n label,\n onClick,\n mirrored = false,\n}: PanelArrowButtonProps) {\n return (\n <SimpleTooltip label={label}>\n <Button\n variant=\"default\"\n size=\"icon\"\n className=\"absolute -right-5 top-1/2 -translate-y-1/2 z-[100]\"\n onClick={onClick}\n >\n <ArrowRight\n size={20}\n className={mirrored ? \"scale-x-[-1]\" : undefined}\n />\n </Button>\n </SimpleTooltip>\n );\n}\n\n// -- Left column: Schema / UI Schema editors -----------------------------\n\nfunction SchemaEditorColumn({\n state,\n}: {\n state: ReturnType<typeof usePlayFormsState>;\n}) {\n const handleSchemaTextChange = (value: string) => {\n state.setSchemaText(value);\n tryParseAndSet(value, state.setSchemaError);\n };\n\n const handleUiSchemaTextChange = (value: string) => {\n state.setUiSchemaText(value);\n tryParseAndSet(value, state.setUiSchemaError);\n };\n\n const handleLoadSchemaToForm = () => {\n tryParseAndLoad<JsonSchema>(\n state.schemaText,\n (parsed) => {\n state.setActiveSchema(parsed);\n state.setFormData({});\n state.setDataText(\"{}\");\n state.setValidationErrors([]);\n state.setIsValid(true);\n state.setLastDiff(null);\n },\n state.setSchemaError,\n );\n };\n\n const handleLoadUiSchemaToForm = () => {\n tryParseAndLoad<Record<string, UISchema>>(\n state.uiSchemaText,\n state.setActiveUiSchema,\n state.setUiSchemaError,\n );\n };\n\n return (\n <div\n style={{\n flex: 1,\n position: \"relative\",\n display: \"flex\",\n flexDirection: \"column\",\n minWidth: 0,\n }}\n >\n <Card className=\"border shadow-sm p-4 flex-1 min-h-0 flex flex-col\">\n <Tabs\n value={state.activeTab}\n onValueChange={state.setActiveTab}\n style={{\n flex: 1,\n minHeight: 0,\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n <TabsList className=\"mb-1\">\n <TabsTrigger value=\"schema\">JSON Schema</TabsTrigger>\n <TabsTrigger value=\"uischema\">UI Schema</TabsTrigger>\n </TabsList>\n\n <TabsContent\n value=\"schema\"\n className=\"flex-1 min-h-0 flex flex-col mt-0\"\n >\n <FormSelect\n placeholder=\"Load example schema...\"\n options={SCHEMA_PRESET_OPTIONS}\n onChange={state.loadSchemaPreset}\n className=\"text-xs\"\n wrapperClassName=\"mb-2\"\n />\n {state.schemaError && (\n <Badge variant=\"destructive\" className=\"text-xs mb-2\">\n {state.schemaError}\n </Badge>\n )}\n <JsonEditor\n value={state.schemaText}\n editablePaths={[\"/\"]}\n onChange={handleSchemaTextChange}\n height=\"100%\"\n className=\"flex-1 min-h-0 rounded-md border overflow-hidden\"\n />\n </TabsContent>\n\n <TabsContent\n value=\"uischema\"\n className=\"flex-1 min-h-0 flex flex-col mt-0\"\n >\n <FormSelect\n placeholder=\"Load example...\"\n options={UISCHEMA_PRESET_OPTIONS}\n onChange={state.loadUiSchemaPreset}\n className=\"text-xs\"\n wrapperClassName=\"mb-2\"\n />\n {state.uiSchemaError && (\n <Badge variant=\"destructive\" className=\"text-xs mb-2\">\n {state.uiSchemaError}\n </Badge>\n )}\n <JsonEditor\n value={state.uiSchemaText}\n editablePaths={[\"/\"]}\n onChange={handleUiSchemaTextChange}\n height=\"100%\"\n className=\"flex-1 min-h-0 rounded-md border overflow-hidden\"\n />\n </TabsContent>\n </Tabs>\n </Card>\n\n <PanelArrowButton\n label={\n state.activeTab === \"schema\"\n ? \"Load Schema to Form\"\n : \"Load UI Schema to Form\"\n }\n onClick={\n state.activeTab === \"schema\"\n ? handleLoadSchemaToForm\n : handleLoadUiSchemaToForm\n }\n />\n </div>\n );\n}\n\n// Preset option arrays (static, avoids re-creation).\nconst SCHEMA_PRESET_OPTIONS = [\n { value: \"flat\", label: \"Practitioner (flat fields)\" },\n { value: \"nested_object\", label: \"Patient (nested object)\" },\n { value: \"array_of_objects\", label: \"Medication Request (array)\" },\n { value: \"ref_defs\", label: \"Care Plan ($ref / $defs)\" },\n { value: \"mixed\", label: \"Organization (mixed)\" },\n { value: \"horizontal_array\", label: \"Observations (horizontal, compact)\" },\n { value: \"horizontal_full\", label: \"Allergies (horizontal, full height)\" },\n { value: \"row_layout\", label: \"Registration (row layout)\" },\n];\n\nconst UISCHEMA_PRESET_OPTIONS = [\n { value: \"empty\", label: \"Empty (no customization)\" },\n { value: \"hideLabels\", label: \"Hide all labels\" },\n { value: \"disableAll\", label: \"Disable all fields\" },\n { value: \"readonlyAll\", label: \"Readonly all fields\" },\n { value: \"fieldOverride\", label: \"Field-level override\" },\n { value: \"customWidget\", label: \"Custom widget\" },\n];\n\n// -- Middle column: Rendered form ----------------------------------------\n\nfunction FormColumn({\n state,\n}: {\n state: ReturnType<typeof usePlayFormsState>;\n}) {\n const handleUpdate = (\n data: Record<string, unknown>,\n _changedFields: Record<string, unknown>,\n diff: FormDiff,\n ) => {\n state.setDataText(JSON.stringify(data, null, 2));\n state.setFormData(data);\n state.setLastDiff(diff);\n };\n\n const handleCancel = () => {\n state.setFormData({});\n state.setDataText(\"{}\");\n state.setValidationErrors([]);\n state.setIsValid(true);\n state.setLastDiff(null);\n };\n\n const handleValidationChange = (errors: string[], valid: boolean) => {\n state.setValidationErrors(errors);\n state.setIsValid(valid);\n };\n\n const handleLoadDataToForm = () => {\n tryParseAndLoad(state.dataText, state.setFormData, state.setDataError);\n };\n\n return (\n <div\n style={{\n flex: 1,\n position: \"relative\",\n display: \"flex\",\n flexDirection: \"column\",\n minWidth: 0,\n }}\n >\n <Card className=\"border shadow-sm p-4 flex-1 min-h-0 flex flex-col\">\n <SimpleStack\n gap=\"md\"\n style={{\n flex: 1,\n minHeight: 0,\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n <div>\n <p className=\"text-sm font-semibold mb-1\">Rendered Form</p>\n <SimpleGroup gap=\"xs\" align=\"center\" className=\"mb-1\">\n <Badge\n variant={state.isValid ? \"default\" : \"destructive\"}\n className=\"text-xs\"\n >\n {state.isValid ? \"Valid\" : \"Invalid\"}\n </Badge>\n <FormCheckbox\n label=\"Defer state updates (change on blur)\"\n checked={state.deferStateUpdates}\n onChange={(checked) => {\n if (checked !== \"indeterminate\") {\n state.setDeferStateUpdates(checked);\n }\n }}\n />\n </SimpleGroup>\n {state.validationErrors.length > 0 && (\n <div style={{ marginTop: \"4px\" }}>\n {state.validationErrors.map((err, idx) => (\n <p key={idx} className=\"text-xs text-destructive\">\n {err}\n </p>\n ))}\n </div>\n )}\n </div>\n\n <div\n style={{\n flex: 1,\n minHeight: 0,\n overflowY: \"auto\",\n paddingRight: \"4px\",\n }}\n >\n {state.activeSchema && (\n <JsonSchemaFormRenderer\n schema={state.activeSchema}\n data={state.formData}\n onUpdate={handleUpdate}\n onCancel={handleCancel}\n onValidationChange={handleValidationChange}\n showActions={true}\n deferStateUpdates={state.deferStateUpdates}\n saveLabel=\"Save Changes\"\n cancelLabel=\"Reset\"\n showExtraProperties={true}\n uiSchema={state.activeUiSchema}\n />\n )}\n {!state.activeSchema && (\n <p className=\"text-sm text-muted-foreground text-center mt-8\">\n Edit the JSON Schema on the left and click the arrow to load it\n </p>\n )}\n </div>\n </SimpleStack>\n </Card>\n\n {!state.dataCollapsed && (\n <PanelArrowButton\n label=\"Load JSON Data into Form\"\n onClick={handleLoadDataToForm}\n mirrored\n />\n )}\n </div>\n );\n}\n\n// -- Right column: JSON data + diff --------------------------------------\n\nfunction DataColumn({\n state,\n}: {\n state: ReturnType<typeof usePlayFormsState>;\n}) {\n const handleDataTextChange = (value: string) => {\n state.setDataText(value);\n tryParseAndSet(value, state.setDataError);\n };\n\n return (\n <div\n style={{\n flex: state.dataCollapsed ? \"0 0 2.25rem\" : 1,\n display: \"flex\",\n flexDirection: \"column\",\n minWidth: 0,\n gap: \"0.75rem\",\n transition: \"flex 200ms ease\",\n }}\n >\n <Card\n className=\"border shadow-sm min-h-0 flex flex-col overflow-hidden\"\n style={{ flex: \"1 1 50%\" }}\n >\n <div className=\"flex items-center justify-between px-4 py-3 shrink-0\">\n {!state.dataCollapsed && (\n <p className=\"text-sm font-semibold\">JSON Data</p>\n )}\n <SimpleTooltip\n label={\n state.dataCollapsed ? \"Expand JSON data\" : \"Collapse JSON data\"\n }\n >\n <Button\n variant=\"ghost\"\n size=\"compact\"\n onClick={state.toggleDataPanel}\n className=\"ml-auto\"\n >\n {state.dataCollapsed ? (\n <ChevronLeft className=\"h-4 w-4\" />\n ) : (\n <ChevronRightIcon className=\"h-4 w-4\" />\n )}\n </Button>\n </SimpleTooltip>\n </div>\n\n {!state.dataCollapsed && (\n <div className=\"flex-1 min-h-0 flex flex-col px-4 pb-4\">\n {state.dataError && (\n <Badge variant=\"destructive\" className=\"text-xs mb-2\">\n {state.dataError}\n </Badge>\n )}\n <JsonEditor\n value={state.dataText}\n editablePaths={[\"/\"]}\n onChange={handleDataTextChange}\n height=\"100%\"\n className=\"flex-1 min-h-0 rounded-md border overflow-hidden\"\n />\n </div>\n )}\n </Card>\n\n {!state.dataCollapsed && (\n <Card\n className=\"border shadow-sm min-h-0 flex flex-col overflow-hidden\"\n style={{ flex: \"1 1 50%\" }}\n >\n <div className=\"flex items-center justify-between px-4 py-3 shrink-0\">\n <p className=\"text-sm font-semibold\">Diff</p>\n </div>\n <div className=\"flex-1 min-h-0 flex flex-col px-4 pb-4\">\n <JsonEditor\n value={JSON.stringify(state.lastDiff ?? [], null, 2)}\n editablePaths={[\"/\"]}\n height=\"100%\"\n className=\"flex-1 min-h-0 rounded-md border overflow-hidden\"\n />\n </div>\n </Card>\n )}\n </div>\n );\n}\n\n// -- Main component ------------------------------------------------------\n\nexport default function PlayForms() {\n const state = usePlayFormsState();\n\n return (\n <div className=\"w-full flex flex-col gap-3 h-[calc(100vh-8rem)]\">\n <div>\n <h1>Forms Playground</h1>\n <p className=\"text-sm text-muted-foreground mb-3\">\n Test and experiment with JsonSchemaFormRenderer. Edit the JSON Schema\n on the left, then load it into the form.\n </p>\n </div>\n\n <div\n style={{\n flex: 1,\n minHeight: 0,\n display: \"flex\",\n gap: \"1.5rem\",\n }}\n >\n <SchemaEditorColumn state={state} />\n <FormColumn state={state} />\n <DataColumn state={state} />\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|