@petrarca/sonnet-playground 0.7.0 → 0.9.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 (76) hide show
  1. package/README.md +10 -8
  2. package/dist/{PlayAdvancedComponents-ZYK66UII.js → PlayAdvancedComponents-VMUI472R.js} +2 -2
  3. package/dist/PlayCodeEditor-AMTFE5SW.js +8 -0
  4. package/dist/PlayCodedValues-G2EVIVMO.js +9 -0
  5. package/dist/{PlayCoreComponents-YTEAS3GL.js → PlayCoreComponents-EQ2BMY2S.js} +2 -2
  6. package/dist/{PlayDataComponents-W44OITT5.js → PlayDataComponents-W2KQHOI7.js} +2 -2
  7. package/dist/PlayFhirQuestionnaire-TO35Q7CP.js +8 -0
  8. package/dist/{PlayFormWidgets-6JYFRTAL.js → PlayFormWidgets-HP3VF2LK.js} +2 -2
  9. package/dist/PlayForms-4CQNEBLS.js +7 -0
  10. package/dist/PlayGraph-25ZKQAQR.js +7 -0
  11. package/dist/PlayGraph-25ZKQAQR.js.map +1 -0
  12. package/dist/PlayMarkdownViewer-X6AIFO2U.js +8 -0
  13. package/dist/PlayMarkdownViewer-X6AIFO2U.js.map +1 -0
  14. package/dist/PlayQuestionnaireDesigner-IR7TKSOT.js +9 -0
  15. package/dist/PlayQuestionnaireDesigner-IR7TKSOT.js.map +1 -0
  16. package/dist/PlaySchemaDesigner-ZQBA7AYO.js +8 -0
  17. package/dist/PlaySchemaDesigner-ZQBA7AYO.js.map +1 -0
  18. package/dist/{PlayShellApi-5O6VYR2X.js → PlayShellApi-MMCQ2AKK.js} +2 -2
  19. package/dist/PlayShellApi-MMCQ2AKK.js.map +1 -0
  20. package/dist/chunk-3FYM6B3E.js +1163 -0
  21. package/dist/chunk-3FYM6B3E.js.map +1 -0
  22. package/dist/{chunk-CQ6PGFRV.js → chunk-3RZHYZRL.js} +57 -1
  23. package/dist/chunk-3RZHYZRL.js.map +1 -0
  24. package/dist/chunk-7IMCPUSI.js +100 -0
  25. package/dist/chunk-7IMCPUSI.js.map +1 -0
  26. package/dist/{chunk-2XMWOZ5O.js → chunk-EPCUUTBZ.js} +48 -41
  27. package/dist/chunk-EPCUUTBZ.js.map +1 -0
  28. package/dist/{chunk-I2FLG6ZD.js → chunk-LDCNLHO2.js} +195 -18
  29. package/dist/chunk-LDCNLHO2.js.map +1 -0
  30. package/dist/chunk-LVV32F7G.js +104 -0
  31. package/dist/chunk-LVV32F7G.js.map +1 -0
  32. package/dist/chunk-OUL3DN2E.js +510 -0
  33. package/dist/chunk-OUL3DN2E.js.map +1 -0
  34. package/dist/chunk-QKFQI4VX.js +83 -0
  35. package/dist/chunk-QKFQI4VX.js.map +1 -0
  36. package/dist/{chunk-6WI3N7JI.js → chunk-RGBSHXS5.js} +145 -4
  37. package/dist/chunk-RGBSHXS5.js.map +1 -0
  38. package/dist/{chunk-UB7462QG.js → chunk-RLJI5VMP.js} +72 -1
  39. package/dist/chunk-RLJI5VMP.js.map +1 -0
  40. package/dist/chunk-VGAS5Z6X.js +543 -0
  41. package/dist/chunk-VGAS5Z6X.js.map +1 -0
  42. package/dist/chunk-VKZ2RJFL.js +647 -0
  43. package/dist/chunk-VKZ2RJFL.js.map +1 -0
  44. package/dist/chunk-WR74TMW4.js +219 -0
  45. package/dist/chunk-WR74TMW4.js.map +1 -0
  46. package/dist/{chunk-E5X7GVLU.js → chunk-XNDD4UN4.js} +2 -2
  47. package/dist/chunk-XNDD4UN4.js.map +1 -0
  48. package/dist/chunk-YTGQRDD2.js +343 -0
  49. package/dist/chunk-YTGQRDD2.js.map +1 -0
  50. package/dist/index.d.ts +13 -10
  51. package/dist/index.js +72 -11
  52. package/dist/index.js.map +1 -1
  53. package/dist/pages/index.d.ts +56 -20
  54. package/dist/pages/index.js +39 -17
  55. package/package.json +15 -14
  56. package/dist/PlayForms-L532W3JL.js +0 -7
  57. package/dist/PlayGraph-M4KQSFI7.js +0 -7
  58. package/dist/PlaySchemaDesigner-S4DBB53G.js +0 -7
  59. package/dist/chunk-2XMWOZ5O.js.map +0 -1
  60. package/dist/chunk-4Y4JFKAK.js +0 -240
  61. package/dist/chunk-4Y4JFKAK.js.map +0 -1
  62. package/dist/chunk-6WI3N7JI.js.map +0 -1
  63. package/dist/chunk-CQ6PGFRV.js.map +0 -1
  64. package/dist/chunk-E5X7GVLU.js.map +0 -1
  65. package/dist/chunk-I2FLG6ZD.js.map +0 -1
  66. package/dist/chunk-O2QMWJZI.js +0 -881
  67. package/dist/chunk-O2QMWJZI.js.map +0 -1
  68. package/dist/chunk-UB7462QG.js.map +0 -1
  69. /package/dist/{PlayAdvancedComponents-ZYK66UII.js.map → PlayAdvancedComponents-VMUI472R.js.map} +0 -0
  70. /package/dist/{PlayCoreComponents-YTEAS3GL.js.map → PlayCodeEditor-AMTFE5SW.js.map} +0 -0
  71. /package/dist/{PlayDataComponents-W44OITT5.js.map → PlayCodedValues-G2EVIVMO.js.map} +0 -0
  72. /package/dist/{PlayFormWidgets-6JYFRTAL.js.map → PlayCoreComponents-EQ2BMY2S.js.map} +0 -0
  73. /package/dist/{PlayForms-L532W3JL.js.map → PlayDataComponents-W2KQHOI7.js.map} +0 -0
  74. /package/dist/{PlayGraph-M4KQSFI7.js.map → PlayFhirQuestionnaire-TO35Q7CP.js.map} +0 -0
  75. /package/dist/{PlaySchemaDesigner-S4DBB53G.js.map → PlayFormWidgets-HP3VF2LK.js.map} +0 -0
  76. /package/dist/{PlayShellApi-5O6VYR2X.js.map → PlayForms-4CQNEBLS.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pages/PlayDataComponents.tsx","../src/pages/EntityTableLongListDemo.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 type SortingState,\n type TableDensity,\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 { EntityTableLongListDemo } from \"./EntityTableLongListDemo\";\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 // An array facet is repeatable: one chip per role, matching any of them.\n roles: z\n .array(z.enum([\"admin\", \"editor\", \"viewer\"]))\n .optional()\n .meta({ \"x-ui-title\": \"Role\" }),\n joined_from: z.string().optional().meta({\n \"x-ui-title\": \"Joined from\",\n \"x-ui-widget\": \"date\",\n }),\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, sortable: true },\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, sortable: true },\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 DENSITY_OPTIONS = [\n \"default\",\n \"compact\",\n] as const satisfies readonly TableDensity[];\nconst LAYOUT_OPTIONS = [\"flow\", \"fill\"] as const;\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// The filters of a free-text search (textKey): the query is typed, these are\n// picked.\nconst FREE_TEXT_FACETS = toJsonSchema(\n z.object({\n source: z\n .enum([\"billing-api\", \"billing-web\", \"handbook\"])\n .optional()\n .meta({ \"x-ui-title\": \"Source\" }),\n tags: z.array(z.string()).optional().meta({ \"x-ui-title\": \"Tag\" }),\n ranking: z\n .enum([\"rerank\", \"none\"])\n .optional()\n .meta({\n \"x-ui-title\": \"Ranking\",\n \"x-ui-options\": { enumNames: { rerank: \"Rerank\", none: \"No rerank\" } },\n }),\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 2b: free text with filters (textKey)\n const [freeTextExpr, setFreeTextExpr] = useState<FilterExpr>(EMPTY_FILTER);\n const [freeTextMode, setFreeTextMode] = useState<SearchMode>(\"explicit\");\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 // Sorting is the \"server's\": the table reports it, this query applies it.\n const [tableSorting, setTableSorting] = useState<SortingState>([]);\n const [tableDensity, setTableDensity] = useState<TableDensity>(\"default\");\n const [tableLayout, setTableLayout] =\n useState<(typeof LAYOUT_OPTIONS)[number]>(\"flow\");\n\n const filteredRows = useMemo(() => {\n const terms = flattenFilterExpr(tableExpr);\n // Repeatable facet: several roles match any of them.\n const roles = terms.filter((t) => t.key === \"roles\").map((t) => t.value);\n const rows = ALL_ROWS.filter(\n (row) =>\n (roles.length === 0 || roles.includes(row.role)) &&\n terms.every(({ key, value }) => {\n const v = value.toLowerCase();\n if (key === \"roles\") return true;\n if (key === \"status\") return row.status.toLowerCase().includes(v);\n if (key === \"joined_from\") return row.joined >= value;\n // default: search by name\n return row.name.toLowerCase().includes(v);\n }),\n );\n const [order] = tableSorting;\n if (!order) return rows;\n const field = order.id as keyof SampleRow;\n const sorted = [...rows].sort((a, b) => a[field].localeCompare(b[field]));\n return order.desc ? sorted.reverse() : sorted;\n }, [tableExpr, tableSorting]);\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 free text with filters), EntityTable (with schema editor and custom\n renderers), EntitySelect, 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 2b: free text with filters -- one field for both */}\n <PlaygroundSection\n title=\"SearchInput — free text with filters (textKey)\"\n description=\"One field for a query and its filters. Type the query; pick filters with the chevron or ArrowDown. Explicit: Enter submits the text (as the textKey term) with the chips. Debounce: they fire as typing pauses. A removed chip reruns at once; enum chips show their labels.\"\n variant=\"card\"\n >\n <div className=\"flex flex-col gap-3 max-w-2xl\">\n <ToggleStrip\n label=\"Mode\"\n options={MODE_OPTIONS}\n value={freeTextMode}\n onChange={setFreeTextMode}\n format={(m) => MODE_LABELS[m]}\n />\n <SearchInput\n value={freeTextExpr}\n onChange={setFreeTextExpr}\n schema={FREE_TEXT_FACETS}\n textKey=\"q\"\n mode={freeTextMode}\n showSearchButton\n placeholder=\"Search for code or content...\"\n />\n <FilterExprInspector expr={freeTextExpr} />\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. Role is a repeatable facet (one chip per role) and Joined from uses the date widget. Name and Joined are sortable: click a header -- the table reports the order and the page's query applies it. Density compact tightens the rows and drops the lines between them; layout fill puts the table in a fixed-height box where the rows scroll under a header that stays on top. 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 <div className=\"mb-4 flex flex-wrap gap-6\">\n <ToggleStrip\n label=\"Density\"\n options={DENSITY_OPTIONS}\n value={tableDensity}\n onChange={setTableDensity}\n />\n <ToggleStrip\n label=\"Layout\"\n options={LAYOUT_OPTIONS}\n value={tableLayout}\n onChange={setTableLayout}\n />\n </div>\n <div className={tableLayout === \"fill\" ? \"h-64\" : undefined}>\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 sorting={tableSorting}\n onSortingChange={setTableSorting}\n density={tableDensity}\n fill={tableLayout === \"fill\"}\n />\n </div>\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 <EntityTableLongListDemo />\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 property display used by detail pages, panels and graph node/edge cards. With no schema, values render by JS shape; an optional per-property schema refines rendering (date/datetime/boolean/number/x-ui-cell). With an object schema, the schema decides the fields, their order, labels (x-ui-title) and cells (x-ui-cell, or a local x- renderer), as for EntityTable. Density: compact (an inspector) or comfortable (a detail page: label column, no rules between rows).\"\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: \"acme_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 <Card className=\"p-4 sm:col-span-2\">\n <p className=\"mb-3 text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n Object schema, comfortable (a detail page)\n </p>\n <PropertyList\n properties={DETAIL_SAMPLE}\n schema={DETAIL_SCHEMA}\n renderers={DETAIL_RENDERERS}\n density=\"comfortable\"\n copyable={false}\n />\n </Card>\n </div>\n );\n}\n\n// A detail page's view: fields in schema order, labels from x-ui-title, cells\n// from x-ui-cell -- built-in (code, badge, datetime, join) or local (x-links).\nconst DetailSchema = z.object({\n program: z.string().meta({ \"x-ui-title\": \"Program\", \"x-ui-cell\": \"code\" }),\n status: z.string().meta({\n \"x-ui-title\": \"Status\",\n \"x-ui-cell\": \"badge\",\n \"x-ui-cell-options\": { colors: { available: \"green\", missing: \"red\" } },\n }),\n exit_codes: z.array(z.number()).meta({ \"x-ui-title\": \"Success exit codes\" }),\n version_args: z.array(z.string()).meta({\n \"x-ui-title\": \"Version check\",\n \"x-ui-cell\": \"join\",\n \"x-ui-cell-options\": { separator: \" \" },\n }),\n used_by: z\n .array(z.string())\n .meta({ \"x-ui-title\": \"Run by\", \"x-ui-cell\": \"x-links\" }),\n updated_at: z.string().meta({ \"x-ui-title\": \"Updated\", format: \"date-time\" }),\n internal_id: z.string().meta({ \"x-ui-column\": { hidden: true } }),\n});\n\nconst DETAIL_SCHEMA = toJsonSchema(DetailSchema);\n\nconst DETAIL_SAMPLE: Record<string, unknown> = {\n program: \"trivy\",\n status: \"available\",\n exit_codes: [0, 1],\n version_args: [\"--version\"],\n used_by: [\"acme.scan\", \"acme.nightly\"],\n updated_at: \"2026-10-30T14:05:00Z\",\n internal_id: \"not shown\",\n};\n\nconst DETAIL_RENDERERS = {\n \"x-links\": createRenderer((row) => {\n const items = (row.used_by as string[] | undefined) ?? [];\n if (!items.length)\n return <span className=\"text-muted-foreground\">none</span>;\n return items.map((item, i) => (\n <React.Fragment key={item}>\n {i > 0 && \", \"}\n <a href=\"#\" className=\"text-primary hover:underline\">\n {item}\n </a>\n </React.Fragment>\n ));\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","/**\n * EntityTable on a long list: 5,000 generated rows in a fill box, compact, to\n * try how the rows arrive -- in pages, with a \"Load more\" footer, or loaded as\n * the end scrolls into view -- and virtual rows (only the rows in view are in\n * the DOM). The \"server\" is in memory, a page answered after a short delay so\n * the loading states show.\n */\nimport React, { useCallback, useEffect, useMemo, useState } from \"react\";\nimport {\n EntityTable,\n type PaginationState,\n type TableLoadMore,\n} from \"@petrarca/sonnet-ui\";\nimport type { JsonSchema } from \"@petrarca/sonnet-core/schema\";\nimport { PlaygroundSection } from \"../PlaygroundSection\";\n\ninterface FileRow {\n id: string;\n name: string;\n folder: string;\n size: number;\n}\n\nconst TOTAL = 5000;\nconst PAGE_SIZE = 100;\nconst DELAY_MS = 300;\n\nconst ROWS: FileRow[] = Array.from({ length: TOTAL }, (_, i) => ({\n id: `f-${i}`,\n name: `file-${String(i).padStart(4, \"0\")}.ts`,\n folder: `src/module-${i % 37}/part-${i % 7}`,\n size: (i * 7919) % 400,\n}));\n\nconst SCHEMA: JsonSchema = {\n title: \"File\",\n type: \"object\",\n properties: {\n name: { type: \"string\", title: \"Name\", \"x-ui-cell\": \"code\" },\n size: { type: \"number\", title: \"Chunks\" },\n folder: { type: \"string\", title: \"Folder\", \"x-ui-cell\": \"muted\" },\n },\n};\n\nconst PAGINGS = [\"pages\", \"load more\", \"on scroll\"] as const;\ntype Paging = (typeof PAGINGS)[number];\n\nconst page = (rows: FileRow[]) => ({\n data: rows,\n meta: {\n total: TOTAL,\n limit: rows.length,\n offset: 0,\n has_next: rows.length < TOTAL,\n has_prev: false,\n },\n});\n\n// Rows loaded progressively: a page at a time, after a delay.\nfunction useProgressiveRows(paging: Paging): {\n rows: FileRow[];\n loadMore: TableLoadMore;\n} {\n const [loaded, setLoaded] = useState(PAGE_SIZE);\n const [isLoading, setIsLoading] = useState(false);\n useEffect(() => setLoaded(PAGE_SIZE), [paging]);\n const onLoadMore = useCallback(() => {\n setIsLoading(true);\n window.setTimeout(() => {\n setLoaded((n) => Math.min(n + PAGE_SIZE, TOTAL));\n setIsLoading(false);\n }, DELAY_MS);\n }, []);\n return {\n rows: ROWS.slice(0, loaded),\n loadMore: {\n hasMore: loaded < TOTAL,\n isLoading,\n onLoadMore,\n auto: paging === \"on scroll\",\n },\n };\n}\n\nfunction Toggle<T extends string>({\n label,\n options,\n value,\n onChange,\n}: {\n label: string;\n options: readonly T[];\n value: T;\n onChange: (v: T) => void;\n}): React.ReactElement {\n return (\n <div className=\"flex items-center gap-2\" role=\"group\" aria-label={label}>\n <span className=\"text-xs text-muted-foreground\">{label}:</span>\n {options.map((option) => (\n <button\n key={option}\n type=\"button\"\n aria-pressed={option === value}\n onClick={() => onChange(option)}\n className={\n option === value\n ? \"rounded-full bg-primary px-3 py-1 text-xs font-medium text-primary-foreground\"\n : \"rounded-full bg-muted px-3 py-1 text-xs font-medium text-muted-foreground hover:text-foreground\"\n }\n >\n {option}\n </button>\n ))}\n </div>\n );\n}\n\nexport function EntityTableLongListDemo(): React.ReactElement {\n const [paging, setPaging] = useState<Paging>(\"on scroll\");\n const [virtual, setVirtual] = useState<\"off\" | \"on\">(\"on\");\n const [pagination, setPagination] = useState<PaginationState>({\n pageIndex: 0,\n pageSize: PAGE_SIZE,\n });\n const progressive = useProgressiveRows(paging);\n const paged = useMemo(() => {\n const from = pagination.pageIndex * pagination.pageSize;\n return ROWS.slice(from, from + pagination.pageSize);\n }, [pagination]);\n\n const byPages = paging === \"pages\";\n return (\n <PlaygroundSection\n title=\"EntityTable on a long list\"\n description=\"5,000 rows in a fill box (compact). Pages: the page controls. Load more: a footer button adds the next 100 rows. On scroll: the next rows load as the end comes into view (no button needed). Virtual rows: only the rows in view are rendered -- open the DOM inspector and scroll.\"\n variant=\"card\"\n >\n <div className=\"mb-4 flex flex-wrap gap-6\">\n <Toggle\n label=\"Rows\"\n options={PAGINGS}\n value={paging}\n onChange={setPaging}\n />\n <Toggle\n label=\"Virtual rows\"\n options={[\"off\", \"on\"] as const}\n value={virtual}\n onChange={setVirtual}\n />\n </div>\n <div className=\"h-80\">\n <EntityTable<FileRow>\n schema={SCHEMA}\n data={page(byPages ? paged : progressive.rows)}\n isLoading={false}\n isError={false}\n entityLabel=\"files\"\n density=\"compact\"\n fill\n virtualize={virtual === \"on\"}\n getRowId={(row) => row.id}\n {...(byPages\n ? { pagination, onPaginationChange: setPagination }\n : { loadMore: progressive.loadMore })}\n />\n </div>\n </PlaygroundSection>\n );\n}\n"],"mappings":"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","names":["React","useState","useMemo","useCallback","EntityTable","jsx","jsxs","useState","useCallback","useMemo","EntityTable","React"]}
@@ -3,8 +3,10 @@ import {
3
3
  } from "./chunk-C2EZ2ECG.js";
4
4
 
5
5
  // src/pages/PlayShellApi.tsx
6
+ import { useState } from "react";
6
7
  import { Button } from "@petrarca/sonnet-ui";
7
8
  import {
9
+ useCollapsedSubNav,
8
10
  notification,
9
11
  dialog,
10
12
  navigation,
@@ -13,6 +15,8 @@ import {
13
15
  } from "@petrarca/sonnet-shell";
14
16
  import { jsx, jsxs } from "react/jsx-runtime";
15
17
  function PlayShellApi() {
18
+ const [focused, setFocused] = useState(false);
19
+ useCollapsedSubNav(focused);
16
20
  return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
17
21
  /* @__PURE__ */ jsx(
18
22
  PlaygroundSection,
@@ -57,6 +61,21 @@ function PlayShellApi() {
57
61
  children: "info()"
58
62
  }
59
63
  ),
64
+ /* @__PURE__ */ jsx(
65
+ Button,
66
+ {
67
+ variant: "outline",
68
+ size: "sm",
69
+ onClick: () => notification.success("Flow assigned to product.", {
70
+ description: "acme reads its default.",
71
+ action: {
72
+ label: "Give acme its own value",
73
+ onClick: () => notification.info("Opening acme's value.")
74
+ }
75
+ }),
76
+ children: "success() with action"
77
+ }
78
+ ),
60
79
  /* @__PURE__ */ jsx(
61
80
  Button,
62
81
  {
@@ -111,6 +130,26 @@ function PlayShellApi() {
111
130
  children: "confirm() \u2014 destructive"
112
131
  }
113
132
  ),
133
+ /* @__PURE__ */ jsx(
134
+ Button,
135
+ {
136
+ variant: "outline",
137
+ size: "sm",
138
+ onClick: async () => {
139
+ const confirmed = await dialog.confirm({
140
+ title: "Delete source acme-billing",
141
+ description: "Removes the source and everything indexed from it.",
142
+ confirmLabel: "Delete",
143
+ variant: "destructive",
144
+ confirmText: "acme-billing"
145
+ });
146
+ notification.info(
147
+ confirmed ? "User confirmed." : "User cancelled."
148
+ );
149
+ },
150
+ children: "confirm() \u2014 type the name"
151
+ }
152
+ ),
114
153
  /* @__PURE__ */ jsx(
115
154
  Button,
116
155
  {
@@ -315,6 +354,23 @@ function PlayShellApi() {
315
354
  ] })
316
355
  }
317
356
  ),
357
+ /* @__PURE__ */ jsx(
358
+ PlaygroundSection,
359
+ {
360
+ title: "useCollapsedSubNav",
361
+ description: "A page that needs the full content width (a canvas, an editor) collapses the sub-navigation while it is shown. Leaving the page restores the user's own setting; the user can still expand it meanwhile.",
362
+ variant: "card",
363
+ children: /* @__PURE__ */ jsx(
364
+ Button,
365
+ {
366
+ variant: "outline",
367
+ size: "sm",
368
+ onClick: () => setFocused((f) => !f),
369
+ children: focused ? "useCollapsedSubNav(false)" : "useCollapsedSubNav(true)"
370
+ }
371
+ )
372
+ }
373
+ ),
318
374
  /* @__PURE__ */ jsx(
319
375
  PlaygroundSection,
320
376
  {
@@ -338,4 +394,4 @@ function PlayShellApi() {
338
394
  export {
339
395
  PlayShellApi
340
396
  };
341
- //# sourceMappingURL=chunk-CQ6PGFRV.js.map
397
+ //# sourceMappingURL=chunk-3RZHYZRL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pages/PlayShellApi.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { Button } from \"@petrarca/sonnet-ui\";\nimport {\n useCollapsedSubNav,\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 * the command menu (Cmd+K), and useCollapsedSubNav.\n */\nexport default function PlayShellApi() {\n const [focused, setFocused] = useState(false);\n useCollapsedSubNav(focused);\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.success(\"Flow assigned to product.\", {\n description: \"acme reads its default.\",\n action: {\n label: \"Give acme its own value\",\n onClick: () => notification.info(\"Opening acme's value.\"),\n },\n })\n }\n >\n success() with action\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: \"Delete source acme-billing\",\n description:\n \"Removes the source and everything indexed from it.\",\n confirmLabel: \"Delete\",\n variant: \"destructive\",\n confirmText: \"acme-billing\",\n });\n notification.info(\n confirmed ? \"User confirmed.\" : \"User cancelled.\",\n );\n }}\n >\n confirm() — type the name\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 {/* ── useCollapsedSubNav ───────────────────────────────────── */}\n <PlaygroundSection\n title=\"useCollapsedSubNav\"\n description=\"A page that needs the full content width (a canvas, an editor) collapses the sub-navigation while it is shown. Leaving the page restores the user's own setting; the user can still expand it meanwhile.\"\n variant=\"card\"\n >\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setFocused((f) => !f)}\n >\n {focused ? \"useCollapsedSubNav(false)\" : \"useCollapsedSubNav(true)\"}\n </Button>\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":[]}
@@ -0,0 +1,100 @@
1
+ import {
2
+ PlaygroundSection
3
+ } from "./chunk-C2EZ2ECG.js";
4
+
5
+ // src/pages/PlayMarkdownViewer.tsx
6
+ import { useEffect, useState } from "react";
7
+ import { MarkdownViewer } from "@petrarca/sonnet-ui/markdown";
8
+ import { Button } from "@petrarca/sonnet-ui";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ var DOCUMENT = `# Release notes
11
+
12
+ The **file browser** shows a tree by source and folder; a *search hit* opens
13
+ the file at its lines. ~~Flat list only~~ is gone.
14
+
15
+ ## What changed
16
+
17
+ - [x] Folders open page by page
18
+ - [x] Files show in the code editor
19
+ - [ ] An outline from the code graph
20
+
21
+ | Area | Before | After |
22
+ |---|---|---|
23
+ | Files | flat table | tree + viewer |
24
+ | Search | two forms | one field |
25
+
26
+ \`\`\`python
27
+ def handler(request: dict) -> dict:
28
+ """Answer one request."""
29
+ return {"ok": True, "items": [1, 2, 3]}
30
+ \`\`\`
31
+
32
+ \`\`\`mermaid
33
+ graph LR
34
+ Search -->|hit| Files
35
+ Files --> Viewer
36
+ Viewer --> Metadata
37
+ \`\`\`
38
+
39
+ > Raw HTML is sanitized: <b>bold</b> stays, scripts and handlers go.
40
+ `;
41
+ var ANSWER = "The query found **3 sources**. The largest is `acme-platform`:\n\n```cypher\nMATCH (s:Source) RETURN s.name, s.files ORDER BY s.files DESC\n```\n\n| Source | Files |\n|---|---|\n| acme-platform | 19978 |\n| acme-portal | 799 |";
42
+ function useStreamedText(text, run) {
43
+ const [shown, setShown] = useState("");
44
+ useEffect(() => {
45
+ setShown("");
46
+ let at = 0;
47
+ const timer = setInterval(() => {
48
+ at = Math.min(text.length, at + 6);
49
+ setShown(text.slice(0, at));
50
+ if (at === text.length) clearInterval(timer);
51
+ }, 40);
52
+ return () => clearInterval(timer);
53
+ }, [text, run]);
54
+ return { shown, done: shown.length === text.length };
55
+ }
56
+ function PlayMarkdownViewer() {
57
+ const [run, setRun] = useState(0);
58
+ const { shown, done } = useStreamedText(ANSWER, run);
59
+ return /* @__PURE__ */ jsxs("div", { className: "w-full max-w-4xl space-y-6", children: [
60
+ /* @__PURE__ */ jsxs("div", { children: [
61
+ /* @__PURE__ */ jsx("h1", { children: "Markdown Viewer" }),
62
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Markdown for reading: GitHub-flavoured, code blocks in the code editor, Mermaid diagrams (loaded only when a document has one), and untrusted content sanitized." })
63
+ ] }),
64
+ /* @__PURE__ */ jsx(
65
+ PlaygroundSection,
66
+ {
67
+ title: "A document",
68
+ description: "Headings, emphasis, a task list, a table, a code block, a diagram, and sanitized raw HTML.",
69
+ variant: "card",
70
+ children: /* @__PURE__ */ jsx(MarkdownViewer, { content: DOCUMENT })
71
+ }
72
+ ),
73
+ /* @__PURE__ */ jsxs(
74
+ PlaygroundSection,
75
+ {
76
+ title: "A streamed answer",
77
+ description: "streaming: incomplete Markdown is closed as it arrives and new text fades in -- for a chat.",
78
+ variant: "card",
79
+ children: [
80
+ /* @__PURE__ */ jsx(MarkdownViewer, { content: shown, streaming: !done }),
81
+ /* @__PURE__ */ jsx(
82
+ Button,
83
+ {
84
+ variant: "outline",
85
+ size: "sm",
86
+ className: "mt-3",
87
+ onClick: () => setRun((n) => n + 1),
88
+ children: "Stream again"
89
+ }
90
+ )
91
+ ]
92
+ }
93
+ )
94
+ ] });
95
+ }
96
+
97
+ export {
98
+ PlayMarkdownViewer
99
+ };
100
+ //# sourceMappingURL=chunk-7IMCPUSI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pages/PlayMarkdownViewer.tsx"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport { MarkdownViewer } from \"@petrarca/sonnet-ui/markdown\";\nimport { Button } from \"@petrarca/sonnet-ui\";\nimport { PlaygroundSection } from \"../PlaygroundSection\";\n\nconst DOCUMENT = `# Release notes\n\nThe **file browser** shows a tree by source and folder; a *search hit* opens\nthe file at its lines. ~~Flat list only~~ is gone.\n\n## What changed\n\n- [x] Folders open page by page\n- [x] Files show in the code editor\n- [ ] An outline from the code graph\n\n| Area | Before | After |\n|---|---|---|\n| Files | flat table | tree + viewer |\n| Search | two forms | one field |\n\n\\`\\`\\`python\ndef handler(request: dict) -> dict:\n \"\"\"Answer one request.\"\"\"\n return {\"ok\": True, \"items\": [1, 2, 3]}\n\\`\\`\\`\n\n\\`\\`\\`mermaid\ngraph LR\n Search -->|hit| Files\n Files --> Viewer\n Viewer --> Metadata\n\\`\\`\\`\n\n> Raw HTML is sanitized: <b>bold</b> stays, scripts and handlers go.\n`;\n\nconst ANSWER =\n \"The query found **3 sources**. The largest is `acme-platform`:\\n\\n\" +\n \"```cypher\\nMATCH (s:Source) RETURN s.name, s.files ORDER BY s.files DESC\\n```\\n\\n\" +\n \"| Source | Files |\\n|---|---|\\n| acme-platform | 19978 |\\n| acme-portal | 799 |\";\n\n// The answer arriving a few characters at a time, as a chat would show it.\nfunction useStreamedText(text: string, run: number) {\n const [shown, setShown] = useState(\"\");\n useEffect(() => {\n setShown(\"\");\n let at = 0;\n const timer = setInterval(() => {\n at = Math.min(text.length, at + 6);\n setShown(text.slice(0, at));\n if (at === text.length) clearInterval(timer);\n }, 40);\n return () => clearInterval(timer);\n }, [text, run]);\n return { shown, done: shown.length === text.length };\n}\n\n/** PlayMarkdownViewer -- a document, and a streamed chat answer. */\nexport default function PlayMarkdownViewer() {\n const [run, setRun] = useState(0);\n const { shown, done } = useStreamedText(ANSWER, run);\n return (\n <div className=\"w-full max-w-4xl space-y-6\">\n <div>\n <h1>Markdown Viewer</h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n Markdown for reading: GitHub-flavoured, code blocks in the code\n editor, Mermaid diagrams (loaded only when a document has one), and\n untrusted content sanitized.\n </p>\n </div>\n\n <PlaygroundSection\n title=\"A document\"\n description=\"Headings, emphasis, a task list, a table, a code block, a diagram, and sanitized raw HTML.\"\n variant=\"card\"\n >\n <MarkdownViewer content={DOCUMENT} />\n </PlaygroundSection>\n\n <PlaygroundSection\n title=\"A streamed answer\"\n description=\"streaming: incomplete Markdown is closed as it arrives and new text fades in -- for a chat.\"\n variant=\"card\"\n >\n <MarkdownViewer content={shown} streaming={!done} />\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"mt-3\"\n onClick={() => setRun((n) => n + 1)}\n >\n Stream again\n </Button>\n </PlaygroundSection>\n </div>\n );\n}\n"],"mappings":";;;;;AAAA,SAAS,WAAW,gBAAgB;AACpC,SAAS,sBAAsB;AAC/B,SAAS,cAAc;AA8DjB,SACE,KADF;AA3DN,IAAM,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgCjB,IAAM,SACJ;AAKF,SAAS,gBAAgB,MAAc,KAAa;AAClD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AACrC,YAAU,MAAM;AACd,aAAS,EAAE;AACX,QAAI,KAAK;AACT,UAAM,QAAQ,YAAY,MAAM;AAC9B,WAAK,KAAK,IAAI,KAAK,QAAQ,KAAK,CAAC;AACjC,eAAS,KAAK,MAAM,GAAG,EAAE,CAAC;AAC1B,UAAI,OAAO,KAAK,OAAQ,eAAc,KAAK;AAAA,IAC7C,GAAG,EAAE;AACL,WAAO,MAAM,cAAc,KAAK;AAAA,EAClC,GAAG,CAAC,MAAM,GAAG,CAAC;AACd,SAAO,EAAE,OAAO,MAAM,MAAM,WAAW,KAAK,OAAO;AACrD;AAGe,SAAR,qBAAsC;AAC3C,QAAM,CAAC,KAAK,MAAM,IAAI,SAAS,CAAC;AAChC,QAAM,EAAE,OAAO,KAAK,IAAI,gBAAgB,QAAQ,GAAG;AACnD,SACE,qBAAC,SAAI,WAAU,8BACb;AAAA,yBAAC,SACC;AAAA,0BAAC,QAAG,6BAAe;AAAA,MACnB,oBAAC,OAAE,WAAU,sCAAqC,8KAIlD;AAAA,OACF;AAAA,IAEA;AAAA,MAAC;AAAA;AAAA,QACC,OAAM;AAAA,QACN,aAAY;AAAA,QACZ,SAAQ;AAAA,QAER,8BAAC,kBAAe,SAAS,UAAU;AAAA;AAAA,IACrC;AAAA,IAEA;AAAA,MAAC;AAAA;AAAA,QACC,OAAM;AAAA,QACN,aAAY;AAAA,QACZ,SAAQ;AAAA,QAER;AAAA,8BAAC,kBAAe,SAAS,OAAO,WAAW,CAAC,MAAM;AAAA,UAClD;AAAA,YAAC;AAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,WAAU;AAAA,cACV,SAAS,MAAM,OAAO,CAAC,MAAM,IAAI,CAAC;AAAA,cACnC;AAAA;AAAA,UAED;AAAA;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;","names":[]}
@@ -1,10 +1,24 @@
1
+ import {
2
+ DesignerControls
3
+ } from "./chunk-QKFQI4VX.js";
4
+
1
5
  // src/pages/PlaySchemaDesigner.tsx
2
6
  import { useState } from "react";
3
7
  import {
4
8
  SchemaDesigner
5
9
  } from "@petrarca/sonnet-schema-designer";
6
- import { FormSelect } from "@petrarca/sonnet-forms";
7
10
  import { jsx, jsxs } from "react/jsx-runtime";
11
+ var CONTACT_SCHEMA = {
12
+ title: "Contact",
13
+ type: "object",
14
+ required: ["name"],
15
+ properties: {
16
+ name: { type: "string", title: "Name" },
17
+ email: { type: "string", format: "email", title: "Email" },
18
+ phone: { type: "string", title: "Phone" },
19
+ newsletter: { type: "boolean", title: "Send me the newsletter" }
20
+ }
21
+ };
8
22
  var SAMPLE_SCHEMA = {
9
23
  title: "Patient",
10
24
  type: "object",
@@ -216,23 +230,27 @@ var AUDIT_EDITABLE_PATHS = [
216
230
  "/properties/actor/properties/metadata/properties",
217
231
  "/properties/targets/items/properties/metadata/properties"
218
232
  ];
233
+ var EXAMPLES = {
234
+ simple: { label: "Simple -- contact", schema: CONTACT_SCHEMA },
235
+ medium: { label: "Medium -- patient", schema: SAMPLE_SCHEMA },
236
+ advanced: { label: "Advanced -- checkout (logic)", schema: LOGIC_SCHEMA }
237
+ };
219
238
  var PROFILES = {
220
239
  full: {
221
240
  label: "Full (schema + uiSchema)",
222
241
  description: "Default: author the schema and its form presentation hints.",
223
- schema: SAMPLE_SCHEMA,
224
242
  capabilities: { previews: ["form", "table", "json", "capabilities"] }
225
243
  },
226
244
  data: {
227
245
  label: "Data schema only",
228
246
  description: "Pure JSON Schema (audit, terminology): no UI/Combined tabs, JSON preview only.",
229
- schema: SAMPLE_SCHEMA,
230
247
  capabilities: { mode: "data", previews: ["json", "capabilities"] }
231
248
  },
232
249
  scoped: {
233
250
  label: "Scoped (audit event)",
234
- description: "Fixed envelope; only the three metadata containers are editable.",
251
+ description: "Made for an audit event: its fixed envelope locked, only its three metadata containers editable.",
235
252
  schema: AUDIT_SCHEMA,
253
+ schemaLabel: "Audit event (the profile's own)",
236
254
  capabilities: {
237
255
  mode: "data",
238
256
  editablePaths: AUDIT_EDITABLE_PATHS,
@@ -242,56 +260,45 @@ var PROFILES = {
242
260
  structure: {
243
261
  label: "Structure only (no preview)",
244
262
  description: "Tree + inspector only; the center preview pane is hidden.",
245
- schema: SAMPLE_SCHEMA,
246
263
  capabilities: { mode: "data", previews: [] }
247
- },
248
- logic: {
249
- label: "Logic (variants + conditionals)",
250
- description: "Shows every logic construct: a oneOf variant, if/then/else conditionals, a const field, and a nullable optional.",
251
- schema: LOGIC_SCHEMA,
252
- capabilities: { previews: ["form", "table", "json", "capabilities"] }
253
264
  }
254
265
  };
255
266
  function PlaySchemaDesigner() {
267
+ const [exampleKey, setExampleKey] = useState("medium");
256
268
  const [profileKey, setProfileKey] = useState("full");
257
269
  const profile = PROFILES[profileKey];
258
- const [schema, setSchema] = useState(profile.schema);
270
+ const [schema, setSchema] = useState(EXAMPLES.medium.schema);
259
271
  const [uiSchema, setUiSchema] = useState({});
272
+ const load = (example, key) => {
273
+ setSchema(PROFILES[key].schema ?? EXAMPLES[example].schema);
274
+ setUiSchema({});
275
+ };
276
+ const selectExample = (key) => {
277
+ setExampleKey(key);
278
+ load(key, profileKey);
279
+ };
260
280
  const selectProfile = (key) => {
281
+ const reload = !!PROFILES[key].schema || !!profile.schema;
261
282
  setProfileKey(key);
262
- setSchema(PROFILES[key].schema);
263
- setUiSchema({});
283
+ if (reload) load(exampleKey, key);
264
284
  };
265
285
  return /* @__PURE__ */ jsxs("div", { className: "w-full flex flex-col gap-3 h-[calc(100vh-8rem)]", children: [
266
286
  /* @__PURE__ */ jsxs("div", { children: [
267
287
  /* @__PURE__ */ jsx("h1", { children: "Schema Designer" }),
268
288
  /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mb-3", children: "Visually author a JSON Schema and its UI presentation hints. Edits flow through onChange as a valid schema + uiSchema." })
269
289
  ] }),
270
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
271
- /* @__PURE__ */ jsx(
272
- "label",
273
- {
274
- htmlFor: "capability-profile",
275
- className: "shrink-0 text-sm font-medium",
276
- children: "Capability profile"
277
- }
278
- ),
279
- /* @__PURE__ */ jsx("div", { className: "w-72", children: /* @__PURE__ */ jsx(
280
- FormSelect,
281
- {
282
- id: "capability-profile",
283
- name: "profile",
284
- value: profileKey,
285
- options: Object.keys(PROFILES).map((k) => ({
286
- value: k,
287
- label: PROFILES[k].label
288
- })),
289
- onChange: (v) => selectProfile(v ?? "full"),
290
- clearable: false
291
- }
292
- ) }),
293
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: profile.description })
294
- ] }),
290
+ /* @__PURE__ */ jsx(
291
+ DesignerControls,
292
+ {
293
+ examples: EXAMPLES,
294
+ example: exampleKey,
295
+ onExample: selectExample,
296
+ exampleLocked: profile.schemaLabel,
297
+ profiles: PROFILES,
298
+ profile: profileKey,
299
+ onProfile: selectProfile
300
+ }
301
+ ),
295
302
  /* @__PURE__ */ jsx("div", { style: { flex: 1, minHeight: 0 }, children: /* @__PURE__ */ jsx(
296
303
  SchemaDesigner,
297
304
  {
@@ -304,7 +311,7 @@ function PlaySchemaDesigner() {
304
311
  setUiSchema(nextUiSchema);
305
312
  }
306
313
  },
307
- profileKey
314
+ `${exampleKey}-${profileKey}`
308
315
  ) })
309
316
  ] });
310
317
  }
@@ -312,4 +319,4 @@ function PlaySchemaDesigner() {
312
319
  export {
313
320
  PlaySchemaDesigner
314
321
  };
315
- //# sourceMappingURL=chunk-2XMWOZ5O.js.map
322
+ //# sourceMappingURL=chunk-EPCUUTBZ.js.map