@petrarca/sonnet-playground 0.5.0 → 0.7.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.
Files changed (39) hide show
  1. package/README.md +63 -101
  2. package/dist/PlayAuth-SOEYPOOL.js +8 -0
  3. package/dist/{PlayCoreComponents-AG5D4SBS.js → PlayCoreComponents-YTEAS3GL.js} +2 -2
  4. package/dist/{PlayFormWidgets-IWJJQ5XL.js → PlayFormWidgets-6JYFRTAL.js} +2 -2
  5. package/dist/PlayForms-L532W3JL.js +7 -0
  6. package/dist/PlayGraph-M4KQSFI7.js +7 -0
  7. package/dist/PlaySchemaDesigner-S4DBB53G.js +7 -0
  8. package/dist/PlaySchemaDesigner-S4DBB53G.js.map +1 -0
  9. package/dist/{chunk-PBT6HTKY.js → chunk-2XMWOZ5O.js} +130 -6
  10. package/dist/chunk-2XMWOZ5O.js.map +1 -0
  11. package/dist/{chunk-Q6NLY2BZ.js → chunk-6WI3N7JI.js} +309 -1
  12. package/dist/chunk-6WI3N7JI.js.map +1 -0
  13. package/dist/{chunk-C2P3UQMZ.js → chunk-E5X7GVLU.js} +2 -2
  14. package/dist/chunk-E5X7GVLU.js.map +1 -0
  15. package/dist/{chunk-6DZ3TSV4.js → chunk-I2FLG6ZD.js} +102 -4
  16. package/dist/chunk-I2FLG6ZD.js.map +1 -0
  17. package/dist/chunk-RYCRENYO.js +401 -0
  18. package/dist/chunk-RYCRENYO.js.map +1 -0
  19. package/dist/{chunk-DZB6WFHA.js → chunk-UB7462QG.js} +106 -1
  20. package/dist/chunk-UB7462QG.js.map +1 -0
  21. package/dist/index.d.ts +59 -17
  22. package/dist/index.js +251 -53
  23. package/dist/index.js.map +1 -1
  24. package/dist/pages/index.d.ts +3 -1
  25. package/dist/pages/index.js +9 -5
  26. package/package.json +7 -7
  27. package/dist/PlayForms-FOF3XE6G.js +0 -7
  28. package/dist/PlayGraph-M7UE5MZC.js +0 -7
  29. package/dist/PlaySchemaDesigner-B2RVRRCH.js +0 -7
  30. package/dist/chunk-6DZ3TSV4.js.map +0 -1
  31. package/dist/chunk-C2P3UQMZ.js.map +0 -1
  32. package/dist/chunk-DZB6WFHA.js.map +0 -1
  33. package/dist/chunk-PBT6HTKY.js.map +0 -1
  34. package/dist/chunk-Q6NLY2BZ.js.map +0 -1
  35. /package/dist/{PlayCoreComponents-AG5D4SBS.js.map → PlayAuth-SOEYPOOL.js.map} +0 -0
  36. /package/dist/{PlayFormWidgets-IWJJQ5XL.js.map → PlayCoreComponents-YTEAS3GL.js.map} +0 -0
  37. /package/dist/{PlayForms-FOF3XE6G.js.map → PlayFormWidgets-6JYFRTAL.js.map} +0 -0
  38. /package/dist/{PlayGraph-M7UE5MZC.js.map → PlayForms-L532W3JL.js.map} +0 -0
  39. /package/dist/{PlaySchemaDesigner-B2RVRRCH.js.map → PlayGraph-M4KQSFI7.js.map} +0 -0
package/README.md CHANGED
@@ -1,21 +1,30 @@
1
1
  # @petrarca/sonnet-playground
2
2
 
3
- Playground framework and built-in component demos for the Petrarca Sonnet
4
- component library.
3
+ The living reference for the Petrarca Sonnet component library: a registry of
4
+ demonstration pages and a factory that turns it into a `ShellModule`. It is a
5
+ library, not a hosted site -- you mount it in your own application and get a
6
+ working component reference inside your own build
7
+ ([ADR-0005](../../docs/adr/0005-the-playground-is-the-living-documentation.md)).
5
8
 
6
- ## What's included
9
+ ## What it provides
7
10
 
8
- **Playground framework** — Registry, overview tile grid, and `createPlaygroundModule()`
9
- factory. Wire a playground into any `sonnet-shell` app with a few lines.
11
+ **A registry.** `PlaygroundRegistry` and `createPlaygroundRegistry`, which
12
+ returns one pre-populated with the built-in entries. Register your own pages
13
+ beside them, grouped under a label you choose.
10
14
 
11
- **Built-in demos** — Pre-built showcase pages for all Sonnet components:
12
- Typography, Color Palette, Core UI, Advanced Components, JSON Editor, Forms,
13
- Form Components, Form Widgets, Data Components, Graph Visualization, Shell API.
15
+ **A module factory.** `createPlaygroundModule` turns a registry into a
16
+ `ShellModule` with an overview page, generated routes and navigation, ready to
17
+ pass to `createModuleRegistry`.
14
18
 
15
- **PlaygroundSection** — Shared section wrapper (`default` and `card` variants)
16
- used by all playground pages.
19
+ **Twelve built-in pages**, each lazily loaded: Typography and Color Palette
20
+ under Design System; Core UI Components, Advanced Components and JSON Editor
21
+ under Components; Form Components, Forms Renderer and Form Widgets under Forms;
22
+ Schema Designer under Schemas; Data Components under Data; Graph Visualization
23
+ under Graph; Shell API under Shell.
17
24
 
18
- ---
25
+ **Page building blocks.** `PlaygroundSection` for consistent section chrome,
26
+ `PlaygroundOverview` for the tile grid, and the playground settings provider,
27
+ hook and panel.
19
28
 
20
29
  ## Install
21
30
 
@@ -23,120 +32,73 @@ used by all playground pages.
23
32
  pnpm add @petrarca/sonnet-playground
24
33
  ```
25
34
 
26
- Peer dependencies: `react`, `react-dom`, `@petrarca/sonnet-shell`,
27
- `@petrarca/sonnet-ui`, `@petrarca/sonnet-forms`, `@petrarca/sonnet-graph`.
35
+ That single install pulls in all six other `@petrarca/sonnet-*` packages --
36
+ `sonnet-core`, `sonnet-ui`, `sonnet-forms`, `sonnet-shell`, `sonnet-graph` and
37
+ `sonnet-schema-designer` -- as regular dependencies, because the pages import
38
+ from every one of them.
28
39
 
29
- ---
30
-
31
- ## Basic usage
32
-
33
- ```ts
34
- // src/modules/playground/index.ts
35
- import {
36
- createPlaygroundRegistry,
37
- createPlaygroundModule,
38
- } from "@petrarca/sonnet-playground";
39
-
40
- const registry = createPlaygroundRegistry();
41
-
42
- // Optionally add app-specific pages:
43
- registry.register({
44
- id: "app.my-page",
45
- title: "My Page",
46
- description: "Custom demo page.",
47
- icon: SomeIcon,
48
- color: "teal",
49
- path: "my-page",
50
- component: React.lazy(() => import("./pages/MyPage")),
51
- group: "App",
52
- order: 0,
53
- });
54
-
55
- export default createPlaygroundModule(registry);
56
- ```
57
-
58
- ```ts
59
- // src/modules/registry.ts
60
- import { createModuleRegistry } from "@petrarca/sonnet-shell";
61
- import home from "./home";
62
- import playground from "./playground";
63
-
64
- export const registry = createModuleRegistry([
65
- home,
66
- playground, // pinBottom: true is set automatically by createPlaygroundModule
67
- ]);
68
- ```
69
-
70
- `createPlaygroundModule` returns a `ShellModule` — pass it directly to
71
- `createModuleRegistry` alongside your app's own modules.
72
-
73
- ---
40
+ | Peer | Range | Needed for |
41
+ |---|---|---|
42
+ | `react`, `react-dom` | `>=19` | Everything |
43
+ | `react-router-dom` | `>=7` | The generated routes and the layout outlet |
44
+ | `tailwindcss` | `>=3` | Every page's styling |
74
45
 
75
- ## Adding app-specific pages
46
+ Those dependencies carry further peers of their own, and some that are only
47
+ optional down there are required here -- the graph page needs every renderer
48
+ peer, and the JSON editor page needs CodeMirror. Getting that wrong shows up as
49
+ one page throwing rather than as an install error. See
50
+ [getting started](docs/usage/getting-started.md).
76
51
 
77
- Register your own pages alongside the built-in demos by calling
78
- `registry.register()` before passing the registry to `createPlaygroundModule`.
79
- Pages appear in the overview tile grid grouped under your chosen `group` label.
52
+ ## Usage
80
53
 
81
54
  ```ts
82
55
  // src/modules/playground/index.ts
83
56
  import { lazy } from "react";
84
- import { Search } from "lucide-react";
57
+ import { Boxes } from "lucide-react";
85
58
  import {
86
- createPlaygroundRegistry,
87
59
  createPlaygroundModule,
60
+ createPlaygroundRegistry,
88
61
  } from "@petrarca/sonnet-playground";
89
62
 
90
63
  const registry = createPlaygroundRegistry();
91
64
 
92
- // Register app-specific pages
93
65
  registry.register({
94
- id: "app.my-widget",
95
- title: "My Widget",
96
- description: "Interactive demo of MyWidget with live configuration.",
97
- icon: Search,
66
+ id: "app.widgets",
67
+ title: "Widgets",
68
+ description: "Interactive demo of the Widget components.",
69
+ icon: Boxes,
98
70
  color: "teal",
99
- path: "my-widget",
100
- component: lazy(() => import("./pages/PlayMyWidget")),
101
- group: "App Components", // appears as a group heading in the overview
71
+ path: "widgets",
72
+ component: lazy(() => import("./pages/PlayWidgets")),
73
+ group: "App Components",
102
74
  order: 0,
103
75
  });
104
76
 
105
77
  export default createPlaygroundModule(registry);
106
78
  ```
107
79
 
108
- Pages are lazy-loaded automatically — wrap the component in `React.lazy()`
109
- as shown above. The framework handles the `Suspense` boundary.
80
+ `createPlaygroundModule` returns a `ShellModule`, so it goes into
81
+ `createModuleRegistry` alongside your own modules. Its options are `icon`,
82
+ `label`, `basePath`, `overviewTitle`, `overviewSubtitle` and `grouped`; the
83
+ defaults are `FlaskConical`, `"Playground"`, `"/playground"`,
84
+ `"Developer Playground"`, `"Experiment with components, test features, and
85
+ explore capabilities."` and `true`.
110
86
 
111
- `group` is optional. Pages without a group appear under the default group in
112
- the overview. Pages with the same `group` string are grouped together.
87
+ Individual built-in pages are available from
88
+ `@petrarca/sonnet-playground/pages` when you want one on a route of your own.
113
89
 
114
- ---
115
-
116
- ## Pages subpath
117
-
118
- Individual built-in pages are available at `@petrarca/sonnet-playground/pages`
119
- for consumers who want to cherry-pick or re-export them:
120
-
121
- ```tsx
122
- import { PlayTypography, PlayColorPalette } from "@petrarca/sonnet-playground/pages";
123
- ```
124
-
125
- ---
126
-
127
- ## createPlaygroundModule options
128
-
129
- | Option | Type | Default |
130
- |---|---|---|
131
- | `icon` | `LucideIcon` | `FlaskConical` |
132
- | `label` | `string` | `"Playground"` |
133
- | `basePath` | `string` | `"/playground"` |
134
- | `overviewTitle` | `string` | `"Developer Playground"` |
135
- | `overviewSubtitle` | `string` | `""` |
136
- | `grouped` | `boolean` | `true` |
90
+ ## Documentation
137
91
 
138
- ---
92
+ - [Usage guides](docs/usage/index.md) -- getting started,
93
+ [adding pages](docs/usage/adding-pages.md) and
94
+ [embedding](docs/usage/embedding.md).
95
+ - [Design docs](docs/design/index.md) -- the registry model and the page
96
+ contract.
97
+ - [sonnet-shell: getting started](../sonnet-shell/docs/usage/getting-started.md)
98
+ -- the application frame this module plugs into.
99
+ - [Workspace documentation](../../docs/README.md) -- how the packages layer and
100
+ the architecture decision records.
139
101
 
140
102
  ## License
141
103
 
142
- See [LICENSE.md](../../LICENSE.md).
104
+ Apache 2.0. See [LICENSE.md](../../LICENSE.md).
@@ -0,0 +1,8 @@
1
+ import {
2
+ PlayAuth
3
+ } from "./chunk-RYCRENYO.js";
4
+ import "./chunk-C2EZ2ECG.js";
5
+ export {
6
+ PlayAuth as default
7
+ };
8
+ //# sourceMappingURL=PlayAuth-SOEYPOOL.js.map
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  PlayCoreComponents
3
- } from "./chunk-Q6NLY2BZ.js";
3
+ } from "./chunk-6WI3N7JI.js";
4
4
  import "./chunk-C2EZ2ECG.js";
5
5
  export {
6
6
  PlayCoreComponents as default
7
7
  };
8
- //# sourceMappingURL=PlayCoreComponents-AG5D4SBS.js.map
8
+ //# sourceMappingURL=PlayCoreComponents-YTEAS3GL.js.map
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  PlayFormWidgets
3
- } from "./chunk-DZB6WFHA.js";
3
+ } from "./chunk-UB7462QG.js";
4
4
  import "./chunk-C2EZ2ECG.js";
5
5
  export {
6
6
  PlayFormWidgets as default
7
7
  };
8
- //# sourceMappingURL=PlayFormWidgets-IWJJQ5XL.js.map
8
+ //# sourceMappingURL=PlayFormWidgets-6JYFRTAL.js.map
@@ -0,0 +1,7 @@
1
+ import {
2
+ PlayForms
3
+ } from "./chunk-I2FLG6ZD.js";
4
+ export {
5
+ PlayForms as default
6
+ };
7
+ //# sourceMappingURL=PlayForms-L532W3JL.js.map
@@ -0,0 +1,7 @@
1
+ import {
2
+ PlayGraph
3
+ } from "./chunk-E5X7GVLU.js";
4
+ export {
5
+ PlayGraph as default
6
+ };
7
+ //# sourceMappingURL=PlayGraph-M4KQSFI7.js.map
@@ -0,0 +1,7 @@
1
+ import {
2
+ PlaySchemaDesigner
3
+ } from "./chunk-2XMWOZ5O.js";
4
+ export {
5
+ PlaySchemaDesigner as default
6
+ };
7
+ //# sourceMappingURL=PlaySchemaDesigner-S4DBB53G.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -86,6 +86,131 @@ var AUDIT_SCHEMA = {
86
86
  }
87
87
  }
88
88
  };
89
+ var LOGIC_SCHEMA = {
90
+ title: "Checkout",
91
+ type: "object",
92
+ // A reusable definition referenced by $ref (shows read-only expansion).
93
+ $defs: {
94
+ Address: {
95
+ type: "object",
96
+ properties: {
97
+ street: { type: "string", title: "Street" },
98
+ city: { type: "string", title: "City" },
99
+ zip: { type: "string", title: "ZIP" }
100
+ }
101
+ }
102
+ },
103
+ "x-ui-order": [
104
+ "schema_version",
105
+ "amount",
106
+ "requires_approval",
107
+ "currency",
108
+ "expedited",
109
+ "delivery_window",
110
+ "gift_wrap",
111
+ "gift_message",
112
+ "shipping_address",
113
+ "note",
114
+ "payment"
115
+ ],
116
+ properties: {
117
+ // A $ref to the shared Address definition (read-only in the tree).
118
+ shipping_address: { $ref: "#/$defs/Address", title: "Shipping address" },
119
+ // A fixed value carried by every document (const authoring).
120
+ schema_version: {
121
+ type: "string",
122
+ title: "Schema version",
123
+ const: "checkout/v1"
124
+ },
125
+ amount: { type: "number", title: "Amount", minimum: 0 },
126
+ currency: {
127
+ type: "string",
128
+ title: "Currency",
129
+ enum: ["EUR", "USD", "GBP"]
130
+ },
131
+ expedited: { type: "boolean", title: "Expedited" },
132
+ gift_wrap: { type: "boolean", title: "Gift wrap" },
133
+ // Declarative visibility rule (x-ui-rule): declared at its own position,
134
+ // shown only when gift_wrap is checked. Contrast with the if/then/else
135
+ // fields above, which are structurally added by their conditionals.
136
+ gift_message: {
137
+ type: "string",
138
+ title: "Gift message",
139
+ "x-ui-rule": {
140
+ effect: "show",
141
+ condition: { scope: "/gift_wrap", schema: { const: true } }
142
+ }
143
+ },
144
+ // Nullable optional (anyOf [T, null]) -- the renderer unwraps to T.
145
+ note: {
146
+ title: "Note (optional)",
147
+ anyOf: [{ type: "string" }, { type: "null" }]
148
+ },
149
+ // A discriminated union (oneOf): the payment method.
150
+ payment: {
151
+ type: "object",
152
+ title: "Payment method",
153
+ discriminator: { propertyName: "kind" },
154
+ oneOf: [
155
+ {
156
+ title: "Card",
157
+ properties: {
158
+ kind: { const: "card" },
159
+ card_number: { type: "string", title: "Card number" },
160
+ cvc: { type: "string", title: "CVC" }
161
+ }
162
+ },
163
+ {
164
+ title: "Bank transfer",
165
+ properties: {
166
+ kind: { const: "bank" },
167
+ iban: { type: "string", title: "IBAN" }
168
+ }
169
+ },
170
+ {
171
+ title: "Cash",
172
+ properties: { kind: { const: "cash" } }
173
+ }
174
+ ]
175
+ }
176
+ },
177
+ required: ["amount", "currency"],
178
+ // Conditionals (if/then/else) authored as allOf members.
179
+ allOf: [
180
+ {
181
+ // Large amounts require an approval reference.
182
+ if: {
183
+ properties: { amount: { exclusiveMinimum: 1e3 } },
184
+ required: ["amount"]
185
+ },
186
+ then: {
187
+ properties: {
188
+ requires_approval: {
189
+ type: "string",
190
+ title: "Approval reference"
191
+ }
192
+ },
193
+ required: ["requires_approval"]
194
+ }
195
+ },
196
+ {
197
+ // Expedited orders ask for a delivery window; otherwise none.
198
+ if: {
199
+ properties: { expedited: { const: true } },
200
+ required: ["expedited"]
201
+ },
202
+ then: {
203
+ properties: {
204
+ delivery_window: {
205
+ type: "string",
206
+ title: "Delivery window",
207
+ enum: ["morning", "afternoon", "evening"]
208
+ }
209
+ }
210
+ }
211
+ }
212
+ ]
213
+ };
89
214
  var AUDIT_EDITABLE_PATHS = [
90
215
  "/properties/metadata/properties",
91
216
  "/properties/actor/properties/metadata/properties",
@@ -120,11 +245,10 @@ var PROFILES = {
120
245
  schema: SAMPLE_SCHEMA,
121
246
  capabilities: { mode: "data", previews: [] }
122
247
  },
123
- readonly: {
124
- label: "Read-only",
125
- description: "Fully locked -- view only, no edit affordances.",
126
- schema: SAMPLE_SCHEMA,
127
- readOnly: true,
248
+ logic: {
249
+ label: "Logic (variants + conditionals)",
250
+ description: "Shows every logic construct: a oneOf variant, if/then/else conditionals, a const field, and a nullable optional.",
251
+ schema: LOGIC_SCHEMA,
128
252
  capabilities: { previews: ["form", "table", "json", "capabilities"] }
129
253
  }
130
254
  };
@@ -188,4 +312,4 @@ function PlaySchemaDesigner() {
188
312
  export {
189
313
  PlaySchemaDesigner
190
314
  };
191
- //# sourceMappingURL=chunk-PBT6HTKY.js.map
315
+ //# sourceMappingURL=chunk-2XMWOZ5O.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pages/PlaySchemaDesigner.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport {\n SchemaDesigner,\n type SchemaDesignerCapabilities,\n} from \"@petrarca/sonnet-schema-designer\";\nimport { FormSelect } from \"@petrarca/sonnet-forms\";\nimport type { JsonSchema, UISchema } from \"@petrarca/sonnet-core/schema\";\n\nconst SAMPLE_SCHEMA: JsonSchema = {\n title: \"Patient\",\n type: \"object\",\n properties: {\n first_name: { type: \"string\", title: \"First name\", minLength: 1 },\n last_name: { type: \"string\", title: \"Last name\", minLength: 1 },\n date_of_birth: { type: \"string\", format: \"date\", title: \"Date of birth\" },\n gender: {\n type: \"string\",\n title: \"Gender\",\n enum: [\"male\", \"female\", \"other\", \"unknown\"],\n },\n active: { type: \"boolean\", title: \"Active\" },\n contact: {\n type: \"object\",\n title: \"Contact\",\n properties: {\n email: { type: \"string\", format: \"email\", title: \"Email\" },\n phone: { type: \"string\", title: \"Phone\" },\n },\n required: [\"email\"],\n },\n addresses: {\n type: \"array\",\n title: \"Addresses\",\n minItems: 1,\n maxItems: 3,\n items: {\n type: \"object\",\n properties: {\n street: { type: \"string\", title: \"Street\" },\n city: { type: \"string\", title: \"City\" },\n zip: { type: \"string\", title: \"ZIP\" },\n country: { type: \"string\", title: \"Country\" },\n },\n required: [\"street\", \"city\"],\n },\n },\n },\n required: [\"first_name\", \"last_name\"],\n};\n\n// An audit-event-like schema: a fixed envelope (actor, targets) with three\n// extensible metadata containers. Used to demo scoped editing.\nconst AUDIT_SCHEMA: JsonSchema = {\n title: \"AuditEvent\",\n type: \"object\",\n properties: {\n actor: {\n type: \"object\",\n title: \"Actor\",\n properties: {\n type: { type: \"string\", title: \"Type\" },\n id: { type: \"string\", title: \"ID\" },\n metadata: {\n type: \"object\",\n title: \"Actor metadata\",\n properties: { role: { type: \"string\", title: \"Role\" } },\n },\n },\n },\n targets: {\n type: \"array\",\n title: \"Targets\",\n items: {\n type: \"object\",\n properties: {\n type: { type: \"string\", title: \"Type\" },\n id: { type: \"string\", title: \"ID\" },\n metadata: {\n type: \"object\",\n title: \"Target metadata\",\n properties: { ward: { type: \"string\", title: \"Ward\" } },\n },\n },\n },\n },\n metadata: {\n type: \"object\",\n title: \"Metadata\",\n properties: { reason: { type: \"string\", title: \"Reason\" } },\n },\n },\n};\n\n// A schema exercising every logic construct the designer can author: a oneOf\n// discriminated variant (payment method), if/then/else conditionals (authored\n// as allOf members), a const-tagged field, and a nullable anyOf optional field.\n// x-ui-order places each conditional field right after the property it depends\n// on (see docs/design/logic-authoring.md in the schema-designer package,\n// ordering note).\nconst LOGIC_SCHEMA: JsonSchema = {\n title: \"Checkout\",\n type: \"object\",\n // A reusable definition referenced by $ref (shows read-only expansion).\n $defs: {\n Address: {\n type: \"object\",\n properties: {\n street: { type: \"string\", title: \"Street\" },\n city: { type: \"string\", title: \"City\" },\n zip: { type: \"string\", title: \"ZIP\" },\n },\n },\n },\n \"x-ui-order\": [\n \"schema_version\",\n \"amount\",\n \"requires_approval\",\n \"currency\",\n \"expedited\",\n \"delivery_window\",\n \"gift_wrap\",\n \"gift_message\",\n \"shipping_address\",\n \"note\",\n \"payment\",\n ],\n properties: {\n // A $ref to the shared Address definition (read-only in the tree).\n shipping_address: { $ref: \"#/$defs/Address\", title: \"Shipping address\" },\n // A fixed value carried by every document (const authoring).\n schema_version: {\n type: \"string\",\n title: \"Schema version\",\n const: \"checkout/v1\",\n },\n amount: { type: \"number\", title: \"Amount\", minimum: 0 },\n currency: {\n type: \"string\",\n title: \"Currency\",\n enum: [\"EUR\", \"USD\", \"GBP\"],\n },\n expedited: { type: \"boolean\", title: \"Expedited\" },\n gift_wrap: { type: \"boolean\", title: \"Gift wrap\" },\n // Declarative visibility rule (x-ui-rule): declared at its own position,\n // shown only when gift_wrap is checked. Contrast with the if/then/else\n // fields above, which are structurally added by their conditionals.\n gift_message: {\n type: \"string\",\n title: \"Gift message\",\n \"x-ui-rule\": {\n effect: \"show\",\n condition: { scope: \"/gift_wrap\", schema: { const: true } },\n },\n },\n // Nullable optional (anyOf [T, null]) -- the renderer unwraps to T.\n note: {\n title: \"Note (optional)\",\n anyOf: [{ type: \"string\" }, { type: \"null\" }],\n },\n // A discriminated union (oneOf): the payment method.\n payment: {\n type: \"object\",\n title: \"Payment method\",\n discriminator: { propertyName: \"kind\" },\n oneOf: [\n {\n title: \"Card\",\n properties: {\n kind: { const: \"card\" },\n card_number: { type: \"string\", title: \"Card number\" },\n cvc: { type: \"string\", title: \"CVC\" },\n },\n },\n {\n title: \"Bank transfer\",\n properties: {\n kind: { const: \"bank\" },\n iban: { type: \"string\", title: \"IBAN\" },\n },\n },\n {\n title: \"Cash\",\n properties: { kind: { const: \"cash\" } },\n },\n ],\n },\n },\n required: [\"amount\", \"currency\"],\n // Conditionals (if/then/else) authored as allOf members.\n allOf: [\n {\n // Large amounts require an approval reference.\n if: {\n properties: { amount: { exclusiveMinimum: 1000 } },\n required: [\"amount\"],\n },\n then: {\n properties: {\n requires_approval: {\n type: \"string\",\n title: \"Approval reference\",\n },\n },\n required: [\"requires_approval\"],\n },\n },\n {\n // Expedited orders ask for a delivery window; otherwise none.\n if: {\n properties: { expedited: { const: true } },\n required: [\"expedited\"],\n },\n then: {\n properties: {\n delivery_window: {\n type: \"string\",\n title: \"Delivery window\",\n enum: [\"morning\", \"afternoon\", \"evening\"],\n },\n },\n },\n },\n ],\n};\n\nconst AUDIT_EDITABLE_PATHS = [\n \"/properties/metadata/properties\",\n \"/properties/actor/properties/metadata/properties\",\n \"/properties/targets/items/properties/metadata/properties\",\n];\n\ntype ProfileKey = \"full\" | \"data\" | \"scoped\" | \"structure\" | \"logic\";\n\ninterface Profile {\n label: string;\n description: string;\n schema: JsonSchema;\n capabilities?: SchemaDesignerCapabilities;\n readOnly?: boolean;\n}\n\nconst PROFILES: Record<ProfileKey, Profile> = {\n full: {\n label: \"Full (schema + uiSchema)\",\n description: \"Default: author the schema and its form presentation hints.\",\n schema: SAMPLE_SCHEMA,\n capabilities: { previews: [\"form\", \"table\", \"json\", \"capabilities\"] },\n },\n data: {\n label: \"Data schema only\",\n description:\n \"Pure JSON Schema (audit, terminology): no UI/Combined tabs, JSON preview only.\",\n schema: SAMPLE_SCHEMA,\n capabilities: { mode: \"data\", previews: [\"json\", \"capabilities\"] },\n },\n scoped: {\n label: \"Scoped (audit event)\",\n description:\n \"Fixed envelope; only the three metadata containers are editable.\",\n schema: AUDIT_SCHEMA,\n capabilities: {\n mode: \"data\",\n editablePaths: AUDIT_EDITABLE_PATHS,\n previews: [\"json\", \"capabilities\"],\n },\n },\n structure: {\n label: \"Structure only (no preview)\",\n description: \"Tree + inspector only; the center preview pane is hidden.\",\n schema: SAMPLE_SCHEMA,\n capabilities: { mode: \"data\", previews: [] },\n },\n logic: {\n label: \"Logic (variants + conditionals)\",\n description:\n \"Shows every logic construct: a oneOf variant, if/then/else conditionals, a const field, and a nullable optional.\",\n schema: LOGIC_SCHEMA,\n capabilities: { previews: [\"form\", \"table\", \"json\", \"capabilities\"] },\n },\n};\n\n/**\n * PlaySchemaDesigner -- exercises SchemaDesigner: visually author a JsonSchema\n * (and its uiSchema presentation hints), with a live preview. The profile\n * switcher presets the capability profile (data/full triage, scoped editing,\n * read-only); the in-designer Capabilities tab tweaks it live.\n */\nexport default function PlaySchemaDesigner() {\n const [profileKey, setProfileKey] = useState<ProfileKey>(\"full\");\n const profile = PROFILES[profileKey];\n\n const [schema, setSchema] = useState<JsonSchema>(profile.schema);\n const [uiSchema, setUiSchema] = useState<Record<string, UISchema>>({});\n\n const selectProfile = (key: ProfileKey) => {\n setProfileKey(key);\n setSchema(PROFILES[key].schema);\n setUiSchema({});\n };\n\n return (\n <div className=\"w-full flex flex-col gap-3 h-[calc(100vh-8rem)]\">\n <div>\n <h1>Schema Designer</h1>\n <p className=\"text-sm text-muted-foreground mb-3\">\n Visually author a JSON Schema and its UI presentation hints. Edits\n flow through onChange as a valid schema + uiSchema.\n </p>\n </div>\n\n <div className=\"flex items-center gap-3\">\n <label\n htmlFor=\"capability-profile\"\n className=\"shrink-0 text-sm font-medium\"\n >\n Capability profile\n </label>\n <div className=\"w-72\">\n <FormSelect\n id=\"capability-profile\"\n name=\"profile\"\n value={profileKey}\n options={(Object.keys(PROFILES) as ProfileKey[]).map((k) => ({\n value: k,\n label: PROFILES[k].label,\n }))}\n onChange={(v) => selectProfile((v as ProfileKey) ?? \"full\")}\n clearable={false}\n />\n </div>\n <p className=\"text-sm text-muted-foreground\">{profile.description}</p>\n </div>\n\n <div style={{ flex: 1, minHeight: 0 }}>\n <SchemaDesigner\n key={profileKey}\n schema={schema}\n uiSchema={uiSchema}\n capabilities={profile.capabilities}\n readOnly={profile.readOnly}\n onChange={(nextSchema, nextUiSchema) => {\n setSchema(nextSchema);\n setUiSchema(nextUiSchema);\n }}\n />\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}