@petrarca/sonnet-playground 0.3.0 → 0.4.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 (30) hide show
  1. package/README.md +142 -0
  2. package/dist/{PlayCoreComponents-F2OFSQZK.js → PlayCoreComponents-GXFMB24T.js} +2 -2
  3. package/dist/{PlayDataComponents-BA3NA225.js → PlayDataComponents-M4SJ4XEL.js} +2 -2
  4. package/dist/{PlayFormComponents-MZC7CNES.js → PlayFormComponents-4E2A2Y2W.js} +2 -2
  5. package/dist/PlayGraph-3F56PREG.js +7 -0
  6. package/dist/{PlayShellApi-3T4FZPEV.js → PlayShellApi-5O6VYR2X.js} +2 -2
  7. package/dist/{chunk-MT4ILA37.js → chunk-32DDRRWU.js} +63 -9
  8. package/dist/chunk-32DDRRWU.js.map +1 -0
  9. package/dist/{chunk-4S2ITDB3.js → chunk-CQ6PGFRV.js} +21 -2
  10. package/dist/chunk-CQ6PGFRV.js.map +1 -0
  11. package/dist/{chunk-SBKZRIJC.js → chunk-VOC5VZG2.js} +48 -5
  12. package/dist/chunk-VOC5VZG2.js.map +1 -0
  13. package/dist/{chunk-DKLALDHR.js → chunk-YEBK2TUW.js} +2 -2
  14. package/dist/chunk-YEBK2TUW.js.map +1 -0
  15. package/dist/{chunk-QCK2M4KD.js → chunk-YOOWJORD.js} +28 -1
  16. package/dist/chunk-YOOWJORD.js.map +1 -0
  17. package/dist/index.js +5 -5
  18. package/dist/pages/index.js +5 -5
  19. package/package.json +6 -6
  20. package/dist/PlayGraph-RHFIDAS3.js +0 -7
  21. package/dist/chunk-4S2ITDB3.js.map +0 -1
  22. package/dist/chunk-DKLALDHR.js.map +0 -1
  23. package/dist/chunk-MT4ILA37.js.map +0 -1
  24. package/dist/chunk-QCK2M4KD.js.map +0 -1
  25. package/dist/chunk-SBKZRIJC.js.map +0 -1
  26. /package/dist/{PlayCoreComponents-F2OFSQZK.js.map → PlayCoreComponents-GXFMB24T.js.map} +0 -0
  27. /package/dist/{PlayDataComponents-BA3NA225.js.map → PlayDataComponents-M4SJ4XEL.js.map} +0 -0
  28. /package/dist/{PlayFormComponents-MZC7CNES.js.map → PlayFormComponents-4E2A2Y2W.js.map} +0 -0
  29. /package/dist/{PlayGraph-RHFIDAS3.js.map → PlayGraph-3F56PREG.js.map} +0 -0
  30. /package/dist/{PlayShellApi-3T4FZPEV.js.map → PlayShellApi-5O6VYR2X.js.map} +0 -0
package/README.md ADDED
@@ -0,0 +1,142 @@
1
+ # @petrarca/sonnet-playground
2
+
3
+ Playground framework and built-in component demos for the Petrarca Sonnet
4
+ component library.
5
+
6
+ ## What's included
7
+
8
+ **Playground framework** — Registry, overview tile grid, and `createPlaygroundModule()`
9
+ factory. Wire a playground into any `sonnet-shell` app with a few lines.
10
+
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.
14
+
15
+ **PlaygroundSection** — Shared section wrapper (`default` and `card` variants)
16
+ used by all playground pages.
17
+
18
+ ---
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ pnpm add @petrarca/sonnet-playground
24
+ ```
25
+
26
+ Peer dependencies: `react`, `react-dom`, `@petrarca/sonnet-shell`,
27
+ `@petrarca/sonnet-ui`, `@petrarca/sonnet-forms`, `@petrarca/sonnet-graph`.
28
+
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
+ ---
74
+
75
+ ## Adding app-specific pages
76
+
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.
80
+
81
+ ```ts
82
+ // src/modules/playground/index.ts
83
+ import { lazy } from "react";
84
+ import { Search } from "lucide-react";
85
+ import {
86
+ createPlaygroundRegistry,
87
+ createPlaygroundModule,
88
+ } from "@petrarca/sonnet-playground";
89
+
90
+ const registry = createPlaygroundRegistry();
91
+
92
+ // Register app-specific pages
93
+ registry.register({
94
+ id: "app.my-widget",
95
+ title: "My Widget",
96
+ description: "Interactive demo of MyWidget with live configuration.",
97
+ icon: Search,
98
+ color: "teal",
99
+ path: "my-widget",
100
+ component: lazy(() => import("./pages/PlayMyWidget")),
101
+ group: "App Components", // appears as a group heading in the overview
102
+ order: 0,
103
+ });
104
+
105
+ export default createPlaygroundModule(registry);
106
+ ```
107
+
108
+ Pages are lazy-loaded automatically — wrap the component in `React.lazy()`
109
+ as shown above. The framework handles the `Suspense` boundary.
110
+
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.
113
+
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` |
137
+
138
+ ---
139
+
140
+ ## License
141
+
142
+ See [LICENSE.md](../../LICENSE.md).
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  PlayCoreComponents
3
- } from "./chunk-QCK2M4KD.js";
3
+ } from "./chunk-YOOWJORD.js";
4
4
  import "./chunk-C2EZ2ECG.js";
5
5
  export {
6
6
  PlayCoreComponents as default
7
7
  };
8
- //# sourceMappingURL=PlayCoreComponents-F2OFSQZK.js.map
8
+ //# sourceMappingURL=PlayCoreComponents-GXFMB24T.js.map
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  PlayDataComponents
3
- } from "./chunk-DKLALDHR.js";
3
+ } from "./chunk-YEBK2TUW.js";
4
4
  import "./chunk-C2EZ2ECG.js";
5
5
  export {
6
6
  PlayDataComponents as default
7
7
  };
8
- //# sourceMappingURL=PlayDataComponents-BA3NA225.js.map
8
+ //# sourceMappingURL=PlayDataComponents-M4SJ4XEL.js.map
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  PlayFormComponents
3
- } from "./chunk-MT4ILA37.js";
3
+ } from "./chunk-32DDRRWU.js";
4
4
  import "./chunk-C2EZ2ECG.js";
5
5
  export {
6
6
  PlayFormComponents as default
7
7
  };
8
- //# sourceMappingURL=PlayFormComponents-MZC7CNES.js.map
8
+ //# sourceMappingURL=PlayFormComponents-4E2A2Y2W.js.map
@@ -0,0 +1,7 @@
1
+ import {
2
+ PlayGraph
3
+ } from "./chunk-VOC5VZG2.js";
4
+ export {
5
+ PlayGraph as default
6
+ };
7
+ //# sourceMappingURL=PlayGraph-3F56PREG.js.map
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  PlayShellApi
3
- } from "./chunk-4S2ITDB3.js";
3
+ } from "./chunk-CQ6PGFRV.js";
4
4
  import "./chunk-C2EZ2ECG.js";
5
5
  export {
6
6
  PlayShellApi as default
7
7
  };
8
- //# sourceMappingURL=PlayShellApi-3T4FZPEV.js.map
8
+ //# sourceMappingURL=PlayShellApi-5O6VYR2X.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-C2EZ2ECG.js";
4
4
 
5
5
  // src/pages/PlayFormComponents.tsx
6
- import { useState } from "react";
6
+ import { useState, useCallback, useRef } from "react";
7
7
  import { SimpleStack, Card } from "@petrarca/sonnet-ui";
8
8
  import {
9
9
  FormInput,
@@ -18,8 +18,16 @@ import { jsx, jsxs } from "react/jsx-runtime";
18
18
  function PlayFormComponents() {
19
19
  const [textValue, setTextValue] = useState("");
20
20
  const [emailValue, setEmailValue] = useState("");
21
+ const [emailError, setEmailError] = useState("");
21
22
  const [passwordValue, setPasswordValue] = useState("");
22
- const [urlValue, setUrlValue] = useState("");
23
+ const validateEmail = useCallback((value) => {
24
+ if (!value) {
25
+ setEmailError("");
26
+ return;
27
+ }
28
+ const valid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
29
+ setEmailError(valid ? "" : "Invalid email address");
30
+ }, []);
23
31
  const [textareaValue, setTextareaValue] = useState("");
24
32
  const [textareaError, setTextareaError] = useState("");
25
33
  const [numberValue, setNumberValue] = useState(void 0);
@@ -27,6 +35,19 @@ function PlayFormComponents() {
27
35
  const [decimalValue, setDecimalValue] = useState(
28
36
  void 0
29
37
  );
38
+ const [rangeValidated, setRangeValidated] = useState(
39
+ void 0
40
+ );
41
+ const [rangeError, setRangeError] = useState("");
42
+ const rangeValidatedRef = useRef(void 0);
43
+ const validateRange = useCallback((value) => {
44
+ if (value === void 0) {
45
+ setRangeError("");
46
+ return;
47
+ }
48
+ if (value < 1 || value > 10) setRangeError("Must be between 1 and 10");
49
+ else setRangeError("");
50
+ }, []);
30
51
  const [checkboxValue, setCheckboxValue] = useState(false);
31
52
  const [checkboxIndeterminate, setCheckboxIndeterminate] = useState("indeterminate");
32
53
  const [selectValue, setSelectValue] = useState("");
@@ -88,7 +109,7 @@ function PlayFormComponents() {
88
109
  placeholder: "john@example.com"
89
110
  }
90
111
  ) }),
91
- /* @__PURE__ */ jsx(ExampleBlock, { label: "With error", children: /* @__PURE__ */ jsx(
112
+ /* @__PURE__ */ jsx(ExampleBlock, { label: "WITH ERROR (STATIC)", children: /* @__PURE__ */ jsx(
92
113
  FormInput,
93
114
  {
94
115
  label: "Email",
@@ -98,6 +119,21 @@ function PlayFormComponents() {
98
119
  placeholder: "john@example.com"
99
120
  }
100
121
  ) }),
122
+ /* @__PURE__ */ jsx(ExampleBlock, { label: "Email (on-blur validation)", children: /* @__PURE__ */ jsx(
123
+ FormInput,
124
+ {
125
+ label: "Email",
126
+ type: "email",
127
+ value: emailValue,
128
+ onChange: (e) => {
129
+ setEmailValue(e.target.value);
130
+ if (emailError) validateEmail(e.target.value);
131
+ },
132
+ onBlur: (e) => validateEmail(e.target.value),
133
+ error: emailError,
134
+ placeholder: "user@example.com"
135
+ }
136
+ ) }),
101
137
  /* @__PURE__ */ jsx(ExampleBlock, { label: "Password", children: /* @__PURE__ */ jsx(
102
138
  FormInput,
103
139
  {
@@ -249,7 +285,7 @@ function PlayFormComponents() {
249
285
  placeholder: "0"
250
286
  }
251
287
  ) }),
252
- /* @__PURE__ */ jsx(ExampleBlock, { label: "With error", children: /* @__PURE__ */ jsx(
288
+ /* @__PURE__ */ jsx(ExampleBlock, { label: "WITH ERROR (STATIC)", children: /* @__PURE__ */ jsx(
253
289
  FormNumberInput,
254
290
  {
255
291
  label: "Invalid Input",
@@ -257,6 +293,24 @@ function PlayFormComponents() {
257
293
  onChange: setNumberValue,
258
294
  error: "Value must be greater than 0"
259
295
  }
296
+ ) }),
297
+ /* @__PURE__ */ jsx(ExampleBlock, { label: "Range (on-blur validation)", children: /* @__PURE__ */ jsx(
298
+ FormNumberInput,
299
+ {
300
+ label: "Rating (1\u201310)",
301
+ value: rangeValidated,
302
+ onChange: (v) => {
303
+ setRangeValidated(v);
304
+ rangeValidatedRef.current = v;
305
+ if (rangeError) validateRange(v);
306
+ },
307
+ onBlur: () => validateRange(rangeValidatedRef.current),
308
+ error: rangeError,
309
+ min: 1,
310
+ max: 10,
311
+ step: 1,
312
+ placeholder: "1\u201310"
313
+ }
260
314
  ) })
261
315
  ] }),
262
316
  /* @__PURE__ */ jsx("pre", { className: "text-xs bg-muted p-2 rounded overflow-x-auto", children: /* @__PURE__ */ jsx("code", { children: `<FormNumberInput
@@ -322,7 +376,7 @@ function PlayFormComponents() {
322
376
  disabled: true
323
377
  }
324
378
  ) }),
325
- /* @__PURE__ */ jsx(ExampleBlock, { label: "With error", children: /* @__PURE__ */ jsx(
379
+ /* @__PURE__ */ jsx(ExampleBlock, { label: "WITH ERROR (STATIC)", children: /* @__PURE__ */ jsx(
326
380
  FormCheckbox,
327
381
  {
328
382
  label: "Required checkbox",
@@ -392,7 +446,7 @@ function PlayFormComponents() {
392
446
  placeholder: "Cannot change"
393
447
  }
394
448
  ) }),
395
- /* @__PURE__ */ jsx(ExampleBlock, { label: "With error", children: /* @__PURE__ */ jsx(
449
+ /* @__PURE__ */ jsx(ExampleBlock, { label: "WITH ERROR (STATIC)", children: /* @__PURE__ */ jsx(
396
450
  FormSelect,
397
451
  {
398
452
  label: "Invalid Selection",
@@ -460,7 +514,7 @@ function PlayFormComponents() {
460
514
  placeholder: "Select at least one skill"
461
515
  }
462
516
  ) }),
463
- /* @__PURE__ */ jsx(ExampleBlock, { label: "With error", children: /* @__PURE__ */ jsx(
517
+ /* @__PURE__ */ jsx(ExampleBlock, { label: "WITH ERROR (STATIC)", children: /* @__PURE__ */ jsx(
464
518
  FormMultiSelect,
465
519
  {
466
520
  label: "Categories",
@@ -518,7 +572,7 @@ function PlayFormComponents() {
518
572
  placeholder: "Add at least one keyword"
519
573
  }
520
574
  ) }),
521
- /* @__PURE__ */ jsx(ExampleBlock, { label: "With error", children: /* @__PURE__ */ jsx(
575
+ /* @__PURE__ */ jsx(ExampleBlock, { label: "WITH ERROR (STATIC)", children: /* @__PURE__ */ jsx(
522
576
  FormTagsInput,
523
577
  {
524
578
  label: "Tags",
@@ -560,4 +614,4 @@ function PlayFormComponents() {
560
614
  export {
561
615
  PlayFormComponents
562
616
  };
563
- //# sourceMappingURL=chunk-MT4ILA37.js.map
617
+ //# sourceMappingURL=chunk-32DDRRWU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pages/PlayFormComponents.tsx"],"sourcesContent":["/**\n * Playground page for testing Form components\n * Accessible at /playground/form-components\n *\n * Tests all custom Form wrapper components that provide consistent\n * label, description, and error handling around base UI components.\n */\n\nimport { useState, useCallback, useRef } from \"react\";\nimport { SimpleStack, Card } from \"@petrarca/sonnet-ui\";\nimport { ExampleBlock } from \"../PlaygroundSection\";\nimport {\n FormInput,\n FormTextarea,\n FormNumberInput,\n FormCheckbox,\n FormSelect,\n FormMultiSelect,\n FormTagsInput,\n} from \"@petrarca/sonnet-forms\";\n\nexport default function PlayFormComponents() {\n // FormInput states\n const [textValue, setTextValue] = useState(\"\");\n const [emailValue, setEmailValue] = useState(\"\");\n const [emailError, setEmailError] = useState(\"\");\n const [passwordValue, setPasswordValue] = useState(\"\");\n\n const validateEmail = useCallback((value: string) => {\n if (!value) {\n setEmailError(\"\");\n return;\n }\n const valid = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value);\n setEmailError(valid ? \"\" : \"Invalid email address\");\n }, []);\n\n // FormTextarea states\n const [textareaValue, setTextareaValue] = useState(\"\");\n const [textareaError, setTextareaError] = useState(\"\");\n\n // FormNumberInput states\n const [numberValue, setNumberValue] = useState<number | undefined>(undefined);\n const [rangeValue, setRangeValue] = useState<number | undefined>(5);\n const [decimalValue, setDecimalValue] = useState<number | undefined>(\n undefined,\n );\n const [rangeValidated, setRangeValidated] = useState<number | undefined>(\n undefined,\n );\n const [rangeError, setRangeError] = useState(\"\");\n const rangeValidatedRef = useRef<number | undefined>(undefined);\n\n const validateRange = useCallback((value: number | undefined) => {\n if (value === undefined) {\n setRangeError(\"\");\n return;\n }\n if (value < 1 || value > 10) setRangeError(\"Must be between 1 and 10\");\n else setRangeError(\"\");\n }, []);\n\n // FormCheckbox states\n const [checkboxValue, setCheckboxValue] = useState(false);\n const [checkboxIndeterminate, setCheckboxIndeterminate] = useState<\n boolean | \"indeterminate\"\n >(\"indeterminate\");\n\n // FormSelect states\n const [selectValue, setSelectValue] = useState(\"\");\n const [selectRequired, setSelectRequired] = useState(\"\");\n\n // FormMultiSelect states\n const [multiSelectValue, setMultiSelectValue] = useState<string[]>([]);\n\n // FormTagsInput states\n const [tagsValue, setTagsValue] = useState<string[]>([\"react\", \"typescript\"]);\n\n // Options for selects\n const colorOptions = [\n { label: \"Red\", value: \"red\" },\n { label: \"Green\", value: \"green\" },\n { label: \"Blue\", value: \"blue\" },\n { label: \"Yellow\", value: \"yellow\" },\n { label: \"Purple\", value: \"purple\" },\n ];\n\n const countryOptions = [\n { label: \"United States\", value: \"us\" },\n { label: \"Canada\", value: \"ca\" },\n { label: \"United Kingdom\", value: \"uk\" },\n { label: \"Germany\", value: \"de\" },\n { label: \"France\", value: \"fr\" },\n { label: \"Japan\", value: \"jp\" },\n { label: \"Australia\", value: \"au\" },\n ];\n\n return (\n <div className=\"w-full max-w-4xl space-y-6\">\n <div>\n <h1>Form Components Playground</h1>\n <p className=\"text-sm text-muted-foreground mb-3\">\n Test all custom Form wrapper components with labels, descriptions, and\n error states\n </p>\n </div>\n\n <div>\n <SimpleStack gap=\"md\" style={{ maxWidth: \"900px\" }}>\n {/* FormInput */}\n <Card className=\"border shadow-sm p-4\">\n <SimpleStack gap=\"sm\">\n <h2>FormInput</h2>\n <p className=\"text-sm text-muted-foreground\">\n Text input wrapper with label, description, and error support.\n Supports all HTML input types.\n </p>\n\n <div className=\"grid grid-cols-2 gap-3 pt-2\">\n <ExampleBlock label=\"Basic\">\n <FormInput\n label=\"Username\"\n value={textValue}\n onChange={(e) => setTextValue(e.target.value)}\n placeholder=\"Enter username\"\n />\n </ExampleBlock>\n <ExampleBlock label=\"With description\">\n <FormInput\n label=\"Full Name\"\n description=\"Your first and last name\"\n value={textValue}\n onChange={(e) => setTextValue(e.target.value)}\n placeholder=\"John Doe\"\n />\n </ExampleBlock>\n <ExampleBlock label=\"Required\">\n <FormInput\n label=\"Email\"\n required\n value={emailValue}\n onChange={(e) => setEmailValue(e.target.value)}\n placeholder=\"john@example.com\"\n />\n </ExampleBlock>\n <ExampleBlock label=\"WITH ERROR (STATIC)\">\n <FormInput\n label=\"Email\"\n value={emailValue}\n onChange={(e) => setEmailValue(e.target.value)}\n error=\"Invalid email format\"\n placeholder=\"john@example.com\"\n />\n </ExampleBlock>\n <ExampleBlock label=\"Email (on-blur validation)\">\n <FormInput\n label=\"Email\"\n type=\"email\"\n value={emailValue}\n onChange={(e) => {\n setEmailValue(e.target.value);\n if (emailError) validateEmail(e.target.value);\n }}\n onBlur={(e) => validateEmail(e.target.value)}\n error={emailError}\n placeholder=\"user@example.com\"\n />\n </ExampleBlock>\n <ExampleBlock label=\"Password\">\n <FormInput\n label=\"Password\"\n type=\"password\"\n value={passwordValue}\n onChange={(e) => setPasswordValue(e.target.value)}\n placeholder=\"••••••••\"\n />\n </ExampleBlock>\n <ExampleBlock label=\"Disabled\">\n <FormInput\n label=\"Readonly Field\"\n value=\"Cannot edit this\"\n onChange={() => {}}\n disabled\n />\n </ExampleBlock>\n </div>\n\n <pre className=\"text-xs bg-muted p-2 rounded overflow-x-auto\">\n <code>{`<FormInput\n label=\"Username\"\n value={textValue}\n onChange={(e) => setTextValue(e.target.value)}\n placeholder=\"Enter username\"\n description=\"Optional description\"\n error=\"Optional error message\"\n required={false}\n disabled={false}\n/>`}</code>\n </pre>\n\n <p className=\"text-xs text-muted-foreground\">\n Current value: {textValue || \"(empty)\"}\n </p>\n </SimpleStack>\n </Card>\n\n {/* FormTextarea */}\n <Card className=\"border shadow-sm p-4\">\n <SimpleStack gap=\"sm\">\n <h2>FormTextarea</h2>\n <p className=\"text-sm text-muted-foreground\">\n Multi-line text input with label, description, and error\n support.\n </p>\n\n <div className=\"grid grid-cols-2 gap-3 pt-2\">\n <ExampleBlock label=\"Basic\">\n <FormTextarea\n label=\"Description\"\n value={textareaValue}\n onChange={(e) => setTextareaValue(e.target.value)}\n placeholder=\"Enter a detailed description...\"\n rows={4}\n />\n </ExampleBlock>\n <ExampleBlock label=\"With description\">\n <FormTextarea\n label=\"Bio\"\n description=\"Tell us about yourself (max 500 characters)\"\n value={textareaValue}\n onChange={(e) => setTextareaValue(e.target.value)}\n placeholder=\"I am a...\"\n rows={3}\n />\n </ExampleBlock>\n <ExampleBlock label=\"With error validation\">\n <FormTextarea\n label=\"Comments\"\n value={textareaValue}\n onChange={(e) => {\n setTextareaValue(e.target.value);\n setTextareaError(\n e.target.value.length > 100\n ? \"Maximum 100 characters allowed\"\n : \"\",\n );\n }}\n error={textareaError}\n placeholder=\"Enter your comments...\"\n rows={3}\n />\n </ExampleBlock>\n <ExampleBlock label=\"Disabled\">\n <FormTextarea\n label=\"Readonly Text\"\n value=\"This cannot be edited\"\n onChange={() => {}}\n disabled\n rows={2}\n />\n </ExampleBlock>\n </div>\n\n <pre className=\"text-xs bg-muted p-2 rounded overflow-x-auto\">\n <code>{`<FormTextarea\n label=\"Description\"\n value={textareaValue}\n onChange={(e) => setTextareaValue(e.target.value)}\n placeholder=\"Enter text...\"\n rows={4}\n description=\"Optional description\"\n error=\"Optional error message\"\n/>`}</code>\n </pre>\n\n <p className=\"text-xs text-muted-foreground\">\n Current value: {textareaValue || \"(empty)\"}\n </p>\n </SimpleStack>\n </Card>\n\n {/* FormNumberInput */}\n <Card className=\"border shadow-sm p-4\">\n <SimpleStack gap=\"sm\">\n <h2>FormNumberInput</h2>\n <p className=\"text-sm text-muted-foreground\">\n Number input with min/max validation and step control.\n </p>\n\n <div className=\"grid grid-cols-2 gap-3 pt-2\">\n <ExampleBlock label=\"Basic\">\n <FormNumberInput\n label=\"Age\"\n value={numberValue}\n onChange={setNumberValue}\n placeholder=\"Enter age\"\n />\n </ExampleBlock>\n <ExampleBlock label=\"With min/max/step\">\n <FormNumberInput\n label=\"Rating (1-10)\"\n value={rangeValue}\n onChange={setRangeValue}\n min={1}\n max={10}\n step={1}\n description=\"Rate from 1 to 10\"\n />\n </ExampleBlock>\n <ExampleBlock label=\"Decimal\">\n <FormNumberInput\n label=\"Price\"\n value={decimalValue}\n onChange={setDecimalValue}\n allowDecimal={true}\n step={0.01}\n placeholder=\"0.00\"\n description=\"Enter price with cents\"\n />\n </ExampleBlock>\n <ExampleBlock label=\"Required\">\n <FormNumberInput\n label=\"Quantity\"\n required\n value={numberValue}\n onChange={setNumberValue}\n min={0}\n placeholder=\"0\"\n />\n </ExampleBlock>\n <ExampleBlock label=\"WITH ERROR (STATIC)\">\n <FormNumberInput\n label=\"Invalid Input\"\n value={numberValue}\n onChange={setNumberValue}\n error=\"Value must be greater than 0\"\n />\n </ExampleBlock>\n <ExampleBlock label=\"Range (on-blur validation)\">\n <FormNumberInput\n label=\"Rating (1–10)\"\n value={rangeValidated}\n onChange={(v) => {\n setRangeValidated(v);\n rangeValidatedRef.current = v;\n if (rangeError) validateRange(v);\n }}\n onBlur={() => validateRange(rangeValidatedRef.current)}\n error={rangeError}\n min={1}\n max={10}\n step={1}\n placeholder=\"1–10\"\n />\n </ExampleBlock>\n </div>\n\n <pre className=\"text-xs bg-muted p-2 rounded overflow-x-auto\">\n <code>{`<FormNumberInput\n label=\"Age\"\n value={numberValue}\n onChange={setNumberValue}\n min={0}\n max={120}\n step={1}\n allowDecimal={false}\n/>`}</code>\n </pre>\n\n <p className=\"text-xs text-muted-foreground\">\n Current value: {numberValue ?? \"(empty)\"}\n </p>\n </SimpleStack>\n </Card>\n\n {/* FormCheckbox */}\n <Card className=\"border shadow-sm p-4\">\n <SimpleStack gap=\"sm\">\n <h2>FormCheckbox</h2>\n <p className=\"text-sm text-muted-foreground\">\n Checkbox with label, description, and indeterminate state\n support.\n </p>\n\n <div className=\"grid grid-cols-2 gap-3 pt-2\">\n <ExampleBlock label=\"Basic\">\n <FormCheckbox\n label=\"Accept terms and conditions\"\n checked={checkboxValue}\n onChange={(checked) => setCheckboxValue(checked === true)}\n />\n </ExampleBlock>\n <ExampleBlock label=\"With description\">\n <FormCheckbox\n label=\"Subscribe to newsletter\"\n description=\"Receive weekly updates about new features\"\n checked={checkboxValue}\n onChange={(checked) => setCheckboxValue(checked === true)}\n />\n </ExampleBlock>\n <ExampleBlock label=\"Required\">\n <FormCheckbox\n label=\"I agree to the privacy policy\"\n required\n checked={checkboxValue}\n onChange={(checked) => setCheckboxValue(checked === true)}\n />\n </ExampleBlock>\n <ExampleBlock label=\"Indeterminate\">\n <FormCheckbox\n label=\"Select all items\"\n description=\"Some items are selected\"\n checked={checkboxIndeterminate}\n onChange={setCheckboxIndeterminate}\n />\n </ExampleBlock>\n <ExampleBlock label=\"Disabled\">\n <FormCheckbox\n label=\"Cannot change this\"\n checked={true}\n onChange={() => {}}\n disabled\n />\n </ExampleBlock>\n <ExampleBlock label=\"WITH ERROR (STATIC)\">\n <FormCheckbox\n label=\"Required checkbox\"\n checked={checkboxValue}\n onChange={(checked) => setCheckboxValue(checked === true)}\n error=\"You must accept to continue\"\n />\n </ExampleBlock>\n </div>\n\n <pre className=\"text-xs bg-muted p-2 rounded overflow-x-auto\">\n <code>{`<FormCheckbox\n label=\"Accept terms\"\n checked={checkboxValue}\n onChange={(checked) => setCheckboxValue(checked === true)}\n description=\"Optional description\"\n required={false}\n/>`}</code>\n </pre>\n\n <p className=\"text-xs text-muted-foreground\">\n Current value: {String(checkboxValue)}\n </p>\n </SimpleStack>\n </Card>\n\n {/* FormSelect */}\n <Card className=\"border shadow-sm p-4\">\n <SimpleStack gap=\"sm\">\n <h2>FormSelect</h2>\n <p className=\"text-sm text-muted-foreground\">\n Searchable single-select dropdown with label and error support.\n </p>\n\n <div className=\"grid grid-cols-2 gap-3 pt-2\">\n <ExampleBlock label=\"Basic\">\n <FormSelect\n label=\"Favorite Color\"\n value={selectValue}\n onChange={(value) => setSelectValue(value || \"\")}\n options={colorOptions}\n placeholder=\"Choose a color\"\n />\n </ExampleBlock>\n <ExampleBlock label=\"With description\">\n <FormSelect\n label=\"Country\"\n description=\"Select your country of residence\"\n value={selectValue}\n onChange={(value) => setSelectValue(value || \"\")}\n options={countryOptions}\n placeholder=\"Select country\"\n />\n </ExampleBlock>\n <ExampleBlock label=\"Required\">\n <FormSelect\n label=\"Required Selection\"\n required\n value={selectRequired}\n onChange={(value) => setSelectRequired(value || \"\")}\n options={colorOptions}\n placeholder=\"Must select one\"\n />\n </ExampleBlock>\n <ExampleBlock label=\"Disabled\">\n <FormSelect\n label=\"Disabled Select\"\n value=\"blue\"\n onChange={() => {}}\n options={colorOptions}\n disabled\n placeholder=\"Cannot change\"\n />\n </ExampleBlock>\n <ExampleBlock label=\"WITH ERROR (STATIC)\">\n <FormSelect\n label=\"Invalid Selection\"\n value={selectValue}\n onChange={(value) => setSelectValue(value || \"\")}\n options={colorOptions}\n error=\"This field is required\"\n placeholder=\"Select option\"\n />\n </ExampleBlock>\n </div>\n\n <pre className=\"text-xs bg-muted p-2 rounded overflow-x-auto\">\n <code>{`<FormSelect\n label=\"Country\"\n value={selectValue}\n onChange={(value) => setSelectValue(value || '')}\n options={[\n { label: 'USA', value: 'us' },\n { label: 'UK', value: 'uk' }\n ]}\n placeholder=\"Select...\"\n/>`}</code>\n </pre>\n\n <p className=\"text-xs text-muted-foreground\">\n Current value: {selectValue || \"(none selected)\"}\n </p>\n </SimpleStack>\n </Card>\n\n {/* FormMultiSelect */}\n <Card className=\"border shadow-sm p-4\">\n <SimpleStack gap=\"sm\">\n <h2>FormMultiSelect</h2>\n <p className=\"text-sm text-muted-foreground\">\n Searchable multi-select dropdown with badges.\n </p>\n\n <div className=\"grid grid-cols-2 gap-3 pt-2\">\n <ExampleBlock label=\"Basic\">\n <FormMultiSelect\n label=\"Favorite Colors\"\n value={multiSelectValue}\n onChange={setMultiSelectValue}\n options={colorOptions}\n placeholder=\"Select multiple colors\"\n />\n </ExampleBlock>\n <ExampleBlock label=\"With description\">\n <FormMultiSelect\n label=\"Visited Countries\"\n description=\"Select all countries you've visited\"\n value={multiSelectValue}\n onChange={setMultiSelectValue}\n options={countryOptions}\n placeholder=\"Select countries\"\n />\n </ExampleBlock>\n <ExampleBlock label=\"Required\">\n <FormMultiSelect\n label=\"Skills\"\n required\n value={multiSelectValue}\n onChange={setMultiSelectValue}\n options={[\n { label: \"JavaScript\", value: \"js\" },\n { label: \"TypeScript\", value: \"ts\" },\n { label: \"Python\", value: \"py\" },\n { label: \"Java\", value: \"java\" },\n ]}\n placeholder=\"Select at least one skill\"\n />\n </ExampleBlock>\n <ExampleBlock label=\"WITH ERROR (STATIC)\">\n <FormMultiSelect\n label=\"Categories\"\n value={multiSelectValue}\n onChange={setMultiSelectValue}\n options={colorOptions}\n error=\"Please select at least 2 categories\"\n placeholder=\"Select categories\"\n />\n </ExampleBlock>\n </div>\n\n <pre className=\"text-xs bg-muted p-2 rounded overflow-x-auto\">\n <code>{`<FormMultiSelect\n label=\"Skills\"\n value={multiSelectValue}\n onChange={setMultiSelectValue}\n options={skillOptions}\n placeholder=\"Select skills\"\n/>`}</code>\n </pre>\n\n <p className=\"text-xs text-muted-foreground\">\n Current value:{\" \"}\n {multiSelectValue.length > 0\n ? multiSelectValue.join(\", \")\n : \"(none selected)\"}\n </p>\n </SimpleStack>\n </Card>\n\n {/* FormTagsInput */}\n <Card className=\"border shadow-sm p-4\">\n <SimpleStack gap=\"sm\">\n <h2>FormTagsInput</h2>\n <p className=\"text-sm text-muted-foreground\">\n Free-text tag input with creation and deletion.\n </p>\n\n <div className=\"grid grid-cols-2 gap-3 pt-2\">\n <ExampleBlock label=\"Basic\">\n <FormTagsInput\n label=\"Technologies\"\n value={tagsValue}\n onChange={setTagsValue}\n placeholder=\"Type and press Enter to add tags\"\n />\n </ExampleBlock>\n <ExampleBlock label=\"With description\">\n <FormTagsInput\n label=\"Skills\"\n description=\"Add your programming skills (press Enter after each)\"\n value={tagsValue}\n onChange={setTagsValue}\n placeholder=\"e.g., React, Node.js\"\n />\n </ExampleBlock>\n <ExampleBlock label=\"Required\">\n <FormTagsInput\n label=\"Keywords\"\n required\n value={tagsValue}\n onChange={setTagsValue}\n placeholder=\"Add at least one keyword\"\n />\n </ExampleBlock>\n <ExampleBlock label=\"WITH ERROR (STATIC)\">\n <FormTagsInput\n label=\"Tags\"\n value={tagsValue}\n onChange={setTagsValue}\n error=\"Maximum 5 tags allowed\"\n placeholder=\"Add tags\"\n />\n </ExampleBlock>\n <ExampleBlock label=\"Disabled\">\n <FormTagsInput\n label=\"Fixed Tags\"\n value={[\"readonly\", \"tags\"]}\n onChange={() => {}}\n disabled\n placeholder=\"Cannot edit\"\n />\n </ExampleBlock>\n </div>\n\n <pre className=\"text-xs bg-muted p-2 rounded overflow-x-auto\">\n <code>{`<FormTagsInput\n label=\"Technologies\"\n value={tagsValue}\n onChange={setTagsValue}\n placeholder=\"Type and press Enter\"\n description=\"Optional description\"\n/>`}</code>\n </pre>\n\n <p className=\"text-xs text-muted-foreground\">\n Current tags:{\" \"}\n {tagsValue.length > 0 ? tagsValue.join(\", \") : \"(none)\"}\n </p>\n </SimpleStack>\n </Card>\n </SimpleStack>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -229,7 +229,26 @@ function PlayShellApi() {
229
229
  children: "open() \u2014 full coverage"
230
230
  }
231
231
  ),
232
- /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onClick: () => panel.close(), children: "close()" })
232
+ /* @__PURE__ */ jsx(
233
+ Button,
234
+ {
235
+ variant: "outline",
236
+ size: "sm",
237
+ onClick: () => panel.open({
238
+ title: "Resizable Panel",
239
+ description: "Drag the left edge to resize. Double-click to reset.",
240
+ content: /* @__PURE__ */ jsxs("div", { className: "p-4 space-y-3", children: [
241
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Resizable panel" }),
242
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "resizable=true \xB7 defaultWidth=640 \xB7 minWidth=320 \xB7 maxWidth=1000" })
243
+ ] }),
244
+ width: "default",
245
+ resizable: true,
246
+ minWidth: 320,
247
+ maxWidth: 1e3
248
+ }),
249
+ children: "open() \u2014 resizable"
250
+ }
251
+ )
233
252
  ] })
234
253
  }
235
254
  ),
@@ -319,4 +338,4 @@ function PlayShellApi() {
319
338
  export {
320
339
  PlayShellApi
321
340
  };
322
- //# sourceMappingURL=chunk-4S2ITDB3.js.map
341
+ //# sourceMappingURL=chunk-CQ6PGFRV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pages/PlayShellApi.tsx"],"sourcesContent":["import { Button } from \"@petrarca/sonnet-ui\";\nimport {\n notification,\n dialog,\n navigation,\n panel,\n sidePane,\n} from \"@petrarca/sonnet-shell\";\nimport { PlaygroundSection } from \"../PlaygroundSection\";\n\n/**\n * PlayShellApi -- playground page that exercises the shell API surface.\n *\n * Covers: notification, dialog, navigation, panel, sidePane,\n * and the command menu (Cmd+K).\n */\nexport default function PlayShellApi() {\n return (\n <div className=\"space-y-6\">\n {/* ── notification ─────────────────────────────────────────── */}\n <PlaygroundSection\n title=\"notification\"\n description=\"Toasts via the shell notification API — wraps Sonner.\"\n variant=\"card\"\n >\n <div className=\"flex flex-wrap gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => notification.success(\"Operation completed.\")}\n >\n success()\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => notification.error(\"Something went wrong.\")}\n >\n error()\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => notification.warning(\"Proceed with caution.\")}\n >\n warning()\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => notification.info(\"Here is some information.\")}\n >\n info()\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() =>\n notification.promise(\n new Promise((resolve) => setTimeout(resolve, 2000)),\n {\n loading: \"Loading...\",\n success: \"Done!\",\n error: \"Failed.\",\n },\n )\n }\n >\n promise()\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => notification.dismiss()}\n >\n dismiss()\n </Button>\n </div>\n </PlaygroundSection>\n\n {/* ── dialog ───────────────────────────────────────────────── */}\n <PlaygroundSection\n title=\"dialog\"\n description=\"Confirmation dialog via the shell dialog API.\"\n variant=\"card\"\n >\n <div className=\"flex flex-wrap gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={async () => {\n const confirmed = await dialog.confirm({\n title: \"Delete Resource\",\n description:\n \"This will permanently delete the resource. Are you sure?\",\n confirmLabel: \"Delete\",\n variant: \"destructive\",\n });\n notification.info(\n confirmed ? \"User confirmed.\" : \"User cancelled.\",\n );\n }}\n >\n confirm() — destructive\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={async () => {\n const confirmed = await dialog.confirm({\n title: \"Save Changes\",\n description: \"Do you want to save your changes?\",\n });\n notification.info(\n confirmed ? \"User confirmed.\" : \"User cancelled.\",\n );\n }}\n >\n confirm() — default\n </Button>\n </div>\n </PlaygroundSection>\n\n {/* ── navigation ───────────────────────────────────────────── */}\n <PlaygroundSection\n title=\"navigation\"\n description=\"Programmatic navigation via the shell navigation API.\"\n variant=\"card\"\n >\n <div className=\"flex flex-wrap gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => navigation.goTo(\"/home\")}\n >\n goTo(\"/home\")\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => navigation.goTo(\"/playground\")}\n >\n goTo(\"/playground\")\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => navigation.openCommandMenu()}\n >\n openCommandMenu()\n </Button>\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigation.back()}>\n back()\n </Button>\n </div>\n </PlaygroundSection>\n\n {/* ── panel ────────────────────────────────────────────────── */}\n <PlaygroundSection\n title=\"panel\"\n description=\"Shell-managed slide-over panel — renders content inside a Sheet owned by the shell.\"\n variant=\"card\"\n >\n <div className=\"flex flex-wrap gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() =>\n panel.open({\n title: \"Panel Demo\",\n description: \"This is a shell-managed slide-over panel.\",\n content: (\n <div className=\"p-4 space-y-3\">\n <p className=\"text-sm\">\n This content is rendered inside the shell's Sheet\n component.\n </p>\n <p className=\"text-xs text-muted-foreground\">\n Use <code>panel.open()</code> to show any React content in\n a slide-over panel.\n </p>\n </div>\n ),\n })\n }\n >\n open() — narrow\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() =>\n panel.open({\n title: \"Wide Panel\",\n content: (\n <div className=\"p-4 space-y-3\">\n <p className=\"text-sm font-medium\">Wide panel (default)</p>\n <p className=\"text-xs text-muted-foreground\">\n width=\"default\" gives a wider panel for more complex\n content.\n </p>\n </div>\n ),\n width: \"default\",\n })\n }\n >\n open() — default width\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() =>\n panel.open({\n title: \"Full Coverage\",\n content: (\n <div className=\"p-4 space-y-3\">\n <p className=\"text-sm font-medium\">Full coverage panel</p>\n <p className=\"text-xs text-muted-foreground\">\n coverage=\"full\" overlays the entire content area.\n </p>\n </div>\n ),\n width: \"default\",\n coverage: \"full\",\n })\n }\n >\n open() — full coverage\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() =>\n panel.open({\n title: \"Resizable Panel\",\n description:\n \"Drag the left edge to resize. Double-click to reset.\",\n content: (\n <div className=\"p-4 space-y-3\">\n <p className=\"text-sm font-medium\">Resizable panel</p>\n <p className=\"text-xs text-muted-foreground\">\n resizable=true · defaultWidth=640 · minWidth=320 ·\n maxWidth=1000\n </p>\n </div>\n ),\n width: \"default\",\n resizable: true,\n minWidth: 320,\n maxWidth: 1000,\n })\n }\n >\n open() — resizable\n </Button>\n </div>\n </PlaygroundSection>\n\n {/* ── sidePane ─────────────────────────────────────────────── */}\n <PlaygroundSection\n title=\"sidePane\"\n description=\"Persistent inline resizable panel. Sits beside the content area — the main view shrinks rather than being overlaid. Drag the edge to resize; double-click to reset.\"\n variant=\"card\"\n >\n <div className=\"flex flex-wrap gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() =>\n sidePane.open({\n moduleId: \"shell-demo-narrow\",\n defaultWidth: 240,\n minWidth: 180,\n maxWidth: 400,\n content: (\n <div className=\"p-4 space-y-3\">\n <p className=\"text-sm font-medium\">Narrow pane (240px)</p>\n <p className=\"text-xs text-muted-foreground\">\n defaultWidth=240 minWidth=180 maxWidth=400\n </p>\n </div>\n ),\n })\n }\n >\n open() — narrow\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() =>\n sidePane.open({\n moduleId: \"shell-demo-wide\",\n defaultWidth: 480,\n minWidth: 320,\n maxWidth: 800,\n content: (\n <div className=\"p-4 space-y-3\">\n <p className=\"text-sm font-medium\">Wide pane (480px)</p>\n <p className=\"text-xs text-muted-foreground\">\n defaultWidth=480 minWidth=320 maxWidth=800\n </p>\n </div>\n ),\n })\n }\n >\n open() — wide\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() =>\n sidePane.toggle({\n moduleId: \"shell-demo-toggle\",\n defaultWidth: 320,\n content: (\n <div className=\"p-4 space-y-3\">\n <p className=\"text-sm font-medium\">Toggle pane</p>\n <p className=\"text-xs text-muted-foreground\">\n Click again to close. Same moduleId toggles.\n </p>\n </div>\n ),\n })\n }\n >\n toggle()\n </Button>\n <Button variant=\"outline\" size=\"sm\" onClick={() => sidePane.close()}>\n close()\n </Button>\n </div>\n </PlaygroundSection>\n\n {/* ── CommandMenu (Cmd+K) ──────────────────────────────────── */}\n <PlaygroundSection\n title=\"CommandMenu (Cmd+K)\"\n description=\"Open the command palette programmatically. Modules can register commands that appear here via the commands array in their ShellModule definition.\"\n variant=\"card\"\n >\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => navigation.openCommandMenu()}\n >\n Open CommandMenu\n </Button>\n </PlaygroundSection>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -1,8 +1,9 @@
1
1
  // src/pages/PlayGraph.tsx
2
- import { useCallback, useState } from "react";
2
+ import { useCallback, useRef, useState } from "react";
3
3
  import {
4
4
  GraphVisualizer,
5
5
  ActionPanel,
6
+ GraphA11yList,
6
7
  GraphRendererProvider,
7
8
  GraphStoresContext,
8
9
  createGraphDataStore,
@@ -21,7 +22,8 @@ import {
21
22
  Tabs,
22
23
  TabsContent,
23
24
  TabsList,
24
- TabsTrigger
25
+ TabsTrigger,
26
+ ResizeHandle
25
27
  } from "@petrarca/sonnet-ui";
26
28
  import { Play, RotateCcw } from "lucide-react";
27
29
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -238,6 +240,23 @@ function PlayGraph() {
238
240
  () => serializeGraphData(INITIAL_DATA)
239
241
  );
240
242
  const [parseError, setParseError] = useState(null);
243
+ const [panelWidth, setPanelWidth] = useState(300);
244
+ const rowRef = useRef(null);
245
+ const startResize = useCallback((e) => {
246
+ e.preventDefault();
247
+ const target = e.currentTarget;
248
+ target.setPointerCapture(e.pointerId);
249
+ const move = (ev) => {
250
+ const right = rowRef.current?.getBoundingClientRect().right ?? 0;
251
+ setPanelWidth(Math.min(560, Math.max(200, right - ev.clientX)));
252
+ };
253
+ const up = () => {
254
+ window.removeEventListener("pointermove", move);
255
+ window.removeEventListener("pointerup", up);
256
+ };
257
+ window.addEventListener("pointermove", move);
258
+ window.addEventListener("pointerup", up);
259
+ }, []);
241
260
  const handleApply = useCallback(() => {
242
261
  let parsed;
243
262
  try {
@@ -278,9 +297,33 @@ function PlayGraph() {
278
297
  /* @__PURE__ */ jsx(TabsTrigger, { value: "graph", children: "Graph" }),
279
298
  /* @__PURE__ */ jsx(TabsTrigger, { value: "data", children: "Data" })
280
299
  ] }),
281
- /* @__PURE__ */ jsx(TabsContent, { value: "graph", className: "mt-0", children: /* @__PURE__ */ jsx(GraphRendererProvider, { defaultRenderer: "cytoscape", children: /* @__PURE__ */ jsxs("div", { className: "flex border rounded-lg overflow-hidden h-[600px]", children: [
300
+ /* @__PURE__ */ jsx(TabsContent, { value: "graph", className: "mt-0", children: /* @__PURE__ */ jsx(GraphRendererProvider, { defaultRenderer: "cytoscape", children: /* @__PURE__ */ jsxs("div", { ref: rowRef, className: "flex overflow-hidden h-[600px]", children: [
282
301
  /* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsx(GraphVisualizer, {}) }),
283
- /* @__PURE__ */ jsx("div", { className: "w-[300px] flex-shrink-0 border-l", children: /* @__PURE__ */ jsx(ActionPanel, {}) })
302
+ /* @__PURE__ */ jsx(
303
+ ResizeHandle,
304
+ {
305
+ orientation: "vertical",
306
+ "aria-valuenow": panelWidth,
307
+ "aria-valuemin": 200,
308
+ "aria-valuemax": 560,
309
+ onPointerDown: startResize,
310
+ onDoubleClick: () => setPanelWidth(300)
311
+ }
312
+ ),
313
+ /* @__PURE__ */ jsxs(
314
+ "div",
315
+ {
316
+ style: { width: panelWidth },
317
+ className: "flex-shrink-0 flex flex-col min-h-0",
318
+ children: [
319
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0 overflow-hidden", children: /* @__PURE__ */ jsx(ActionPanel, {}) }),
320
+ /* @__PURE__ */ jsxs("div", { className: "shrink-0 px-4 pb-4 pt-2", children: [
321
+ /* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wide mb-2", children: "Accessible list (demo)" }),
322
+ /* @__PURE__ */ jsx(GraphA11yList, { visible: true, maxHeight: 160 })
323
+ ] })
324
+ ]
325
+ }
326
+ )
284
327
  ] }) }) }),
285
328
  /* @__PURE__ */ jsx(TabsContent, { value: "data", className: "mt-0", children: /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
286
329
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
@@ -313,4 +356,4 @@ function PlayGraph() {
313
356
  export {
314
357
  PlayGraph
315
358
  };
316
- //# sourceMappingURL=chunk-SBKZRIJC.js.map
359
+ //# sourceMappingURL=chunk-VOC5VZG2.js.map