@petrarca/sonnet-playground 0.4.0 → 0.4.1

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.
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  PlayDataComponents
3
- } from "./chunk-YEBK2TUW.js";
3
+ } from "./chunk-O2QMWJZI.js";
4
4
  import "./chunk-C2EZ2ECG.js";
5
5
  export {
6
6
  PlayDataComponents as default
7
7
  };
8
- //# sourceMappingURL=PlayDataComponents-M4SJ4XEL.js.map
8
+ //# sourceMappingURL=PlayDataComponents-W44OITT5.js.map
@@ -0,0 +1,7 @@
1
+ import {
2
+ PlayGraph
3
+ } from "./chunk-4ORSUS65.js";
4
+ export {
5
+ PlayGraph as default
6
+ };
7
+ //# sourceMappingURL=PlayGraph-ADRTDRA7.js.map
@@ -176,7 +176,7 @@ function createPlaygroundStores() {
176
176
  graphFocus,
177
177
  graphFilter,
178
178
  // Static data -- no server expansion available in the playground
179
- expandNode: async () => ({ nodes: [], edges: [] }),
179
+ expandNode: async () => ({ nodes: [], edges: [], has_more: false }),
180
180
  getNodes: async () => []
181
181
  });
182
182
  return { graphFilter, graphData, graphExploration, selection };
@@ -356,4 +356,4 @@ function PlayGraph() {
356
356
  export {
357
357
  PlayGraph
358
358
  };
359
- //# sourceMappingURL=chunk-VOC5VZG2.js.map
359
+ //# sourceMappingURL=chunk-4ORSUS65.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pages/PlayGraph.tsx"],"sourcesContent":["/**\n * Playground page for @petrarca/sonnet-graph.\n * Accessible at /playground/graph\n *\n * Demonstrates graph visualization with static mock data -- no backend required.\n * Uses the GraphStoresContext provider pattern that consumers like explorer\n * and Atlas would use to wire their own stores.\n */\n\nimport React, { useCallback, useRef, useState } from \"react\";\nimport {\n GraphVisualizer,\n ActionPanel,\n GraphA11yList,\n GraphRendererProvider,\n GraphStoresContext,\n createGraphDataStore,\n createGraphFilterStore,\n createGraphExplorationStore,\n createSelectionStore,\n createGraphFocusStore,\n enrichNodes,\n enrichEdges,\n buildColorPalette,\n type RawGraphNode,\n type RawGraphEdge,\n type WorkspaceStores,\n} from \"@petrarca/sonnet-graph\";\nimport {\n Button,\n Alert,\n AlertDescription,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n ResizeHandle,\n} from \"@petrarca/sonnet-ui\";\nimport { Play, RotateCcw } from \"lucide-react\";\n\n// ---------------------------------------------------------------------------\n// Mock data -- a small org hierarchy\n// ---------------------------------------------------------------------------\n\nconst MOCK_NODES: RawGraphNode[] = [\n {\n id_: 1,\n label_: \"Company\",\n properties_: { name: \"Acme Corp\", founded: 1985, industry: \"Technology\" },\n },\n {\n id_: 2,\n label_: \"Department\",\n properties_: { name: \"Engineering\", headcount: 42 },\n },\n {\n id_: 3,\n label_: \"Department\",\n properties_: { name: \"Marketing\", headcount: 18 },\n },\n {\n id_: 4,\n label_: \"Department\",\n properties_: { name: \"Sales\", headcount: 25 },\n },\n {\n id_: 5,\n label_: \"Person\",\n properties_: { name: \"Alice Chen\", role: \"CTO\" },\n },\n {\n id_: 6,\n label_: \"Person\",\n properties_: { name: \"Bob Smith\", role: \"VP Engineering\" },\n },\n {\n id_: 7,\n label_: \"Person\",\n properties_: { name: \"Carol Davis\", role: \"CMO\" },\n },\n {\n id_: 8,\n label_: \"Person\",\n properties_: { name: \"Dave Wilson\", role: \"VP Sales\" },\n },\n {\n id_: 9,\n label_: \"Person\",\n properties_: { name: \"Eve Johnson\", role: \"Senior Engineer\" },\n },\n {\n id_: 10,\n label_: \"Person\",\n properties_: { name: \"Frank Brown\", role: \"Product Manager\" },\n },\n {\n id_: 11,\n label_: \"Product\",\n properties_: { name: \"CloudSuite\", version: \"3.2\", status: \"GA\" },\n },\n {\n id_: 12,\n label_: \"Product\",\n properties_: { name: \"DataPipeline\", version: \"1.0\", status: \"Beta\" },\n },\n];\n\nconst MOCK_EDGES: RawGraphEdge[] = [\n {\n id_: 101,\n label_: \"HAS_DEPARTMENT\",\n start_id_: 1,\n end_id_: 2,\n properties_: {},\n },\n {\n id_: 102,\n label_: \"HAS_DEPARTMENT\",\n start_id_: 1,\n end_id_: 3,\n properties_: {},\n },\n {\n id_: 103,\n label_: \"HAS_DEPARTMENT\",\n start_id_: 1,\n end_id_: 4,\n properties_: {},\n },\n {\n id_: 104,\n label_: \"LEADS\",\n start_id_: 5,\n end_id_: 2,\n properties_: { since: 2019 },\n },\n {\n id_: 105,\n label_: \"WORKS_IN\",\n start_id_: 6,\n end_id_: 2,\n properties_: { since: 2020 },\n },\n {\n id_: 106,\n label_: \"LEADS\",\n start_id_: 7,\n end_id_: 3,\n properties_: { since: 2021 },\n },\n {\n id_: 107,\n label_: \"LEADS\",\n start_id_: 8,\n end_id_: 4,\n properties_: { since: 2018 },\n },\n {\n id_: 108,\n label_: \"WORKS_IN\",\n start_id_: 9,\n end_id_: 2,\n properties_: { since: 2022 },\n },\n {\n id_: 109,\n label_: \"WORKS_IN\",\n start_id_: 10,\n end_id_: 2,\n properties_: { since: 2021 },\n },\n { id_: 110, label_: \"REPORTS_TO\", start_id_: 6, end_id_: 5, properties_: {} },\n { id_: 111, label_: \"REPORTS_TO\", start_id_: 9, end_id_: 6, properties_: {} },\n {\n id_: 112,\n label_: \"REPORTS_TO\",\n start_id_: 10,\n end_id_: 6,\n properties_: {},\n },\n { id_: 113, label_: \"OWNS\", start_id_: 2, end_id_: 11, properties_: {} },\n { id_: 114, label_: \"OWNS\", start_id_: 2, end_id_: 12, properties_: {} },\n];\n\n// ---------------------------------------------------------------------------\n// Store setup\n//\n// Stores are created once at module load, not inside the component.\n// This avoids re-creation on re-render and removes the need for useMemo.\n// ---------------------------------------------------------------------------\n\nfunction createPlaygroundStores(): WorkspaceStores {\n const graphFilter = createGraphFilterStore();\n const graphData = createGraphDataStore();\n const selection = createSelectionStore();\n const graphFocus = createGraphFocusStore();\n const graphExploration = createGraphExplorationStore({\n graphData,\n selection,\n graphFocus,\n graphFilter,\n // Static data -- no server expansion available in the playground\n expandNode: async () => ({ nodes: [], edges: [], has_more: false }),\n getNodes: async () => [],\n });\n return { graphFilter, graphData, graphExploration, selection };\n}\n\nconst PLAYGROUND_STORES = createPlaygroundStores();\n\n// ---------------------------------------------------------------------------\n// Data helpers\n// ---------------------------------------------------------------------------\n\ninterface GraphInput {\n nodes: RawGraphNode[];\n edges: RawGraphEdge[];\n}\n\nconst INITIAL_DATA: GraphInput = { nodes: MOCK_NODES, edges: MOCK_EDGES };\n\nfunction serializeGraphData(data: GraphInput): string {\n return JSON.stringify(data, null, 2);\n}\n\nfunction validateNode(n: unknown, i: number): string | null {\n if (!n || typeof n !== \"object\") return `nodes[${i}] must be an object`;\n const node = n as Record<string, unknown>;\n if (node.id_ === undefined) return `nodes[${i}] is missing id_`;\n if (typeof node.label_ !== \"string\") return `nodes[${i}] is missing label_`;\n return null;\n}\n\nfunction validateEdge(e: unknown, i: number): string | null {\n if (!e || typeof e !== \"object\") return `edges[${i}] must be an object`;\n const edge = e as Record<string, unknown>;\n if (edge.id_ === undefined) return `edges[${i}] is missing id_`;\n if (typeof edge.label_ !== \"string\") return `edges[${i}] is missing label_`;\n if (edge.start_id_ === undefined) return `edges[${i}] is missing start_id_`;\n if (edge.end_id_ === undefined) return `edges[${i}] is missing end_id_`;\n return null;\n}\n\n/** Validates that parsed JSON is a usable GraphInput. Returns an error string or null. */\nfunction validateGraphInput(value: unknown): string | null {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return \"JSON must be an object with nodes and edges arrays\";\n }\n const obj = value as Record<string, unknown>;\n if (!Array.isArray(obj.nodes)) return '\"nodes\" must be an array';\n if (!Array.isArray(obj.edges)) return '\"edges\" must be an array';\n for (const [i, n] of (obj.nodes as unknown[]).entries()) {\n const err = validateNode(n, i);\n if (err) return err;\n }\n for (const [i, e] of (obj.edges as unknown[]).entries()) {\n const err = validateEdge(e, i);\n if (err) return err;\n }\n return null;\n}\n\nfunction loadIntoStore(stores: WorkspaceStores, data: GraphInput) {\n const labelCounts: Record<string, number> = {};\n for (const n of data.nodes) {\n labelCounts[n.label_] = (labelCounts[n.label_] ?? 0) + 1;\n }\n const palette = buildColorPalette(labelCounts);\n const nodes = enrichNodes(data.nodes, palette);\n const edges = enrichEdges(data.edges, palette);\n stores.graphFilter.getState().resetFilters();\n stores.graphData.getState().setQueryData(nodes, edges, {\n nodes: nodes.length,\n edges: edges.length,\n });\n // Signal renderers to re-fit layout after data change\n stores.graphFilter.getState().notifyDataChange();\n}\n\n// Load initial data immediately -- no effect needed, no empty render cycle\nloadIntoStore(PLAYGROUND_STORES, INITIAL_DATA);\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport default function PlayGraph(): React.ReactElement {\n const [jsonText, setJsonText] = useState(() =>\n serializeGraphData(INITIAL_DATA),\n );\n const [parseError, setParseError] = useState<string | null>(null);\n\n // Resizable side panel (demonstrates ResizeHandle).\n const [panelWidth, setPanelWidth] = useState(300);\n const rowRef = useRef<HTMLDivElement>(null);\n const startResize = useCallback((e: React.PointerEvent) => {\n e.preventDefault();\n const target = e.currentTarget as HTMLElement;\n target.setPointerCapture(e.pointerId);\n const move = (ev: PointerEvent) => {\n const right = rowRef.current?.getBoundingClientRect().right ?? 0;\n setPanelWidth(Math.min(560, Math.max(200, right - ev.clientX)));\n };\n const up = () => {\n window.removeEventListener(\"pointermove\", move);\n window.removeEventListener(\"pointerup\", up);\n };\n window.addEventListener(\"pointermove\", move);\n window.addEventListener(\"pointerup\", up);\n }, []);\n\n const handleApply = useCallback(() => {\n let parsed: unknown;\n try {\n parsed = JSON.parse(jsonText);\n } catch (e) {\n setParseError(e instanceof Error ? e.message : \"Invalid JSON\");\n return;\n }\n const validationError = validateGraphInput(parsed);\n if (validationError) {\n setParseError(validationError);\n return;\n }\n setParseError(null);\n loadIntoStore(PLAYGROUND_STORES, parsed as GraphInput);\n }, [jsonText]);\n\n const handleReset = useCallback(() => {\n setJsonText(serializeGraphData(INITIAL_DATA));\n setParseError(null);\n loadIntoStore(PLAYGROUND_STORES, INITIAL_DATA);\n }, []);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\") {\n e.preventDefault();\n handleApply();\n }\n },\n [handleApply],\n );\n\n return (\n <div className=\"space-y-6\">\n <div>\n <h1>Graph Visualization</h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n Interactive property graph with dual renderer support. Edit the JSON\n data and apply to re-render.\n </p>\n </div>\n <GraphStoresContext.Provider value={PLAYGROUND_STORES}>\n <Tabs defaultValue=\"graph\" className=\"space-y-3\">\n <TabsList>\n <TabsTrigger value=\"graph\">Graph</TabsTrigger>\n <TabsTrigger value=\"data\">Data</TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"graph\" className=\"mt-0\">\n <GraphRendererProvider defaultRenderer=\"cytoscape\">\n <div ref={rowRef} className=\"flex overflow-hidden h-[600px]\">\n <div className=\"flex-1 min-w-0\">\n <GraphVisualizer />\n </div>\n {/* Drag to resize the side panel (ResizeHandle demo). */}\n <ResizeHandle\n orientation=\"vertical\"\n aria-valuenow={panelWidth}\n aria-valuemin={200}\n aria-valuemax={560}\n onPointerDown={startResize}\n onDoubleClick={() => setPanelWidth(300)}\n />\n <div\n style={{ width: panelWidth }}\n className=\"flex-shrink-0 flex flex-col min-h-0\"\n >\n <div className=\"flex-1 min-h-0 overflow-hidden\">\n <ActionPanel />\n </div>\n {/* Accessible DOM mirror (playground demo only): keyboard / AT /\n automation can select the same nodes/edges as the canvas.\n Real consumers render it sr-only (omit `visible`). */}\n <div className=\"shrink-0 px-4 pb-4 pt-2\">\n <p className=\"text-xs font-medium text-muted-foreground uppercase tracking-wide mb-2\">\n Accessible list (demo)\n </p>\n <GraphA11yList visible maxHeight={160} />\n </div>\n </div>\n </div>\n </GraphRendererProvider>\n </TabsContent>\n\n <TabsContent value=\"data\" className=\"mt-0\">\n <div className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <Button size=\"sm\" onClick={handleApply}>\n <Play className=\"h-4 w-4 mr-1\" />\n Apply\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={handleReset}>\n <RotateCcw className=\"h-4 w-4 mr-1\" />\n Reset\n </Button>\n <span className=\"text-xs text-muted-foreground ml-2\">\n Cmd+Enter to apply\n </span>\n </div>\n {parseError && (\n <Alert variant=\"destructive\">\n <AlertDescription>{parseError}</AlertDescription>\n </Alert>\n )}\n <textarea\n value={jsonText}\n onChange={(e) => setJsonText(e.target.value)}\n onKeyDown={handleKeyDown}\n spellCheck={false}\n className=\"w-full h-[600px] font-mono text-xs p-3 border rounded-lg bg-muted/30 resize-y focus:outline-none focus:ring-2 focus:ring-ring\"\n />\n </div>\n </TabsContent>\n </Tabs>\n </GraphStoresContext.Provider>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -18,7 +18,8 @@ import {
18
18
  EntitySelect,
19
19
  EntityTable,
20
20
  createRenderer,
21
- EntityTree
21
+ EntityTree,
22
+ PropertyList
22
23
  } from "@petrarca/sonnet-ui";
23
24
  import { FormTextarea } from "@petrarca/sonnet-forms";
24
25
  import { JsonEditor } from "@petrarca/sonnet-ui/json-editor";
@@ -719,9 +720,58 @@ function PlayDataComponents() {
719
720
  variant: "card",
720
721
  children: /* @__PURE__ */ jsx(EntityTreeDemo, {})
721
722
  }
723
+ ),
724
+ /* @__PURE__ */ jsx(
725
+ PlaygroundSection,
726
+ {
727
+ title: "PropertyList",
728
+ description: "Read-only, schema-OPTIONAL property display used by detail panels and graph node/edge cards. Stacked layout (uppercase muted key above value), click-to-copy. With no schema, values render by JS shape; an optional per-property schema refines rendering (date/datetime/boolean/number/x-ui-cell).",
729
+ variant: "card",
730
+ children: /* @__PURE__ */ jsx(PropertyListDemo, {})
731
+ }
722
732
  )
723
733
  ] });
724
734
  }
735
+ var PROPERTY_LIST_SAMPLE = {
736
+ name: "lauro_server.api",
737
+ description: "Build tools (Maven, Gradle, Webpack, Vite, etc.)",
738
+ is_component: false,
739
+ tags: ["python", "fastapi", "graph"],
740
+ created_at: "2026-01-15T09:30:00Z",
741
+ empty_value: null,
742
+ // Real nested object -> collapsed JSON tree.
743
+ config: {
744
+ retries: 3,
745
+ timeout_s: 30,
746
+ endpoints: ["/a", "/b"],
747
+ nested: { enabled: true }
748
+ },
749
+ // Long text -> clamp + show more.
750
+ notes: "This module exposes the public API surface. It aggregates routers from submodules, wires middleware, and configures CORS. See the architecture doc for the full request lifecycle and the list of mounted sub-applications."
751
+ };
752
+ var PROPERTY_LIST_SCHEMA = {
753
+ is_component: { type: "boolean" },
754
+ created_at: { type: "string", format: "date-time" }
755
+ };
756
+ function PropertyListDemo() {
757
+ return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-6 sm:grid-cols-2", children: [
758
+ /* @__PURE__ */ jsxs(Card, { className: "p-4", children: [
759
+ /* @__PURE__ */ jsx("p", { className: "mb-3 text-xs font-medium uppercase tracking-wide text-muted-foreground", children: "No schema (value-shape)" }),
760
+ /* @__PURE__ */ jsx(PropertyList, { properties: PROPERTY_LIST_SAMPLE })
761
+ ] }),
762
+ /* @__PURE__ */ jsxs(Card, { className: "p-4", children: [
763
+ /* @__PURE__ */ jsx("p", { className: "mb-3 text-xs font-medium uppercase tracking-wide text-muted-foreground", children: "With optional schema (boolean / date-time)" }),
764
+ /* @__PURE__ */ jsx(
765
+ PropertyList,
766
+ {
767
+ properties: PROPERTY_LIST_SAMPLE,
768
+ propertySchemas: PROPERTY_LIST_SCHEMA,
769
+ showHeader: true
770
+ }
771
+ )
772
+ ] })
773
+ ] });
774
+ }
725
775
  var OrgSchema = z.object({
726
776
  name: z.string().meta({ title: "Name", "x-ui-column": { order: 0 } }),
727
777
  type: z.string().meta({ title: "Type", "x-ui-column": { order: 1 } }),
@@ -828,4 +878,4 @@ function EntityTreeDemo() {
828
878
  export {
829
879
  PlayDataComponents
830
880
  };
831
- //# sourceMappingURL=chunk-YEBK2TUW.js.map
881
+ //# sourceMappingURL=chunk-O2QMWJZI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pages/PlayDataComponents.tsx"],"sourcesContent":["/**\n * Playground page for SearchInput, EntitySelect, EntityTable, and EntityTree.\n * Accessible at /playground/data-components\n *\n * Six sections:\n * 1. Simple mode -- single freetext search, no field picker\n * 2. Faceted mode -- two-column: schema editor left, live search + output right\n * 3. EntityTable -- static sample data wired to faceted SearchInput\n * 4. Local renderers -- same data with x- prefixed custom cell renderers\n * 5. EntitySelect -- async searchable select backed by a static mock fetcher\n * 6. EntityTree -- schema-driven tree with static nested data\n */\n\nimport React, { useState, useMemo, useCallback } from \"react\";\nimport { ArrowRight, ArrowUp } from \"lucide-react\";\nimport {\n Badge,\n Button,\n Card,\n SimpleTooltip,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n SearchInput,\n type SearchMode,\n EntitySelect,\n EntityTable,\n createRenderer,\n EntityTree,\n PropertyList,\n type TreeNode,\n type TableUiSchema,\n} from \"@petrarca/sonnet-ui\";\nimport type { JsonSchemaProperty } from \"@petrarca/sonnet-core/schema\";\nimport { FormTextarea } from \"@petrarca/sonnet-forms\";\nimport { JsonEditor } from \"@petrarca/sonnet-ui/json-editor\";\nimport { PlaygroundSection } from \"../PlaygroundSection\";\nimport {\n EMPTY_FILTER,\n flattenFilterExpr,\n isEmptyFilterExpr,\n serializeFilterExpr,\n type FilterExpr,\n} from \"@petrarca/sonnet-core/search\";\nimport { toJsonSchema, type JsonSchema } from \"@petrarca/sonnet-core/schema\";\nimport { useTreeExpansion } from \"@petrarca/sonnet-core/hooks\";\nimport type { EntityOptionFetcher } from \"@petrarca/sonnet-core/entityOptions\";\nimport { z } from \"zod/v4\";\n\n// Static mock patient data for the EntitySelect playground demo.\n// Uses a local fetcher so the playground has no dependency on a live API.\nconst MOCK_PATIENTS = [\n { value: \"pat_001\", label: \"Alice Hartmann\" },\n { value: \"pat_002\", label: \"Bob Nguyen\" },\n { value: \"pat_003\", label: \"Carol Smith\" },\n { value: \"pat_004\", label: \"David Okafor\" },\n { value: \"pat_005\", label: \"Eva Larsson\" },\n { value: \"pat_006\", label: \"Frank Torres\" },\n { value: \"pat_007\", label: \"Grace Kim\" },\n { value: \"pat_008\", label: \"Henry Bauer\" },\n];\n\nconst patientFetcher: EntityOptionFetcher = ({ search } = {}) => {\n const q = search?.toLowerCase() ?? \"\";\n const results = q\n ? MOCK_PATIENTS.filter((p) => p.label.toLowerCase().includes(q))\n : MOCK_PATIENTS;\n return Promise.resolve(results);\n};\n\ninterface SampleRow {\n id: string;\n name: string;\n status: \"active\" | \"inactive\" | \"pending\";\n role: string;\n joined: string;\n}\n\nconst ALL_ROWS: SampleRow[] = [\n {\n id: \"u-001\",\n name: \"Alice Hartmann\",\n status: \"active\",\n role: \"admin\",\n joined: \"2024-01-15\",\n },\n {\n id: \"u-002\",\n name: \"Bob Nguyen\",\n status: \"active\",\n role: \"editor\",\n joined: \"2024-02-03\",\n },\n {\n id: \"u-003\",\n name: \"Carol Smith\",\n status: \"inactive\",\n role: \"viewer\",\n joined: \"2024-03-20\",\n },\n {\n id: \"u-004\",\n name: \"David Okafor\",\n status: \"pending\",\n role: \"editor\",\n joined: \"2024-04-11\",\n },\n {\n id: \"u-005\",\n name: \"Eva Larsson\",\n status: \"active\",\n role: \"admin\",\n joined: \"2024-05-08\",\n },\n {\n id: \"u-006\",\n name: \"Frank Torres\",\n status: \"inactive\",\n role: \"viewer\",\n joined: \"2024-06-22\",\n },\n {\n id: \"u-007\",\n name: \"Grace Kim\",\n status: \"active\",\n role: \"editor\",\n joined: \"2024-07-14\",\n },\n {\n id: \"u-008\",\n name: \"Henry Bauer\",\n status: \"pending\",\n role: \"viewer\",\n joined: \"2024-08-30\",\n },\n];\n\nconst STATUS_COLOR = {\n active: \"green\",\n inactive: \"violet\",\n pending: \"yellow\",\n} as const;\n\nconst PlaygroundFacets = z.object({\n search: z.string().meta({ \"x-ui-title\": \"Name\" }),\n status: z\n .enum([\"active\", \"inactive\", \"pending\"])\n .optional()\n .meta({\n \"x-ui-title\": \"Status\",\n \"x-ui-options\": {\n enumNames: {\n active: \"Active\",\n inactive: \"Inactive\",\n pending: \"Pending\",\n },\n },\n }),\n role: z.string().optional().meta({ \"x-ui-title\": \"Role\" }),\n});\n\nconst SEARCH_FACET_SCHEMA = toJsonSchema(PlaygroundFacets);\n\nconst SAMPLE_SCHEMA: JsonSchema = {\n title: \"User\",\n type: \"object\",\n properties: {\n name: {\n type: \"string\",\n title: \"Name\",\n \"x-ui-column\": { order: 0 },\n \"x-ui-cell\": \"bold\",\n },\n status: {\n type: \"string\",\n title: \"Status\",\n \"x-ui-column\": { order: 1 },\n \"x-ui-cell\": \"badge\",\n \"x-ui-cell-options\": { colors: STATUS_COLOR },\n },\n role: {\n type: \"string\",\n title: \"Role\",\n \"x-ui-column\": { order: 2 },\n \"x-ui-cell\": \"muted\",\n },\n id: {\n type: \"string\",\n title: \"ID\",\n \"x-ui-column\": { order: 3 },\n \"x-ui-cell\": \"code\",\n },\n joined: {\n type: \"string\",\n format: \"date\",\n title: \"Joined\",\n \"x-ui-column\": { order: 4 },\n },\n },\n};\n\nconst SAMPLE_UI_SCHEMA: TableUiSchema = {}; // mutable via the live schema editor below\n\n// Local renderer demo: three x- prefixed renderers using the same SampleRow data.\nconst ROLE_ICONS: Record<string, string> = {\n admin: \"A\",\n editor: \"E\",\n viewer: \"V\",\n};\n\nconst CUSTOM_RENDERERS = {\n // Extract initials from the name, display as avatar circle + name.\n \"x-play-initials\": createRenderer<SampleRow>((row) => {\n const initials = row.name\n .split(\" \")\n .map((w) => w[0])\n .join(\"\");\n return (\n <span className=\"inline-flex items-center gap-2\">\n <span className=\"inline-flex items-center justify-center h-7 w-7 rounded-full bg-muted text-xs font-medium shrink-0\">\n {initials}\n </span>\n <span className=\"font-medium\">{row.name}</span>\n </span>\n );\n }),\n\n // Role with a letter prefix read from options.icons.\n \"x-play-role-icon\": createRenderer<SampleRow>((row, options) => {\n const icons = (options.icons as Record<string, string>) ?? {};\n const icon = icons[row.role] ?? \"?\";\n return (\n <span>\n <span className=\"inline-flex items-center justify-center h-5 w-5 rounded bg-muted text-xs font-mono mr-1.5\">\n {icon}\n </span>\n {row.role}\n </span>\n );\n }),\n\n // Compute days since joined, color-coded by threshold from options.\n \"x-play-tenure\": createRenderer<SampleRow>((row, options) => {\n const threshold = (options.recentDays as number) ?? 365;\n const days = Math.floor(\n (Date.now() - new Date(row.joined).getTime()) / 86_400_000,\n );\n const isRecent = days < threshold;\n return (\n <span className={isRecent ? \"text-primary\" : \"text-muted-foreground\"}>\n {days}d\n </span>\n );\n }),\n};\n\nconst CUSTOM_RENDERER_SCHEMA: JsonSchema = {\n title: \"User (custom renderers)\",\n type: \"object\",\n properties: {\n name: {\n type: \"string\",\n title: \"Name\",\n \"x-ui-column\": { order: 0 },\n \"x-ui-cell\": \"x-play-initials\",\n },\n role: {\n type: \"string\",\n title: \"Role\",\n \"x-ui-column\": { order: 1 },\n \"x-ui-cell\": \"x-play-role-icon\",\n \"x-ui-cell-options\": { icons: ROLE_ICONS },\n },\n status: {\n type: \"string\",\n title: \"Status\",\n \"x-ui-column\": { order: 2 },\n \"x-ui-cell\": \"badge\",\n \"x-ui-cell-options\": { colors: STATUS_COLOR },\n },\n joined: {\n type: \"string\",\n title: \"Tenure\",\n \"x-ui-column\": { order: 3 },\n \"x-ui-cell\": \"x-play-tenure\",\n \"x-ui-cell-options\": { recentDays: 500 },\n },\n id: {\n type: \"string\",\n title: \"ID\",\n \"x-ui-column\": { order: 4 },\n \"x-ui-cell\": \"code\",\n },\n },\n};\n\n// Sentinel value meaning \"schema was reloaded, next submit resets the counter to 0\".\nconst SUBMIT_COUNT_RESET = -1;\n\n// Presets for the searchFields demo (Section 1b). Uses the same user domain\n// as the rest of the playground (name, role, status).\nconst SEARCH_FIELD_PRESETS: { label: string; fields: string[] }[] = [\n { label: \"name, role\", fields: [\"name\", \"role\"] },\n { label: \"name (single)\", fields: [\"name\"] },\n { label: \"name, role, status\", fields: [\"name\", \"role\", \"status\"] },\n];\n\n// Reusable toggle-button strip for playground controls.\n// Renders a label followed by a set of pill buttons. className applies to\n// the wrapping fragment's implicit container -- callers place it inside a\n// flex row, so use ml-* on the caller side via the containerClassName prop.\nfunction ToggleStrip<T extends string | number>({\n label,\n options,\n value,\n onChange,\n format,\n containerClassName,\n}: {\n label: string;\n options: readonly T[];\n value: T;\n onChange: (v: T) => void;\n format?: (v: T) => string;\n containerClassName?: string;\n}) {\n const fmt = format ?? String;\n return (\n <div className={`flex items-center gap-3 ${containerClassName ?? \"\"}`}>\n <span className=\"text-xs text-muted-foreground\">{label}:</span>\n {options.map((opt) => (\n <button\n key={String(opt)}\n type=\"button\"\n onClick={() => onChange(opt)}\n className={[\n \"px-3 py-1 rounded-full text-xs font-medium transition-colors\",\n value === opt\n ? \"bg-primary text-primary-foreground\"\n : \"bg-muted text-muted-foreground hover:text-foreground\",\n ].join(\" \")}\n >\n {fmt(opt)}\n </button>\n ))}\n </div>\n );\n}\n\nconst MODE_OPTIONS = [\"explicit\", \"debounce\"] as const;\nconst MODE_LABELS: Record<string, string> = {\n explicit: \"Explicit (Enter)\",\n debounce: \"Debounce (300 ms)\",\n};\nconst MIN_CHARS_OPTIONS = [0, 1, 2, 3] as const;\nconst FIELD_PRESET_INDICES = SEARCH_FIELD_PRESETS.map(\n (_, i) => i,\n) as readonly number[];\n\nfunction FilterExprInspector({ expr }: { expr: FilterExpr }) {\n return (\n <pre className=\"mt-3 rounded-md bg-muted px-4 py-3 text-xs overflow-auto max-h-40\">\n {JSON.stringify(expr, null, 2)}\n </pre>\n );\n}\n\nfunction FlatTermsInspector({ expr }: { expr: FilterExpr }) {\n const terms = flattenFilterExpr(expr);\n return (\n <pre className=\"mt-3 rounded-md bg-muted px-4 py-3 text-xs overflow-auto max-h-40\">\n {JSON.stringify(terms, null, 2)}\n </pre>\n );\n}\n\n/** Playground sandbox for SearchInput, EntitySelect, and EntityTable. */\nexport default function PlayDataComponents(): React.ReactElement {\n // Section 1: simple mode\n const [simpleExpr, setSimpleExpr] = useState<FilterExpr>(EMPTY_FILTER);\n const [simpleMode, setSimpleMode] = useState<SearchMode>(\"explicit\");\n const [simpleMinChars, setSimpleMinChars] = useState(0);\n\n // Section 1b: searchFields mode (multi-field OR)\n const [fieldsExpr, setFieldsExpr] = useState<FilterExpr>(EMPTY_FILTER);\n const [fieldsMode, setFieldsMode] = useState<SearchMode>(\"explicit\");\n const [fieldsMinChars, setFieldsMinChars] = useState(0);\n const [fieldsPresetIdx, setFieldsPresetIdx] = useState(0);\n const activeSearchFields = SEARCH_FIELD_PRESETS[fieldsPresetIdx].fields;\n\n // Section 2: faceted mode with live schema editor\n const [facetedExpr, setFacetedExpr] = useState<FilterExpr>(EMPTY_FILTER);\n const [facetedSubmitCount, setFacetedSubmitCount] = useState(0);\n const handleFacetedChange = useCallback((expr: FilterExpr) => {\n setFacetedExpr(expr);\n setFacetedSubmitCount((n) => n + 1);\n }, []);\n const [schemaText, setSchemaText] = useState(() =>\n JSON.stringify(toJsonSchema(PlaygroundFacets), null, 2),\n );\n const [schemaError, setSchemaError] = useState(\"\");\n const [activeSchema, setActiveSchema] =\n useState<JsonSchema>(SEARCH_FACET_SCHEMA);\n\n const handleSchemaTextChange = useCallback((value: string) => {\n setSchemaText(value);\n try {\n JSON.parse(value);\n setSchemaError(\"\");\n } catch {\n setSchemaError(\"Invalid JSON\");\n }\n }, []);\n\n const handleLoadSchema = useCallback(() => {\n try {\n const parsed = JSON.parse(schemaText) as JsonSchema;\n setActiveSchema(parsed);\n setFacetedExpr(EMPTY_FILTER);\n setFacetedSubmitCount(SUBMIT_COUNT_RESET);\n setSchemaError(\"\");\n } catch {\n setSchemaError(\"Invalid JSON -- cannot load\");\n }\n }, [schemaText]);\n\n // Section 3: schema + UI schema editors for the table.\n const [tableSchemaText, setTableSchemaText] = useState(() =>\n JSON.stringify(SAMPLE_SCHEMA, null, 2),\n );\n const [tableUiSchemaText, setTableUiSchemaText] = useState(() =>\n JSON.stringify(SAMPLE_UI_SCHEMA, null, 2),\n );\n const [tableSchemaError, setTableSchemaError] = useState(\"\");\n const [activeTableSchema, setActiveTableSchema] =\n useState<JsonSchema>(SAMPLE_SCHEMA);\n const [activeTableUiSchema, setActiveTableUiSchema] =\n useState<TableUiSchema>(SAMPLE_UI_SCHEMA);\n const [tableSchemaTab, setTableSchemaTab] = useState(\"schema\");\n\n const handleTableSchemaTextChange = useCallback((value: string) => {\n setTableSchemaText(value);\n try {\n JSON.parse(value);\n setTableSchemaError(\"\");\n } catch {\n setTableSchemaError(\"Invalid JSON\");\n }\n }, []);\n\n const handleTableUiSchemaTextChange = useCallback((value: string) => {\n setTableUiSchemaText(value);\n try {\n JSON.parse(value);\n setTableSchemaError(\"\");\n } catch {\n setTableSchemaError(\"Invalid JSON\");\n }\n }, []);\n\n const handleApplyTableSchema = useCallback(() => {\n try {\n const schema = JSON.parse(tableSchemaText) as JsonSchema;\n const uiSchema = JSON.parse(tableUiSchemaText) as TableUiSchema;\n setActiveTableSchema(schema);\n setActiveTableUiSchema(uiSchema);\n setTableSchemaError(\"\");\n } catch {\n setTableSchemaError(\"Invalid JSON -- cannot apply\");\n }\n }, [tableSchemaText, tableUiSchemaText]);\n\n // Section 3: faceted mode wired to EntityTable.\n // onChange fires only on submit -- filteredRows updates when the user presses Enter.\n const [tableExpr, setTableExpr] = useState<FilterExpr>(EMPTY_FILTER);\n\n const filteredRows = useMemo(() => {\n const terms = flattenFilterExpr(tableExpr);\n if (terms.length === 0) return ALL_ROWS;\n\n return ALL_ROWS.filter((row) =>\n terms.every(({ key, value }) => {\n const v = value.toLowerCase();\n if (key === \"status\") return row.status.toLowerCase().includes(v);\n if (key === \"role\") return row.role.toLowerCase().includes(v);\n // default: search by name\n return row.name.toLowerCase().includes(v);\n }),\n );\n }, [tableExpr]);\n\n const tableData = useMemo(\n () => ({\n data: filteredRows,\n meta: {\n total: filteredRows.length,\n limit: filteredRows.length,\n offset: 0,\n has_next: false,\n has_prev: false,\n },\n }),\n [filteredRows],\n );\n\n // Section 5: EntitySelect\n const [selectedPatient, setSelectedPatient] = useState<string | null>(null);\n\n return (\n <div className=\"w-full max-w-4xl space-y-6\">\n <div>\n <h1>Data Components</h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n Interactive sandbox for SearchInput (simple, multi-field, faceted),\n EntityTable (with schema editor and custom renderers), EntitySelect,\n and EntityTree.\n </p>\n </div>\n\n {/* Section 1: simple mode */}\n <PlaygroundSection\n title=\"SearchInput — simple mode\"\n description=\"No fields prop. Produces a single search term under the key 'search'.\"\n variant=\"card\"\n >\n <div className=\"flex flex-wrap gap-4 mb-3\">\n <ToggleStrip\n label=\"Mode\"\n options={MODE_OPTIONS}\n value={simpleMode}\n onChange={(m) => {\n setSimpleMode(m);\n setSimpleExpr(EMPTY_FILTER);\n }}\n format={(m) => MODE_LABELS[m]}\n />\n <ToggleStrip\n label=\"Min chars\"\n options={MIN_CHARS_OPTIONS}\n value={simpleMinChars}\n onChange={setSimpleMinChars}\n format={(n) => (n === 0 ? \"off\" : String(n))}\n />\n </div>\n <SearchInput\n value={simpleExpr}\n onChange={setSimpleExpr}\n mode={simpleMode}\n minChars={simpleMinChars}\n placeholder=\"Search...\"\n className=\"max-w-sm\"\n />\n <FlatTermsInspector expr={simpleExpr} />\n </PlaygroundSection>\n\n {/* Section 1b: searchFields mode */}\n <PlaygroundSection\n title=\"SearchInput — searchFields (multi-field OR)\"\n description=\"Produces a FilterOr with one term per field. Toggle field sets, mode, and minChars to explore different behaviours.\"\n variant=\"card\"\n >\n <div className=\"flex flex-wrap gap-4 mb-3\">\n <ToggleStrip\n label=\"Fields\"\n options={FIELD_PRESET_INDICES}\n value={fieldsPresetIdx}\n onChange={(idx) => {\n setFieldsPresetIdx(idx);\n setFieldsExpr(EMPTY_FILTER);\n }}\n format={(idx) => SEARCH_FIELD_PRESETS[idx].label}\n />\n <ToggleStrip\n label=\"Mode\"\n options={MODE_OPTIONS}\n value={fieldsMode}\n onChange={(m) => {\n setFieldsMode(m);\n setFieldsExpr(EMPTY_FILTER);\n }}\n format={(m) => MODE_LABELS[m]}\n />\n <ToggleStrip\n label=\"Min chars\"\n options={MIN_CHARS_OPTIONS}\n value={fieldsMinChars}\n onChange={setFieldsMinChars}\n format={(n) => (n === 0 ? \"off\" : String(n))}\n />\n </div>\n <SearchInput\n value={fieldsExpr}\n onChange={setFieldsExpr}\n searchFields={activeSearchFields}\n mode={fieldsMode}\n minChars={fieldsMinChars}\n placeholder={`Search by ${activeSearchFields.join(\" or \")}...`}\n className=\"max-w-sm\"\n />\n <div className=\"mt-3 space-y-2\">\n <p className=\"text-xs text-muted-foreground\">\n searchFields: [{activeSearchFields.map((f) => `\"${f}\"`).join(\", \")}]\n </p>\n <p className=\"text-xs text-muted-foreground\">FilterExpr AST:</p>\n <FilterExprInspector expr={fieldsExpr} />\n {!isEmptyFilterExpr(fieldsExpr) && (\n <>\n <p className=\"text-xs text-muted-foreground\">\n Serialized q= string:\n </p>\n <pre className=\"rounded-md bg-muted px-4 py-3 text-xs overflow-auto\">\n {serializeFilterExpr(fieldsExpr)}\n </pre>\n </>\n )}\n </div>\n </PlaygroundSection>\n\n {/* Section 2: faceted mode -- two-column schema editor */}\n <PlaygroundSection\n title=\"SearchInput — faceted mode\"\n description=\"Edit the JSON Schema on the left and load it into the search input. Add chips by picking a field and typing a value. Press Enter on empty input to fire onChange.\"\n variant=\"card\"\n >\n <div className=\"flex gap-4 items-start\">\n {/* Left: schema editor */}\n <Card className=\"flex-1 min-w-0 p-3 flex flex-col gap-2\">\n <p className=\"text-xs font-medium text-muted-foreground\">\n JSON Schema\n </p>\n {schemaError && (\n <Badge variant=\"destructive\" className=\"text-xs self-start\">\n {schemaError}\n </Badge>\n )}\n <FormTextarea\n value={schemaText}\n onChange={(e) => handleSchemaTextChange(e.target.value)}\n className=\"font-mono text-xs\"\n rows={18}\n />\n </Card>\n\n {/* Load button */}\n <div className=\"flex items-center self-center\">\n <SimpleTooltip label=\"Load schema into search\">\n <Button\n variant=\"default\"\n size=\"icon\"\n onClick={handleLoadSchema}\n disabled={!!schemaError}\n >\n <ArrowRight size={18} />\n </Button>\n </SimpleTooltip>\n </div>\n\n {/* Right: live search + output */}\n <Card className=\"flex-1 min-w-0 p-3 flex flex-col gap-3\">\n <p className=\"text-xs font-medium text-muted-foreground\">\n Live search\n </p>\n <SearchInput\n value={facetedExpr}\n onChange={handleFacetedChange}\n schema={activeSchema}\n mode=\"explicit\"\n placeholder=\"Add filter...\"\n />\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span>onChange fired:</span>\n <span className=\"font-mono font-medium text-foreground\">\n {facetedSubmitCount}x\n </span>\n </div>\n <FilterExprInspector expr={facetedExpr} />\n </Card>\n </div>\n </PlaygroundSection>\n\n {/* Section 3: faceted mode + EntityTable wired together */}\n <PlaygroundSection\n title=\"EntityTable with SearchInput\"\n description=\"Faceted search wired to EntityTable. onChange fires only on submit (Enter on empty input) -- table filters when the user presses Enter. Edit the JSON Schema or UI Schema below and press Apply to see column changes live.\"\n variant=\"card\"\n >\n <SearchInput\n value={tableExpr}\n onChange={setTableExpr}\n schema={SEARCH_FACET_SCHEMA}\n mode=\"explicit\"\n placeholder=\"Filter users... (press Enter to apply)\"\n className=\"mb-4 max-w-sm\"\n />\n <EntityTable<SampleRow>\n schema={activeTableSchema}\n uiSchema={activeTableUiSchema}\n data={tableData}\n isLoading={false}\n isError={false}\n entityLabel=\"users\"\n isFiltered={!isEmptyFilterExpr(tableExpr)}\n />\n\n {/* Schema editor below the table */}\n <div className=\"mt-4\">\n <Card className=\"border shadow-sm p-4 flex flex-col\">\n <div className=\"flex items-center justify-between mb-2\">\n <Tabs\n value={tableSchemaTab}\n onValueChange={setTableSchemaTab}\n className=\"flex flex-col flex-1\"\n >\n <div className=\"flex items-center justify-between\">\n <TabsList>\n <TabsTrigger value=\"schema\">JSON Schema</TabsTrigger>\n <TabsTrigger value=\"uischema\">UI Schema</TabsTrigger>\n </TabsList>\n <div className=\"flex items-center gap-2\">\n {tableSchemaError && (\n <Badge variant=\"destructive\" className=\"text-xs\">\n {tableSchemaError}\n </Badge>\n )}\n <SimpleTooltip label=\"Apply schema to table above\">\n <Button\n variant=\"default\"\n size=\"icon\"\n onClick={handleApplyTableSchema}\n disabled={!!tableSchemaError}\n >\n <ArrowUp size={18} />\n </Button>\n </SimpleTooltip>\n </div>\n </div>\n <TabsContent value=\"schema\" className=\"mt-2\">\n <JsonEditor\n value={tableSchemaText}\n editablePaths={[\"/\"]}\n onChange={handleTableSchemaTextChange}\n height=\"280px\"\n className=\"rounded-md border overflow-hidden\"\n />\n </TabsContent>\n <TabsContent value=\"uischema\" className=\"mt-2\">\n <JsonEditor\n value={tableUiSchemaText}\n editablePaths={[\"/\"]}\n onChange={handleTableUiSchemaTextChange}\n height=\"280px\"\n className=\"rounded-md border overflow-hidden\"\n />\n </TabsContent>\n </Tabs>\n </div>\n </Card>\n </div>\n </PlaygroundSection>\n\n {/* Section 4: Local renderers demo */}\n <PlaygroundSection\n title=\"EntityTable with Local Renderers\"\n description=\"Same sample data rendered with x- prefixed local renderers passed via the renderers prop. The schema is pure data -- renderer functions live in code and are resolved by name. Three custom renderers: x-play-initials (avatar from name), x-play-role-icon (letter prefix from options), x-play-tenure (computed days with threshold).\"\n variant=\"card\"\n >\n <EntityTable<SampleRow>\n schema={CUSTOM_RENDERER_SCHEMA}\n renderers={CUSTOM_RENDERERS}\n data={{\n data: ALL_ROWS,\n meta: {\n total: ALL_ROWS.length,\n limit: ALL_ROWS.length,\n offset: 0,\n has_next: false,\n has_prev: false,\n },\n }}\n isLoading={false}\n isError={false}\n entityLabel=\"users\"\n />\n </PlaygroundSection>\n\n {/* Section 5: EntitySelect -- searchable select with mock fetcher */}\n <PlaygroundSection\n title=\"EntitySelect\"\n description=\"Searchable single-select backed by a static mock patient fetcher. Search text is filtered client-side. Available as a form widget via x-ui-widget: 'entity-select'.\"\n variant=\"card\"\n >\n <div className=\"flex gap-6 items-start\">\n <EntitySelect\n fetcher={patientFetcher}\n queryKey=\"playground-patients\"\n value={selectedPatient}\n onChange={setSelectedPatient}\n label=\"Patient\"\n placeholder=\"Select patient...\"\n searchPlaceholder=\"Search patients...\"\n className=\"max-w-xs\"\n />\n <Card className=\"flex-1 min-w-0 p-3\">\n <p className=\"text-xs font-medium text-muted-foreground mb-2\">\n Selected value\n </p>\n <pre className=\"rounded-md bg-muted px-4 py-3 text-xs overflow-auto\">\n {JSON.stringify(selectedPatient, null, 2)}\n </pre>\n </Card>\n </div>\n </PlaygroundSection>\n\n {/* Section 6: EntityTree -- schema-driven tree with static nested data */}\n <PlaygroundSection\n title=\"EntityTree\"\n description=\"Schema-driven tree component built on TreeView. Columns are resolved from a JSON Schema using the same resolveColumns pipeline as EntityTable. Supports expand/collapse, row selection, loading/error/empty states, and custom cell renderers.\"\n variant=\"card\"\n >\n <EntityTreeDemo />\n </PlaygroundSection>\n\n {/* Section 7: PropertyList -- read-only stacked property display */}\n <PlaygroundSection\n title=\"PropertyList\"\n description=\"Read-only, schema-OPTIONAL property display used by detail panels and graph node/edge cards. Stacked layout (uppercase muted key above value), click-to-copy. With no schema, values render by JS shape; an optional per-property schema refines rendering (date/datetime/boolean/number/x-ui-cell).\"\n variant=\"card\"\n >\n <PropertyListDemo />\n </PlaygroundSection>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// PropertyList demo\n// ---------------------------------------------------------------------------\n\nconst PROPERTY_LIST_SAMPLE: Record<string, unknown> = {\n name: \"lauro_server.api\",\n description: \"Build tools (Maven, Gradle, Webpack, Vite, etc.)\",\n is_component: false,\n tags: [\"python\", \"fastapi\", \"graph\"],\n created_at: \"2026-01-15T09:30:00Z\",\n empty_value: null,\n // Real nested object -> collapsed JSON tree.\n config: {\n retries: 3,\n timeout_s: 30,\n endpoints: [\"/a\", \"/b\"],\n nested: { enabled: true },\n },\n // Long text -> clamp + show more.\n notes:\n \"This module exposes the public API surface. \" +\n \"It aggregates routers from submodules, wires middleware, and configures CORS. \" +\n \"See the architecture doc for the full request lifecycle and the list of mounted sub-applications.\",\n};\n\nconst PROPERTY_LIST_SCHEMA: Record<string, JsonSchemaProperty> = {\n is_component: { type: \"boolean\" },\n created_at: { type: \"string\", format: \"date-time\" },\n};\n\nfunction PropertyListDemo(): React.ReactElement {\n return (\n <div className=\"grid grid-cols-1 gap-6 sm:grid-cols-2\">\n <Card className=\"p-4\">\n <p className=\"mb-3 text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n No schema (value-shape)\n </p>\n <PropertyList properties={PROPERTY_LIST_SAMPLE} />\n </Card>\n <Card className=\"p-4\">\n <p className=\"mb-3 text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n With optional schema (boolean / date-time)\n </p>\n <PropertyList\n properties={PROPERTY_LIST_SAMPLE}\n propertySchemas={PROPERTY_LIST_SCHEMA}\n showHeader\n />\n </Card>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// EntityTree demo\n// ---------------------------------------------------------------------------\n\ninterface OrgRow extends Record<string, unknown> {\n name: string;\n type: string;\n headcount: number;\n}\n\nconst OrgSchema = z.object({\n name: z.string().meta({ title: \"Name\", \"x-ui-column\": { order: 0 } }),\n type: z.string().meta({ title: \"Type\", \"x-ui-column\": { order: 1 } }),\n headcount: z\n .number()\n .meta({ title: \"Headcount\", \"x-ui-column\": { order: 2 } }),\n});\n\nconst ORG_TREE_SCHEMA = toJsonSchema(OrgSchema);\n\nconst ORG_NODES: TreeNode<OrgRow>[] = [\n {\n id: \"eng\",\n data: { name: \"Engineering\", type: \"Division\", headcount: 120 },\n hasChildren: true,\n children: [\n {\n id: \"frontend\",\n data: { name: \"Frontend\", type: \"Team\", headcount: 18 },\n hasChildren: true,\n children: [\n {\n id: \"design-sys\",\n data: { name: \"Design System\", type: \"Squad\", headcount: 5 },\n hasChildren: false,\n },\n ],\n },\n {\n id: \"backend\",\n data: { name: \"Backend\", type: \"Team\", headcount: 32 },\n hasChildren: false,\n },\n {\n id: \"infra\",\n data: { name: \"Infrastructure\", type: \"Team\", headcount: 14 },\n hasChildren: false,\n },\n ],\n },\n {\n id: \"product\",\n data: { name: \"Product\", type: \"Division\", headcount: 45 },\n hasChildren: true,\n children: [\n {\n id: \"research\",\n data: { name: \"Research\", type: \"Team\", headcount: 8 },\n hasChildren: false,\n },\n {\n id: \"pm\",\n data: { name: \"Product Management\", type: \"Team\", headcount: 12 },\n hasChildren: false,\n },\n ],\n },\n {\n id: \"ops\",\n data: { name: \"Operations\", type: \"Division\", headcount: 30 },\n hasChildren: false,\n },\n];\n\nfunction EntityTreeDemo() {\n const {\n expandedIds: treeExpandedIds,\n onExpand: onTreeExpand,\n onCollapse: onTreeCollapse,\n } = useTreeExpansion();\n const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());\n const [activeId, setActiveId] = useState<string | null>(null);\n\n return (\n <div className=\"space-y-4\">\n <EntityTree<OrgRow>\n schema={ORG_TREE_SCHEMA}\n nodes={ORG_NODES}\n expandedIds={treeExpandedIds}\n onExpand={onTreeExpand}\n onCollapse={onTreeCollapse}\n onNodeSelect={(node) => setActiveId(node.id)}\n onNodeEdit={(node) => setActiveId(node.id)}\n activeNodeId={activeId ?? undefined}\n selectedIds={selectedIds}\n onSelectionChange={(id, selected) =>\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 entityLabel=\"departments\"\n />\n <div className=\"flex gap-6 text-xs text-muted-foreground\">\n {activeId && (\n <span>\n Active: <span className=\"font-mono\">{activeId}</span>\n </span>\n )}\n {selectedIds.size > 0 && (\n <span>\n Selected:{\" \"}\n <span className=\"font-mono\">{[...selectedIds].join(\", \")}</span>\n </span>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
package/dist/index.js CHANGED
@@ -184,7 +184,7 @@ var builtinEntries = [
184
184
  icon: Table2,
185
185
  color: "teal",
186
186
  path: "data-components",
187
- component: lazy(() => import("./PlayDataComponents-M4SJ4XEL.js")),
187
+ component: lazy(() => import("./PlayDataComponents-W44OITT5.js")),
188
188
  group: "Data",
189
189
  order: 0
190
190
  },
@@ -195,7 +195,7 @@ var builtinEntries = [
195
195
  icon: Network,
196
196
  color: "cyan",
197
197
  path: "graph",
198
- component: lazy(() => import("./PlayGraph-3F56PREG.js")),
198
+ component: lazy(() => import("./PlayGraph-ADRTDRA7.js")),
199
199
  group: "Graph",
200
200
  order: 0
201
201
  },
@@ -6,10 +6,10 @@ import {
6
6
  } from "../chunk-DZB6WFHA.js";
7
7
  import {
8
8
  PlayDataComponents
9
- } from "../chunk-YEBK2TUW.js";
9
+ } from "../chunk-O2QMWJZI.js";
10
10
  import {
11
11
  PlayGraph
12
- } from "../chunk-VOC5VZG2.js";
12
+ } from "../chunk-4ORSUS65.js";
13
13
  import {
14
14
  PlayShellApi
15
15
  } from "../chunk-CQ6PGFRV.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@petrarca/sonnet-playground",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Playground framework and built-in component demos for the Petrarca Sonnet component library",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {
@@ -26,11 +26,11 @@
26
26
  "lucide-react": "^0.553.0",
27
27
  "sonner": "^2.0.7",
28
28
  "zod": "^4.3.6",
29
- "@petrarca/sonnet-core": "0.4.0",
30
- "@petrarca/sonnet-forms": "0.4.0",
31
- "@petrarca/sonnet-ui": "0.4.0",
32
- "@petrarca/sonnet-shell": "0.4.0",
33
- "@petrarca/sonnet-graph": "0.4.0"
29
+ "@petrarca/sonnet-core": "0.4.1",
30
+ "@petrarca/sonnet-ui": "0.4.1",
31
+ "@petrarca/sonnet-forms": "0.4.1",
32
+ "@petrarca/sonnet-shell": "0.4.1",
33
+ "@petrarca/sonnet-graph": "0.4.1"
34
34
  },
35
35
  "peerDependencies": {
36
36
  "react": ">=19",
@@ -1,7 +0,0 @@
1
- import {
2
- PlayGraph
3
- } from "./chunk-VOC5VZG2.js";
4
- export {
5
- PlayGraph as default
6
- };
7
- //# sourceMappingURL=PlayGraph-3F56PREG.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/pages/PlayGraph.tsx"],"sourcesContent":["/**\n * Playground page for @petrarca/sonnet-graph.\n * Accessible at /playground/graph\n *\n * Demonstrates graph visualization with static mock data -- no backend required.\n * Uses the GraphStoresContext provider pattern that consumers like explorer\n * and Atlas would use to wire their own stores.\n */\n\nimport React, { useCallback, useRef, useState } from \"react\";\nimport {\n GraphVisualizer,\n ActionPanel,\n GraphA11yList,\n GraphRendererProvider,\n GraphStoresContext,\n createGraphDataStore,\n createGraphFilterStore,\n createGraphExplorationStore,\n createSelectionStore,\n createGraphFocusStore,\n enrichNodes,\n enrichEdges,\n buildColorPalette,\n type RawGraphNode,\n type RawGraphEdge,\n type WorkspaceStores,\n} from \"@petrarca/sonnet-graph\";\nimport {\n Button,\n Alert,\n AlertDescription,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n ResizeHandle,\n} from \"@petrarca/sonnet-ui\";\nimport { Play, RotateCcw } from \"lucide-react\";\n\n// ---------------------------------------------------------------------------\n// Mock data -- a small org hierarchy\n// ---------------------------------------------------------------------------\n\nconst MOCK_NODES: RawGraphNode[] = [\n {\n id_: 1,\n label_: \"Company\",\n properties_: { name: \"Acme Corp\", founded: 1985, industry: \"Technology\" },\n },\n {\n id_: 2,\n label_: \"Department\",\n properties_: { name: \"Engineering\", headcount: 42 },\n },\n {\n id_: 3,\n label_: \"Department\",\n properties_: { name: \"Marketing\", headcount: 18 },\n },\n {\n id_: 4,\n label_: \"Department\",\n properties_: { name: \"Sales\", headcount: 25 },\n },\n {\n id_: 5,\n label_: \"Person\",\n properties_: { name: \"Alice Chen\", role: \"CTO\" },\n },\n {\n id_: 6,\n label_: \"Person\",\n properties_: { name: \"Bob Smith\", role: \"VP Engineering\" },\n },\n {\n id_: 7,\n label_: \"Person\",\n properties_: { name: \"Carol Davis\", role: \"CMO\" },\n },\n {\n id_: 8,\n label_: \"Person\",\n properties_: { name: \"Dave Wilson\", role: \"VP Sales\" },\n },\n {\n id_: 9,\n label_: \"Person\",\n properties_: { name: \"Eve Johnson\", role: \"Senior Engineer\" },\n },\n {\n id_: 10,\n label_: \"Person\",\n properties_: { name: \"Frank Brown\", role: \"Product Manager\" },\n },\n {\n id_: 11,\n label_: \"Product\",\n properties_: { name: \"CloudSuite\", version: \"3.2\", status: \"GA\" },\n },\n {\n id_: 12,\n label_: \"Product\",\n properties_: { name: \"DataPipeline\", version: \"1.0\", status: \"Beta\" },\n },\n];\n\nconst MOCK_EDGES: RawGraphEdge[] = [\n {\n id_: 101,\n label_: \"HAS_DEPARTMENT\",\n start_id_: 1,\n end_id_: 2,\n properties_: {},\n },\n {\n id_: 102,\n label_: \"HAS_DEPARTMENT\",\n start_id_: 1,\n end_id_: 3,\n properties_: {},\n },\n {\n id_: 103,\n label_: \"HAS_DEPARTMENT\",\n start_id_: 1,\n end_id_: 4,\n properties_: {},\n },\n {\n id_: 104,\n label_: \"LEADS\",\n start_id_: 5,\n end_id_: 2,\n properties_: { since: 2019 },\n },\n {\n id_: 105,\n label_: \"WORKS_IN\",\n start_id_: 6,\n end_id_: 2,\n properties_: { since: 2020 },\n },\n {\n id_: 106,\n label_: \"LEADS\",\n start_id_: 7,\n end_id_: 3,\n properties_: { since: 2021 },\n },\n {\n id_: 107,\n label_: \"LEADS\",\n start_id_: 8,\n end_id_: 4,\n properties_: { since: 2018 },\n },\n {\n id_: 108,\n label_: \"WORKS_IN\",\n start_id_: 9,\n end_id_: 2,\n properties_: { since: 2022 },\n },\n {\n id_: 109,\n label_: \"WORKS_IN\",\n start_id_: 10,\n end_id_: 2,\n properties_: { since: 2021 },\n },\n { id_: 110, label_: \"REPORTS_TO\", start_id_: 6, end_id_: 5, properties_: {} },\n { id_: 111, label_: \"REPORTS_TO\", start_id_: 9, end_id_: 6, properties_: {} },\n {\n id_: 112,\n label_: \"REPORTS_TO\",\n start_id_: 10,\n end_id_: 6,\n properties_: {},\n },\n { id_: 113, label_: \"OWNS\", start_id_: 2, end_id_: 11, properties_: {} },\n { id_: 114, label_: \"OWNS\", start_id_: 2, end_id_: 12, properties_: {} },\n];\n\n// ---------------------------------------------------------------------------\n// Store setup\n//\n// Stores are created once at module load, not inside the component.\n// This avoids re-creation on re-render and removes the need for useMemo.\n// ---------------------------------------------------------------------------\n\nfunction createPlaygroundStores(): WorkspaceStores {\n const graphFilter = createGraphFilterStore();\n const graphData = createGraphDataStore();\n const selection = createSelectionStore();\n const graphFocus = createGraphFocusStore();\n const graphExploration = createGraphExplorationStore({\n graphData,\n selection,\n graphFocus,\n graphFilter,\n // Static data -- no server expansion available in the playground\n expandNode: async () => ({ nodes: [], edges: [] }),\n getNodes: async () => [],\n });\n return { graphFilter, graphData, graphExploration, selection };\n}\n\nconst PLAYGROUND_STORES = createPlaygroundStores();\n\n// ---------------------------------------------------------------------------\n// Data helpers\n// ---------------------------------------------------------------------------\n\ninterface GraphInput {\n nodes: RawGraphNode[];\n edges: RawGraphEdge[];\n}\n\nconst INITIAL_DATA: GraphInput = { nodes: MOCK_NODES, edges: MOCK_EDGES };\n\nfunction serializeGraphData(data: GraphInput): string {\n return JSON.stringify(data, null, 2);\n}\n\nfunction validateNode(n: unknown, i: number): string | null {\n if (!n || typeof n !== \"object\") return `nodes[${i}] must be an object`;\n const node = n as Record<string, unknown>;\n if (node.id_ === undefined) return `nodes[${i}] is missing id_`;\n if (typeof node.label_ !== \"string\") return `nodes[${i}] is missing label_`;\n return null;\n}\n\nfunction validateEdge(e: unknown, i: number): string | null {\n if (!e || typeof e !== \"object\") return `edges[${i}] must be an object`;\n const edge = e as Record<string, unknown>;\n if (edge.id_ === undefined) return `edges[${i}] is missing id_`;\n if (typeof edge.label_ !== \"string\") return `edges[${i}] is missing label_`;\n if (edge.start_id_ === undefined) return `edges[${i}] is missing start_id_`;\n if (edge.end_id_ === undefined) return `edges[${i}] is missing end_id_`;\n return null;\n}\n\n/** Validates that parsed JSON is a usable GraphInput. Returns an error string or null. */\nfunction validateGraphInput(value: unknown): string | null {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return \"JSON must be an object with nodes and edges arrays\";\n }\n const obj = value as Record<string, unknown>;\n if (!Array.isArray(obj.nodes)) return '\"nodes\" must be an array';\n if (!Array.isArray(obj.edges)) return '\"edges\" must be an array';\n for (const [i, n] of (obj.nodes as unknown[]).entries()) {\n const err = validateNode(n, i);\n if (err) return err;\n }\n for (const [i, e] of (obj.edges as unknown[]).entries()) {\n const err = validateEdge(e, i);\n if (err) return err;\n }\n return null;\n}\n\nfunction loadIntoStore(stores: WorkspaceStores, data: GraphInput) {\n const labelCounts: Record<string, number> = {};\n for (const n of data.nodes) {\n labelCounts[n.label_] = (labelCounts[n.label_] ?? 0) + 1;\n }\n const palette = buildColorPalette(labelCounts);\n const nodes = enrichNodes(data.nodes, palette);\n const edges = enrichEdges(data.edges, palette);\n stores.graphFilter.getState().resetFilters();\n stores.graphData.getState().setQueryData(nodes, edges, {\n nodes: nodes.length,\n edges: edges.length,\n });\n // Signal renderers to re-fit layout after data change\n stores.graphFilter.getState().notifyDataChange();\n}\n\n// Load initial data immediately -- no effect needed, no empty render cycle\nloadIntoStore(PLAYGROUND_STORES, INITIAL_DATA);\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport default function PlayGraph(): React.ReactElement {\n const [jsonText, setJsonText] = useState(() =>\n serializeGraphData(INITIAL_DATA),\n );\n const [parseError, setParseError] = useState<string | null>(null);\n\n // Resizable side panel (demonstrates ResizeHandle).\n const [panelWidth, setPanelWidth] = useState(300);\n const rowRef = useRef<HTMLDivElement>(null);\n const startResize = useCallback((e: React.PointerEvent) => {\n e.preventDefault();\n const target = e.currentTarget as HTMLElement;\n target.setPointerCapture(e.pointerId);\n const move = (ev: PointerEvent) => {\n const right = rowRef.current?.getBoundingClientRect().right ?? 0;\n setPanelWidth(Math.min(560, Math.max(200, right - ev.clientX)));\n };\n const up = () => {\n window.removeEventListener(\"pointermove\", move);\n window.removeEventListener(\"pointerup\", up);\n };\n window.addEventListener(\"pointermove\", move);\n window.addEventListener(\"pointerup\", up);\n }, []);\n\n const handleApply = useCallback(() => {\n let parsed: unknown;\n try {\n parsed = JSON.parse(jsonText);\n } catch (e) {\n setParseError(e instanceof Error ? e.message : \"Invalid JSON\");\n return;\n }\n const validationError = validateGraphInput(parsed);\n if (validationError) {\n setParseError(validationError);\n return;\n }\n setParseError(null);\n loadIntoStore(PLAYGROUND_STORES, parsed as GraphInput);\n }, [jsonText]);\n\n const handleReset = useCallback(() => {\n setJsonText(serializeGraphData(INITIAL_DATA));\n setParseError(null);\n loadIntoStore(PLAYGROUND_STORES, INITIAL_DATA);\n }, []);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\") {\n e.preventDefault();\n handleApply();\n }\n },\n [handleApply],\n );\n\n return (\n <div className=\"space-y-6\">\n <div>\n <h1>Graph Visualization</h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n Interactive property graph with dual renderer support. Edit the JSON\n data and apply to re-render.\n </p>\n </div>\n <GraphStoresContext.Provider value={PLAYGROUND_STORES}>\n <Tabs defaultValue=\"graph\" className=\"space-y-3\">\n <TabsList>\n <TabsTrigger value=\"graph\">Graph</TabsTrigger>\n <TabsTrigger value=\"data\">Data</TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"graph\" className=\"mt-0\">\n <GraphRendererProvider defaultRenderer=\"cytoscape\">\n <div ref={rowRef} className=\"flex overflow-hidden h-[600px]\">\n <div className=\"flex-1 min-w-0\">\n <GraphVisualizer />\n </div>\n {/* Drag to resize the side panel (ResizeHandle demo). */}\n <ResizeHandle\n orientation=\"vertical\"\n aria-valuenow={panelWidth}\n aria-valuemin={200}\n aria-valuemax={560}\n onPointerDown={startResize}\n onDoubleClick={() => setPanelWidth(300)}\n />\n <div\n style={{ width: panelWidth }}\n className=\"flex-shrink-0 flex flex-col min-h-0\"\n >\n <div className=\"flex-1 min-h-0 overflow-hidden\">\n <ActionPanel />\n </div>\n {/* Accessible DOM mirror (playground demo only): keyboard / AT /\n automation can select the same nodes/edges as the canvas.\n Real consumers render it sr-only (omit `visible`). */}\n <div className=\"shrink-0 px-4 pb-4 pt-2\">\n <p className=\"text-xs font-medium text-muted-foreground uppercase tracking-wide mb-2\">\n Accessible list (demo)\n </p>\n <GraphA11yList visible maxHeight={160} />\n </div>\n </div>\n </div>\n </GraphRendererProvider>\n </TabsContent>\n\n <TabsContent value=\"data\" className=\"mt-0\">\n <div className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <Button size=\"sm\" onClick={handleApply}>\n <Play className=\"h-4 w-4 mr-1\" />\n Apply\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={handleReset}>\n <RotateCcw className=\"h-4 w-4 mr-1\" />\n Reset\n </Button>\n <span className=\"text-xs text-muted-foreground ml-2\">\n Cmd+Enter to apply\n </span>\n </div>\n {parseError && (\n <Alert variant=\"destructive\">\n <AlertDescription>{parseError}</AlertDescription>\n </Alert>\n )}\n <textarea\n value={jsonText}\n onChange={(e) => setJsonText(e.target.value)}\n onKeyDown={handleKeyDown}\n spellCheck={false}\n className=\"w-full h-[600px] font-mono text-xs p-3 border rounded-lg bg-muted/30 resize-y focus:outline-none focus:ring-2 focus:ring-ring\"\n />\n </div>\n </TabsContent>\n </Tabs>\n </GraphStoresContext.Provider>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/pages/PlayDataComponents.tsx"],"sourcesContent":["/**\n * Playground page for SearchInput, EntitySelect, EntityTable, and EntityTree.\n * Accessible at /playground/data-components\n *\n * Six sections:\n * 1. Simple mode -- single freetext search, no field picker\n * 2. Faceted mode -- two-column: schema editor left, live search + output right\n * 3. EntityTable -- static sample data wired to faceted SearchInput\n * 4. Local renderers -- same data with x- prefixed custom cell renderers\n * 5. EntitySelect -- async searchable select backed by a static mock fetcher\n * 6. EntityTree -- schema-driven tree with static nested data\n */\n\nimport React, { useState, useMemo, useCallback } from \"react\";\nimport { ArrowRight, ArrowUp } from \"lucide-react\";\nimport {\n Badge,\n Button,\n Card,\n SimpleTooltip,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n SearchInput,\n type SearchMode,\n EntitySelect,\n EntityTable,\n createRenderer,\n EntityTree,\n type TreeNode,\n type TableUiSchema,\n} from \"@petrarca/sonnet-ui\";\nimport { FormTextarea } from \"@petrarca/sonnet-forms\";\nimport { JsonEditor } from \"@petrarca/sonnet-ui/json-editor\";\nimport { PlaygroundSection } from \"../PlaygroundSection\";\nimport {\n EMPTY_FILTER,\n flattenFilterExpr,\n isEmptyFilterExpr,\n serializeFilterExpr,\n type FilterExpr,\n} from \"@petrarca/sonnet-core/search\";\nimport { toJsonSchema, type JsonSchema } from \"@petrarca/sonnet-core/schema\";\nimport { useTreeExpansion } from \"@petrarca/sonnet-core/hooks\";\nimport type { EntityOptionFetcher } from \"@petrarca/sonnet-core/entityOptions\";\nimport { z } from \"zod/v4\";\n\n// Static mock patient data for the EntitySelect playground demo.\n// Uses a local fetcher so the playground has no dependency on a live API.\nconst MOCK_PATIENTS = [\n { value: \"pat_001\", label: \"Alice Hartmann\" },\n { value: \"pat_002\", label: \"Bob Nguyen\" },\n { value: \"pat_003\", label: \"Carol Smith\" },\n { value: \"pat_004\", label: \"David Okafor\" },\n { value: \"pat_005\", label: \"Eva Larsson\" },\n { value: \"pat_006\", label: \"Frank Torres\" },\n { value: \"pat_007\", label: \"Grace Kim\" },\n { value: \"pat_008\", label: \"Henry Bauer\" },\n];\n\nconst patientFetcher: EntityOptionFetcher = ({ search } = {}) => {\n const q = search?.toLowerCase() ?? \"\";\n const results = q\n ? MOCK_PATIENTS.filter((p) => p.label.toLowerCase().includes(q))\n : MOCK_PATIENTS;\n return Promise.resolve(results);\n};\n\ninterface SampleRow {\n id: string;\n name: string;\n status: \"active\" | \"inactive\" | \"pending\";\n role: string;\n joined: string;\n}\n\nconst ALL_ROWS: SampleRow[] = [\n {\n id: \"u-001\",\n name: \"Alice Hartmann\",\n status: \"active\",\n role: \"admin\",\n joined: \"2024-01-15\",\n },\n {\n id: \"u-002\",\n name: \"Bob Nguyen\",\n status: \"active\",\n role: \"editor\",\n joined: \"2024-02-03\",\n },\n {\n id: \"u-003\",\n name: \"Carol Smith\",\n status: \"inactive\",\n role: \"viewer\",\n joined: \"2024-03-20\",\n },\n {\n id: \"u-004\",\n name: \"David Okafor\",\n status: \"pending\",\n role: \"editor\",\n joined: \"2024-04-11\",\n },\n {\n id: \"u-005\",\n name: \"Eva Larsson\",\n status: \"active\",\n role: \"admin\",\n joined: \"2024-05-08\",\n },\n {\n id: \"u-006\",\n name: \"Frank Torres\",\n status: \"inactive\",\n role: \"viewer\",\n joined: \"2024-06-22\",\n },\n {\n id: \"u-007\",\n name: \"Grace Kim\",\n status: \"active\",\n role: \"editor\",\n joined: \"2024-07-14\",\n },\n {\n id: \"u-008\",\n name: \"Henry Bauer\",\n status: \"pending\",\n role: \"viewer\",\n joined: \"2024-08-30\",\n },\n];\n\nconst STATUS_COLOR = {\n active: \"green\",\n inactive: \"violet\",\n pending: \"yellow\",\n} as const;\n\nconst PlaygroundFacets = z.object({\n search: z.string().meta({ \"x-ui-title\": \"Name\" }),\n status: z\n .enum([\"active\", \"inactive\", \"pending\"])\n .optional()\n .meta({\n \"x-ui-title\": \"Status\",\n \"x-ui-options\": {\n enumNames: {\n active: \"Active\",\n inactive: \"Inactive\",\n pending: \"Pending\",\n },\n },\n }),\n role: z.string().optional().meta({ \"x-ui-title\": \"Role\" }),\n});\n\nconst SEARCH_FACET_SCHEMA = toJsonSchema(PlaygroundFacets);\n\nconst SAMPLE_SCHEMA: JsonSchema = {\n title: \"User\",\n type: \"object\",\n properties: {\n name: {\n type: \"string\",\n title: \"Name\",\n \"x-ui-column\": { order: 0 },\n \"x-ui-cell\": \"bold\",\n },\n status: {\n type: \"string\",\n title: \"Status\",\n \"x-ui-column\": { order: 1 },\n \"x-ui-cell\": \"badge\",\n \"x-ui-cell-options\": { colors: STATUS_COLOR },\n },\n role: {\n type: \"string\",\n title: \"Role\",\n \"x-ui-column\": { order: 2 },\n \"x-ui-cell\": \"muted\",\n },\n id: {\n type: \"string\",\n title: \"ID\",\n \"x-ui-column\": { order: 3 },\n \"x-ui-cell\": \"code\",\n },\n joined: {\n type: \"string\",\n format: \"date\",\n title: \"Joined\",\n \"x-ui-column\": { order: 4 },\n },\n },\n};\n\nconst SAMPLE_UI_SCHEMA: TableUiSchema = {}; // mutable via the live schema editor below\n\n// Local renderer demo: three x- prefixed renderers using the same SampleRow data.\nconst ROLE_ICONS: Record<string, string> = {\n admin: \"A\",\n editor: \"E\",\n viewer: \"V\",\n};\n\nconst CUSTOM_RENDERERS = {\n // Extract initials from the name, display as avatar circle + name.\n \"x-play-initials\": createRenderer<SampleRow>((row) => {\n const initials = row.name\n .split(\" \")\n .map((w) => w[0])\n .join(\"\");\n return (\n <span className=\"inline-flex items-center gap-2\">\n <span className=\"inline-flex items-center justify-center h-7 w-7 rounded-full bg-muted text-xs font-medium shrink-0\">\n {initials}\n </span>\n <span className=\"font-medium\">{row.name}</span>\n </span>\n );\n }),\n\n // Role with a letter prefix read from options.icons.\n \"x-play-role-icon\": createRenderer<SampleRow>((row, options) => {\n const icons = (options.icons as Record<string, string>) ?? {};\n const icon = icons[row.role] ?? \"?\";\n return (\n <span>\n <span className=\"inline-flex items-center justify-center h-5 w-5 rounded bg-muted text-xs font-mono mr-1.5\">\n {icon}\n </span>\n {row.role}\n </span>\n );\n }),\n\n // Compute days since joined, color-coded by threshold from options.\n \"x-play-tenure\": createRenderer<SampleRow>((row, options) => {\n const threshold = (options.recentDays as number) ?? 365;\n const days = Math.floor(\n (Date.now() - new Date(row.joined).getTime()) / 86_400_000,\n );\n const isRecent = days < threshold;\n return (\n <span className={isRecent ? \"text-primary\" : \"text-muted-foreground\"}>\n {days}d\n </span>\n );\n }),\n};\n\nconst CUSTOM_RENDERER_SCHEMA: JsonSchema = {\n title: \"User (custom renderers)\",\n type: \"object\",\n properties: {\n name: {\n type: \"string\",\n title: \"Name\",\n \"x-ui-column\": { order: 0 },\n \"x-ui-cell\": \"x-play-initials\",\n },\n role: {\n type: \"string\",\n title: \"Role\",\n \"x-ui-column\": { order: 1 },\n \"x-ui-cell\": \"x-play-role-icon\",\n \"x-ui-cell-options\": { icons: ROLE_ICONS },\n },\n status: {\n type: \"string\",\n title: \"Status\",\n \"x-ui-column\": { order: 2 },\n \"x-ui-cell\": \"badge\",\n \"x-ui-cell-options\": { colors: STATUS_COLOR },\n },\n joined: {\n type: \"string\",\n title: \"Tenure\",\n \"x-ui-column\": { order: 3 },\n \"x-ui-cell\": \"x-play-tenure\",\n \"x-ui-cell-options\": { recentDays: 500 },\n },\n id: {\n type: \"string\",\n title: \"ID\",\n \"x-ui-column\": { order: 4 },\n \"x-ui-cell\": \"code\",\n },\n },\n};\n\n// Sentinel value meaning \"schema was reloaded, next submit resets the counter to 0\".\nconst SUBMIT_COUNT_RESET = -1;\n\n// Presets for the searchFields demo (Section 1b). Uses the same user domain\n// as the rest of the playground (name, role, status).\nconst SEARCH_FIELD_PRESETS: { label: string; fields: string[] }[] = [\n { label: \"name, role\", fields: [\"name\", \"role\"] },\n { label: \"name (single)\", fields: [\"name\"] },\n { label: \"name, role, status\", fields: [\"name\", \"role\", \"status\"] },\n];\n\n// Reusable toggle-button strip for playground controls.\n// Renders a label followed by a set of pill buttons. className applies to\n// the wrapping fragment's implicit container -- callers place it inside a\n// flex row, so use ml-* on the caller side via the containerClassName prop.\nfunction ToggleStrip<T extends string | number>({\n label,\n options,\n value,\n onChange,\n format,\n containerClassName,\n}: {\n label: string;\n options: readonly T[];\n value: T;\n onChange: (v: T) => void;\n format?: (v: T) => string;\n containerClassName?: string;\n}) {\n const fmt = format ?? String;\n return (\n <div className={`flex items-center gap-3 ${containerClassName ?? \"\"}`}>\n <span className=\"text-xs text-muted-foreground\">{label}:</span>\n {options.map((opt) => (\n <button\n key={String(opt)}\n type=\"button\"\n onClick={() => onChange(opt)}\n className={[\n \"px-3 py-1 rounded-full text-xs font-medium transition-colors\",\n value === opt\n ? \"bg-primary text-primary-foreground\"\n : \"bg-muted text-muted-foreground hover:text-foreground\",\n ].join(\" \")}\n >\n {fmt(opt)}\n </button>\n ))}\n </div>\n );\n}\n\nconst MODE_OPTIONS = [\"explicit\", \"debounce\"] as const;\nconst MODE_LABELS: Record<string, string> = {\n explicit: \"Explicit (Enter)\",\n debounce: \"Debounce (300 ms)\",\n};\nconst MIN_CHARS_OPTIONS = [0, 1, 2, 3] as const;\nconst FIELD_PRESET_INDICES = SEARCH_FIELD_PRESETS.map(\n (_, i) => i,\n) as readonly number[];\n\nfunction FilterExprInspector({ expr }: { expr: FilterExpr }) {\n return (\n <pre className=\"mt-3 rounded-md bg-muted px-4 py-3 text-xs overflow-auto max-h-40\">\n {JSON.stringify(expr, null, 2)}\n </pre>\n );\n}\n\nfunction FlatTermsInspector({ expr }: { expr: FilterExpr }) {\n const terms = flattenFilterExpr(expr);\n return (\n <pre className=\"mt-3 rounded-md bg-muted px-4 py-3 text-xs overflow-auto max-h-40\">\n {JSON.stringify(terms, null, 2)}\n </pre>\n );\n}\n\n/** Playground sandbox for SearchInput, EntitySelect, and EntityTable. */\nexport default function PlayDataComponents(): React.ReactElement {\n // Section 1: simple mode\n const [simpleExpr, setSimpleExpr] = useState<FilterExpr>(EMPTY_FILTER);\n const [simpleMode, setSimpleMode] = useState<SearchMode>(\"explicit\");\n const [simpleMinChars, setSimpleMinChars] = useState(0);\n\n // Section 1b: searchFields mode (multi-field OR)\n const [fieldsExpr, setFieldsExpr] = useState<FilterExpr>(EMPTY_FILTER);\n const [fieldsMode, setFieldsMode] = useState<SearchMode>(\"explicit\");\n const [fieldsMinChars, setFieldsMinChars] = useState(0);\n const [fieldsPresetIdx, setFieldsPresetIdx] = useState(0);\n const activeSearchFields = SEARCH_FIELD_PRESETS[fieldsPresetIdx].fields;\n\n // Section 2: faceted mode with live schema editor\n const [facetedExpr, setFacetedExpr] = useState<FilterExpr>(EMPTY_FILTER);\n const [facetedSubmitCount, setFacetedSubmitCount] = useState(0);\n const handleFacetedChange = useCallback((expr: FilterExpr) => {\n setFacetedExpr(expr);\n setFacetedSubmitCount((n) => n + 1);\n }, []);\n const [schemaText, setSchemaText] = useState(() =>\n JSON.stringify(toJsonSchema(PlaygroundFacets), null, 2),\n );\n const [schemaError, setSchemaError] = useState(\"\");\n const [activeSchema, setActiveSchema] =\n useState<JsonSchema>(SEARCH_FACET_SCHEMA);\n\n const handleSchemaTextChange = useCallback((value: string) => {\n setSchemaText(value);\n try {\n JSON.parse(value);\n setSchemaError(\"\");\n } catch {\n setSchemaError(\"Invalid JSON\");\n }\n }, []);\n\n const handleLoadSchema = useCallback(() => {\n try {\n const parsed = JSON.parse(schemaText) as JsonSchema;\n setActiveSchema(parsed);\n setFacetedExpr(EMPTY_FILTER);\n setFacetedSubmitCount(SUBMIT_COUNT_RESET);\n setSchemaError(\"\");\n } catch {\n setSchemaError(\"Invalid JSON -- cannot load\");\n }\n }, [schemaText]);\n\n // Section 3: schema + UI schema editors for the table.\n const [tableSchemaText, setTableSchemaText] = useState(() =>\n JSON.stringify(SAMPLE_SCHEMA, null, 2),\n );\n const [tableUiSchemaText, setTableUiSchemaText] = useState(() =>\n JSON.stringify(SAMPLE_UI_SCHEMA, null, 2),\n );\n const [tableSchemaError, setTableSchemaError] = useState(\"\");\n const [activeTableSchema, setActiveTableSchema] =\n useState<JsonSchema>(SAMPLE_SCHEMA);\n const [activeTableUiSchema, setActiveTableUiSchema] =\n useState<TableUiSchema>(SAMPLE_UI_SCHEMA);\n const [tableSchemaTab, setTableSchemaTab] = useState(\"schema\");\n\n const handleTableSchemaTextChange = useCallback((value: string) => {\n setTableSchemaText(value);\n try {\n JSON.parse(value);\n setTableSchemaError(\"\");\n } catch {\n setTableSchemaError(\"Invalid JSON\");\n }\n }, []);\n\n const handleTableUiSchemaTextChange = useCallback((value: string) => {\n setTableUiSchemaText(value);\n try {\n JSON.parse(value);\n setTableSchemaError(\"\");\n } catch {\n setTableSchemaError(\"Invalid JSON\");\n }\n }, []);\n\n const handleApplyTableSchema = useCallback(() => {\n try {\n const schema = JSON.parse(tableSchemaText) as JsonSchema;\n const uiSchema = JSON.parse(tableUiSchemaText) as TableUiSchema;\n setActiveTableSchema(schema);\n setActiveTableUiSchema(uiSchema);\n setTableSchemaError(\"\");\n } catch {\n setTableSchemaError(\"Invalid JSON -- cannot apply\");\n }\n }, [tableSchemaText, tableUiSchemaText]);\n\n // Section 3: faceted mode wired to EntityTable.\n // onChange fires only on submit -- filteredRows updates when the user presses Enter.\n const [tableExpr, setTableExpr] = useState<FilterExpr>(EMPTY_FILTER);\n\n const filteredRows = useMemo(() => {\n const terms = flattenFilterExpr(tableExpr);\n if (terms.length === 0) return ALL_ROWS;\n\n return ALL_ROWS.filter((row) =>\n terms.every(({ key, value }) => {\n const v = value.toLowerCase();\n if (key === \"status\") return row.status.toLowerCase().includes(v);\n if (key === \"role\") return row.role.toLowerCase().includes(v);\n // default: search by name\n return row.name.toLowerCase().includes(v);\n }),\n );\n }, [tableExpr]);\n\n const tableData = useMemo(\n () => ({\n data: filteredRows,\n meta: {\n total: filteredRows.length,\n limit: filteredRows.length,\n offset: 0,\n has_next: false,\n has_prev: false,\n },\n }),\n [filteredRows],\n );\n\n // Section 5: EntitySelect\n const [selectedPatient, setSelectedPatient] = useState<string | null>(null);\n\n return (\n <div className=\"w-full max-w-4xl space-y-6\">\n <div>\n <h1>Data Components</h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n Interactive sandbox for SearchInput (simple, multi-field, faceted),\n EntityTable (with schema editor and custom renderers), EntitySelect,\n and EntityTree.\n </p>\n </div>\n\n {/* Section 1: simple mode */}\n <PlaygroundSection\n title=\"SearchInput — simple mode\"\n description=\"No fields prop. Produces a single search term under the key 'search'.\"\n variant=\"card\"\n >\n <div className=\"flex flex-wrap gap-4 mb-3\">\n <ToggleStrip\n label=\"Mode\"\n options={MODE_OPTIONS}\n value={simpleMode}\n onChange={(m) => {\n setSimpleMode(m);\n setSimpleExpr(EMPTY_FILTER);\n }}\n format={(m) => MODE_LABELS[m]}\n />\n <ToggleStrip\n label=\"Min chars\"\n options={MIN_CHARS_OPTIONS}\n value={simpleMinChars}\n onChange={setSimpleMinChars}\n format={(n) => (n === 0 ? \"off\" : String(n))}\n />\n </div>\n <SearchInput\n value={simpleExpr}\n onChange={setSimpleExpr}\n mode={simpleMode}\n minChars={simpleMinChars}\n placeholder=\"Search...\"\n className=\"max-w-sm\"\n />\n <FlatTermsInspector expr={simpleExpr} />\n </PlaygroundSection>\n\n {/* Section 1b: searchFields mode */}\n <PlaygroundSection\n title=\"SearchInput — searchFields (multi-field OR)\"\n description=\"Produces a FilterOr with one term per field. Toggle field sets, mode, and minChars to explore different behaviours.\"\n variant=\"card\"\n >\n <div className=\"flex flex-wrap gap-4 mb-3\">\n <ToggleStrip\n label=\"Fields\"\n options={FIELD_PRESET_INDICES}\n value={fieldsPresetIdx}\n onChange={(idx) => {\n setFieldsPresetIdx(idx);\n setFieldsExpr(EMPTY_FILTER);\n }}\n format={(idx) => SEARCH_FIELD_PRESETS[idx].label}\n />\n <ToggleStrip\n label=\"Mode\"\n options={MODE_OPTIONS}\n value={fieldsMode}\n onChange={(m) => {\n setFieldsMode(m);\n setFieldsExpr(EMPTY_FILTER);\n }}\n format={(m) => MODE_LABELS[m]}\n />\n <ToggleStrip\n label=\"Min chars\"\n options={MIN_CHARS_OPTIONS}\n value={fieldsMinChars}\n onChange={setFieldsMinChars}\n format={(n) => (n === 0 ? \"off\" : String(n))}\n />\n </div>\n <SearchInput\n value={fieldsExpr}\n onChange={setFieldsExpr}\n searchFields={activeSearchFields}\n mode={fieldsMode}\n minChars={fieldsMinChars}\n placeholder={`Search by ${activeSearchFields.join(\" or \")}...`}\n className=\"max-w-sm\"\n />\n <div className=\"mt-3 space-y-2\">\n <p className=\"text-xs text-muted-foreground\">\n searchFields: [{activeSearchFields.map((f) => `\"${f}\"`).join(\", \")}]\n </p>\n <p className=\"text-xs text-muted-foreground\">FilterExpr AST:</p>\n <FilterExprInspector expr={fieldsExpr} />\n {!isEmptyFilterExpr(fieldsExpr) && (\n <>\n <p className=\"text-xs text-muted-foreground\">\n Serialized q= string:\n </p>\n <pre className=\"rounded-md bg-muted px-4 py-3 text-xs overflow-auto\">\n {serializeFilterExpr(fieldsExpr)}\n </pre>\n </>\n )}\n </div>\n </PlaygroundSection>\n\n {/* Section 2: faceted mode -- two-column schema editor */}\n <PlaygroundSection\n title=\"SearchInput — faceted mode\"\n description=\"Edit the JSON Schema on the left and load it into the search input. Add chips by picking a field and typing a value. Press Enter on empty input to fire onChange.\"\n variant=\"card\"\n >\n <div className=\"flex gap-4 items-start\">\n {/* Left: schema editor */}\n <Card className=\"flex-1 min-w-0 p-3 flex flex-col gap-2\">\n <p className=\"text-xs font-medium text-muted-foreground\">\n JSON Schema\n </p>\n {schemaError && (\n <Badge variant=\"destructive\" className=\"text-xs self-start\">\n {schemaError}\n </Badge>\n )}\n <FormTextarea\n value={schemaText}\n onChange={(e) => handleSchemaTextChange(e.target.value)}\n className=\"font-mono text-xs\"\n rows={18}\n />\n </Card>\n\n {/* Load button */}\n <div className=\"flex items-center self-center\">\n <SimpleTooltip label=\"Load schema into search\">\n <Button\n variant=\"default\"\n size=\"icon\"\n onClick={handleLoadSchema}\n disabled={!!schemaError}\n >\n <ArrowRight size={18} />\n </Button>\n </SimpleTooltip>\n </div>\n\n {/* Right: live search + output */}\n <Card className=\"flex-1 min-w-0 p-3 flex flex-col gap-3\">\n <p className=\"text-xs font-medium text-muted-foreground\">\n Live search\n </p>\n <SearchInput\n value={facetedExpr}\n onChange={handleFacetedChange}\n schema={activeSchema}\n mode=\"explicit\"\n placeholder=\"Add filter...\"\n />\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span>onChange fired:</span>\n <span className=\"font-mono font-medium text-foreground\">\n {facetedSubmitCount}x\n </span>\n </div>\n <FilterExprInspector expr={facetedExpr} />\n </Card>\n </div>\n </PlaygroundSection>\n\n {/* Section 3: faceted mode + EntityTable wired together */}\n <PlaygroundSection\n title=\"EntityTable with SearchInput\"\n description=\"Faceted search wired to EntityTable. onChange fires only on submit (Enter on empty input) -- table filters when the user presses Enter. Edit the JSON Schema or UI Schema below and press Apply to see column changes live.\"\n variant=\"card\"\n >\n <SearchInput\n value={tableExpr}\n onChange={setTableExpr}\n schema={SEARCH_FACET_SCHEMA}\n mode=\"explicit\"\n placeholder=\"Filter users... (press Enter to apply)\"\n className=\"mb-4 max-w-sm\"\n />\n <EntityTable<SampleRow>\n schema={activeTableSchema}\n uiSchema={activeTableUiSchema}\n data={tableData}\n isLoading={false}\n isError={false}\n entityLabel=\"users\"\n isFiltered={!isEmptyFilterExpr(tableExpr)}\n />\n\n {/* Schema editor below the table */}\n <div className=\"mt-4\">\n <Card className=\"border shadow-sm p-4 flex flex-col\">\n <div className=\"flex items-center justify-between mb-2\">\n <Tabs\n value={tableSchemaTab}\n onValueChange={setTableSchemaTab}\n className=\"flex flex-col flex-1\"\n >\n <div className=\"flex items-center justify-between\">\n <TabsList>\n <TabsTrigger value=\"schema\">JSON Schema</TabsTrigger>\n <TabsTrigger value=\"uischema\">UI Schema</TabsTrigger>\n </TabsList>\n <div className=\"flex items-center gap-2\">\n {tableSchemaError && (\n <Badge variant=\"destructive\" className=\"text-xs\">\n {tableSchemaError}\n </Badge>\n )}\n <SimpleTooltip label=\"Apply schema to table above\">\n <Button\n variant=\"default\"\n size=\"icon\"\n onClick={handleApplyTableSchema}\n disabled={!!tableSchemaError}\n >\n <ArrowUp size={18} />\n </Button>\n </SimpleTooltip>\n </div>\n </div>\n <TabsContent value=\"schema\" className=\"mt-2\">\n <JsonEditor\n value={tableSchemaText}\n editablePaths={[\"/\"]}\n onChange={handleTableSchemaTextChange}\n height=\"280px\"\n className=\"rounded-md border overflow-hidden\"\n />\n </TabsContent>\n <TabsContent value=\"uischema\" className=\"mt-2\">\n <JsonEditor\n value={tableUiSchemaText}\n editablePaths={[\"/\"]}\n onChange={handleTableUiSchemaTextChange}\n height=\"280px\"\n className=\"rounded-md border overflow-hidden\"\n />\n </TabsContent>\n </Tabs>\n </div>\n </Card>\n </div>\n </PlaygroundSection>\n\n {/* Section 4: Local renderers demo */}\n <PlaygroundSection\n title=\"EntityTable with Local Renderers\"\n description=\"Same sample data rendered with x- prefixed local renderers passed via the renderers prop. The schema is pure data -- renderer functions live in code and are resolved by name. Three custom renderers: x-play-initials (avatar from name), x-play-role-icon (letter prefix from options), x-play-tenure (computed days with threshold).\"\n variant=\"card\"\n >\n <EntityTable<SampleRow>\n schema={CUSTOM_RENDERER_SCHEMA}\n renderers={CUSTOM_RENDERERS}\n data={{\n data: ALL_ROWS,\n meta: {\n total: ALL_ROWS.length,\n limit: ALL_ROWS.length,\n offset: 0,\n has_next: false,\n has_prev: false,\n },\n }}\n isLoading={false}\n isError={false}\n entityLabel=\"users\"\n />\n </PlaygroundSection>\n\n {/* Section 5: EntitySelect -- searchable select with mock fetcher */}\n <PlaygroundSection\n title=\"EntitySelect\"\n description=\"Searchable single-select backed by a static mock patient fetcher. Search text is filtered client-side. Available as a form widget via x-ui-widget: 'entity-select'.\"\n variant=\"card\"\n >\n <div className=\"flex gap-6 items-start\">\n <EntitySelect\n fetcher={patientFetcher}\n queryKey=\"playground-patients\"\n value={selectedPatient}\n onChange={setSelectedPatient}\n label=\"Patient\"\n placeholder=\"Select patient...\"\n searchPlaceholder=\"Search patients...\"\n className=\"max-w-xs\"\n />\n <Card className=\"flex-1 min-w-0 p-3\">\n <p className=\"text-xs font-medium text-muted-foreground mb-2\">\n Selected value\n </p>\n <pre className=\"rounded-md bg-muted px-4 py-3 text-xs overflow-auto\">\n {JSON.stringify(selectedPatient, null, 2)}\n </pre>\n </Card>\n </div>\n </PlaygroundSection>\n\n {/* Section 6: EntityTree -- schema-driven tree with static nested data */}\n <PlaygroundSection\n title=\"EntityTree\"\n description=\"Schema-driven tree component built on TreeView. Columns are resolved from a JSON Schema using the same resolveColumns pipeline as EntityTable. Supports expand/collapse, row selection, loading/error/empty states, and custom cell renderers.\"\n variant=\"card\"\n >\n <EntityTreeDemo />\n </PlaygroundSection>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// EntityTree demo\n// ---------------------------------------------------------------------------\n\ninterface OrgRow extends Record<string, unknown> {\n name: string;\n type: string;\n headcount: number;\n}\n\nconst OrgSchema = z.object({\n name: z.string().meta({ title: \"Name\", \"x-ui-column\": { order: 0 } }),\n type: z.string().meta({ title: \"Type\", \"x-ui-column\": { order: 1 } }),\n headcount: z\n .number()\n .meta({ title: \"Headcount\", \"x-ui-column\": { order: 2 } }),\n});\n\nconst ORG_TREE_SCHEMA = toJsonSchema(OrgSchema);\n\nconst ORG_NODES: TreeNode<OrgRow>[] = [\n {\n id: \"eng\",\n data: { name: \"Engineering\", type: \"Division\", headcount: 120 },\n hasChildren: true,\n children: [\n {\n id: \"frontend\",\n data: { name: \"Frontend\", type: \"Team\", headcount: 18 },\n hasChildren: true,\n children: [\n {\n id: \"design-sys\",\n data: { name: \"Design System\", type: \"Squad\", headcount: 5 },\n hasChildren: false,\n },\n ],\n },\n {\n id: \"backend\",\n data: { name: \"Backend\", type: \"Team\", headcount: 32 },\n hasChildren: false,\n },\n {\n id: \"infra\",\n data: { name: \"Infrastructure\", type: \"Team\", headcount: 14 },\n hasChildren: false,\n },\n ],\n },\n {\n id: \"product\",\n data: { name: \"Product\", type: \"Division\", headcount: 45 },\n hasChildren: true,\n children: [\n {\n id: \"research\",\n data: { name: \"Research\", type: \"Team\", headcount: 8 },\n hasChildren: false,\n },\n {\n id: \"pm\",\n data: { name: \"Product Management\", type: \"Team\", headcount: 12 },\n hasChildren: false,\n },\n ],\n },\n {\n id: \"ops\",\n data: { name: \"Operations\", type: \"Division\", headcount: 30 },\n hasChildren: false,\n },\n];\n\nfunction EntityTreeDemo() {\n const {\n expandedIds: treeExpandedIds,\n onExpand: onTreeExpand,\n onCollapse: onTreeCollapse,\n } = useTreeExpansion();\n const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());\n const [activeId, setActiveId] = useState<string | null>(null);\n\n return (\n <div className=\"space-y-4\">\n <EntityTree<OrgRow>\n schema={ORG_TREE_SCHEMA}\n nodes={ORG_NODES}\n expandedIds={treeExpandedIds}\n onExpand={onTreeExpand}\n onCollapse={onTreeCollapse}\n onNodeSelect={(node) => setActiveId(node.id)}\n onNodeEdit={(node) => setActiveId(node.id)}\n activeNodeId={activeId ?? undefined}\n selectedIds={selectedIds}\n onSelectionChange={(id, selected) =>\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 entityLabel=\"departments\"\n />\n <div className=\"flex gap-6 text-xs text-muted-foreground\">\n {activeId && (\n <span>\n Active: <span className=\"font-mono\">{activeId}</span>\n </span>\n )}\n {selectedIds.size > 0 && (\n <span>\n Selected:{\" \"}\n <span className=\"font-mono\">{[...selectedIds].join(\", \")}</span>\n </span>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}