@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
@@ -1,881 +0,0 @@
1
- import {
2
- PlaygroundSection
3
- } from "./chunk-C2EZ2ECG.js";
4
-
5
- // src/pages/PlayDataComponents.tsx
6
- import { useState, useMemo, useCallback } from "react";
7
- import { ArrowRight, ArrowUp } from "lucide-react";
8
- import {
9
- Badge,
10
- Button,
11
- Card,
12
- SimpleTooltip,
13
- Tabs,
14
- TabsContent,
15
- TabsList,
16
- TabsTrigger,
17
- SearchInput,
18
- EntitySelect,
19
- EntityTable,
20
- createRenderer,
21
- EntityTree,
22
- PropertyList
23
- } from "@petrarca/sonnet-ui";
24
- import { FormTextarea } from "@petrarca/sonnet-forms";
25
- import { JsonEditor } from "@petrarca/sonnet-ui/json-editor";
26
- import {
27
- EMPTY_FILTER,
28
- flattenFilterExpr,
29
- isEmptyFilterExpr,
30
- serializeFilterExpr
31
- } from "@petrarca/sonnet-core/search";
32
- import { toJsonSchema } from "@petrarca/sonnet-core/schema";
33
- import { useTreeExpansion } from "@petrarca/sonnet-core/hooks";
34
- import { z } from "zod/v4";
35
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
36
- var MOCK_PATIENTS = [
37
- { value: "pat_001", label: "Alice Hartmann" },
38
- { value: "pat_002", label: "Bob Nguyen" },
39
- { value: "pat_003", label: "Carol Smith" },
40
- { value: "pat_004", label: "David Okafor" },
41
- { value: "pat_005", label: "Eva Larsson" },
42
- { value: "pat_006", label: "Frank Torres" },
43
- { value: "pat_007", label: "Grace Kim" },
44
- { value: "pat_008", label: "Henry Bauer" }
45
- ];
46
- var patientFetcher = ({ search } = {}) => {
47
- const q = search?.toLowerCase() ?? "";
48
- const results = q ? MOCK_PATIENTS.filter((p) => p.label.toLowerCase().includes(q)) : MOCK_PATIENTS;
49
- return Promise.resolve(results);
50
- };
51
- var ALL_ROWS = [
52
- {
53
- id: "u-001",
54
- name: "Alice Hartmann",
55
- status: "active",
56
- role: "admin",
57
- joined: "2024-01-15"
58
- },
59
- {
60
- id: "u-002",
61
- name: "Bob Nguyen",
62
- status: "active",
63
- role: "editor",
64
- joined: "2024-02-03"
65
- },
66
- {
67
- id: "u-003",
68
- name: "Carol Smith",
69
- status: "inactive",
70
- role: "viewer",
71
- joined: "2024-03-20"
72
- },
73
- {
74
- id: "u-004",
75
- name: "David Okafor",
76
- status: "pending",
77
- role: "editor",
78
- joined: "2024-04-11"
79
- },
80
- {
81
- id: "u-005",
82
- name: "Eva Larsson",
83
- status: "active",
84
- role: "admin",
85
- joined: "2024-05-08"
86
- },
87
- {
88
- id: "u-006",
89
- name: "Frank Torres",
90
- status: "inactive",
91
- role: "viewer",
92
- joined: "2024-06-22"
93
- },
94
- {
95
- id: "u-007",
96
- name: "Grace Kim",
97
- status: "active",
98
- role: "editor",
99
- joined: "2024-07-14"
100
- },
101
- {
102
- id: "u-008",
103
- name: "Henry Bauer",
104
- status: "pending",
105
- role: "viewer",
106
- joined: "2024-08-30"
107
- }
108
- ];
109
- var STATUS_COLOR = {
110
- active: "green",
111
- inactive: "violet",
112
- pending: "yellow"
113
- };
114
- var PlaygroundFacets = z.object({
115
- search: z.string().meta({ "x-ui-title": "Name" }),
116
- status: z.enum(["active", "inactive", "pending"]).optional().meta({
117
- "x-ui-title": "Status",
118
- "x-ui-options": {
119
- enumNames: {
120
- active: "Active",
121
- inactive: "Inactive",
122
- pending: "Pending"
123
- }
124
- }
125
- }),
126
- role: z.string().optional().meta({ "x-ui-title": "Role" })
127
- });
128
- var SEARCH_FACET_SCHEMA = toJsonSchema(PlaygroundFacets);
129
- var SAMPLE_SCHEMA = {
130
- title: "User",
131
- type: "object",
132
- properties: {
133
- name: {
134
- type: "string",
135
- title: "Name",
136
- "x-ui-column": { order: 0 },
137
- "x-ui-cell": "bold"
138
- },
139
- status: {
140
- type: "string",
141
- title: "Status",
142
- "x-ui-column": { order: 1 },
143
- "x-ui-cell": "badge",
144
- "x-ui-cell-options": { colors: STATUS_COLOR }
145
- },
146
- role: {
147
- type: "string",
148
- title: "Role",
149
- "x-ui-column": { order: 2 },
150
- "x-ui-cell": "muted"
151
- },
152
- id: {
153
- type: "string",
154
- title: "ID",
155
- "x-ui-column": { order: 3 },
156
- "x-ui-cell": "code"
157
- },
158
- joined: {
159
- type: "string",
160
- format: "date",
161
- title: "Joined",
162
- "x-ui-column": { order: 4 }
163
- }
164
- }
165
- };
166
- var SAMPLE_UI_SCHEMA = {};
167
- var ROLE_ICONS = {
168
- admin: "A",
169
- editor: "E",
170
- viewer: "V"
171
- };
172
- var CUSTOM_RENDERERS = {
173
- // Extract initials from the name, display as avatar circle + name.
174
- "x-play-initials": createRenderer((row) => {
175
- const initials = row.name.split(" ").map((w) => w[0]).join("");
176
- return /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-2", children: [
177
- /* @__PURE__ */ jsx("span", { className: "inline-flex items-center justify-center h-7 w-7 rounded-full bg-muted text-xs font-medium shrink-0", children: initials }),
178
- /* @__PURE__ */ jsx("span", { className: "font-medium", children: row.name })
179
- ] });
180
- }),
181
- // Role with a letter prefix read from options.icons.
182
- "x-play-role-icon": createRenderer((row, options) => {
183
- const icons = options.icons ?? {};
184
- const icon = icons[row.role] ?? "?";
185
- return /* @__PURE__ */ jsxs("span", { children: [
186
- /* @__PURE__ */ jsx("span", { className: "inline-flex items-center justify-center h-5 w-5 rounded bg-muted text-xs font-mono mr-1.5", children: icon }),
187
- row.role
188
- ] });
189
- }),
190
- // Compute days since joined, color-coded by threshold from options.
191
- "x-play-tenure": createRenderer((row, options) => {
192
- const threshold = options.recentDays ?? 365;
193
- const days = Math.floor(
194
- (Date.now() - new Date(row.joined).getTime()) / 864e5
195
- );
196
- const isRecent = days < threshold;
197
- return /* @__PURE__ */ jsxs("span", { className: isRecent ? "text-primary" : "text-muted-foreground", children: [
198
- days,
199
- "d"
200
- ] });
201
- })
202
- };
203
- var CUSTOM_RENDERER_SCHEMA = {
204
- title: "User (custom renderers)",
205
- type: "object",
206
- properties: {
207
- name: {
208
- type: "string",
209
- title: "Name",
210
- "x-ui-column": { order: 0 },
211
- "x-ui-cell": "x-play-initials"
212
- },
213
- role: {
214
- type: "string",
215
- title: "Role",
216
- "x-ui-column": { order: 1 },
217
- "x-ui-cell": "x-play-role-icon",
218
- "x-ui-cell-options": { icons: ROLE_ICONS }
219
- },
220
- status: {
221
- type: "string",
222
- title: "Status",
223
- "x-ui-column": { order: 2 },
224
- "x-ui-cell": "badge",
225
- "x-ui-cell-options": { colors: STATUS_COLOR }
226
- },
227
- joined: {
228
- type: "string",
229
- title: "Tenure",
230
- "x-ui-column": { order: 3 },
231
- "x-ui-cell": "x-play-tenure",
232
- "x-ui-cell-options": { recentDays: 500 }
233
- },
234
- id: {
235
- type: "string",
236
- title: "ID",
237
- "x-ui-column": { order: 4 },
238
- "x-ui-cell": "code"
239
- }
240
- }
241
- };
242
- var SUBMIT_COUNT_RESET = -1;
243
- var SEARCH_FIELD_PRESETS = [
244
- { label: "name, role", fields: ["name", "role"] },
245
- { label: "name (single)", fields: ["name"] },
246
- { label: "name, role, status", fields: ["name", "role", "status"] }
247
- ];
248
- function ToggleStrip({
249
- label,
250
- options,
251
- value,
252
- onChange,
253
- format,
254
- containerClassName
255
- }) {
256
- const fmt = format ?? String;
257
- return /* @__PURE__ */ jsxs("div", { className: `flex items-center gap-3 ${containerClassName ?? ""}`, children: [
258
- /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
259
- label,
260
- ":"
261
- ] }),
262
- options.map((opt) => /* @__PURE__ */ jsx(
263
- "button",
264
- {
265
- type: "button",
266
- onClick: () => onChange(opt),
267
- className: [
268
- "px-3 py-1 rounded-full text-xs font-medium transition-colors",
269
- value === opt ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground hover:text-foreground"
270
- ].join(" "),
271
- children: fmt(opt)
272
- },
273
- String(opt)
274
- ))
275
- ] });
276
- }
277
- var MODE_OPTIONS = ["explicit", "debounce"];
278
- var MODE_LABELS = {
279
- explicit: "Explicit (Enter)",
280
- debounce: "Debounce (300 ms)"
281
- };
282
- var MIN_CHARS_OPTIONS = [0, 1, 2, 3];
283
- var FIELD_PRESET_INDICES = SEARCH_FIELD_PRESETS.map(
284
- (_, i) => i
285
- );
286
- function FilterExprInspector({ expr }) {
287
- return /* @__PURE__ */ jsx("pre", { className: "mt-3 rounded-md bg-muted px-4 py-3 text-xs overflow-auto max-h-40", children: JSON.stringify(expr, null, 2) });
288
- }
289
- function FlatTermsInspector({ expr }) {
290
- const terms = flattenFilterExpr(expr);
291
- return /* @__PURE__ */ jsx("pre", { className: "mt-3 rounded-md bg-muted px-4 py-3 text-xs overflow-auto max-h-40", children: JSON.stringify(terms, null, 2) });
292
- }
293
- function PlayDataComponents() {
294
- const [simpleExpr, setSimpleExpr] = useState(EMPTY_FILTER);
295
- const [simpleMode, setSimpleMode] = useState("explicit");
296
- const [simpleMinChars, setSimpleMinChars] = useState(0);
297
- const [fieldsExpr, setFieldsExpr] = useState(EMPTY_FILTER);
298
- const [fieldsMode, setFieldsMode] = useState("explicit");
299
- const [fieldsMinChars, setFieldsMinChars] = useState(0);
300
- const [fieldsPresetIdx, setFieldsPresetIdx] = useState(0);
301
- const activeSearchFields = SEARCH_FIELD_PRESETS[fieldsPresetIdx].fields;
302
- const [facetedExpr, setFacetedExpr] = useState(EMPTY_FILTER);
303
- const [facetedSubmitCount, setFacetedSubmitCount] = useState(0);
304
- const handleFacetedChange = useCallback((expr) => {
305
- setFacetedExpr(expr);
306
- setFacetedSubmitCount((n) => n + 1);
307
- }, []);
308
- const [schemaText, setSchemaText] = useState(
309
- () => JSON.stringify(toJsonSchema(PlaygroundFacets), null, 2)
310
- );
311
- const [schemaError, setSchemaError] = useState("");
312
- const [activeSchema, setActiveSchema] = useState(SEARCH_FACET_SCHEMA);
313
- const handleSchemaTextChange = useCallback((value) => {
314
- setSchemaText(value);
315
- try {
316
- JSON.parse(value);
317
- setSchemaError("");
318
- } catch {
319
- setSchemaError("Invalid JSON");
320
- }
321
- }, []);
322
- const handleLoadSchema = useCallback(() => {
323
- try {
324
- const parsed = JSON.parse(schemaText);
325
- setActiveSchema(parsed);
326
- setFacetedExpr(EMPTY_FILTER);
327
- setFacetedSubmitCount(SUBMIT_COUNT_RESET);
328
- setSchemaError("");
329
- } catch {
330
- setSchemaError("Invalid JSON -- cannot load");
331
- }
332
- }, [schemaText]);
333
- const [tableSchemaText, setTableSchemaText] = useState(
334
- () => JSON.stringify(SAMPLE_SCHEMA, null, 2)
335
- );
336
- const [tableUiSchemaText, setTableUiSchemaText] = useState(
337
- () => JSON.stringify(SAMPLE_UI_SCHEMA, null, 2)
338
- );
339
- const [tableSchemaError, setTableSchemaError] = useState("");
340
- const [activeTableSchema, setActiveTableSchema] = useState(SAMPLE_SCHEMA);
341
- const [activeTableUiSchema, setActiveTableUiSchema] = useState(SAMPLE_UI_SCHEMA);
342
- const [tableSchemaTab, setTableSchemaTab] = useState("schema");
343
- const handleTableSchemaTextChange = useCallback((value) => {
344
- setTableSchemaText(value);
345
- try {
346
- JSON.parse(value);
347
- setTableSchemaError("");
348
- } catch {
349
- setTableSchemaError("Invalid JSON");
350
- }
351
- }, []);
352
- const handleTableUiSchemaTextChange = useCallback((value) => {
353
- setTableUiSchemaText(value);
354
- try {
355
- JSON.parse(value);
356
- setTableSchemaError("");
357
- } catch {
358
- setTableSchemaError("Invalid JSON");
359
- }
360
- }, []);
361
- const handleApplyTableSchema = useCallback(() => {
362
- try {
363
- const schema = JSON.parse(tableSchemaText);
364
- const uiSchema = JSON.parse(tableUiSchemaText);
365
- setActiveTableSchema(schema);
366
- setActiveTableUiSchema(uiSchema);
367
- setTableSchemaError("");
368
- } catch {
369
- setTableSchemaError("Invalid JSON -- cannot apply");
370
- }
371
- }, [tableSchemaText, tableUiSchemaText]);
372
- const [tableExpr, setTableExpr] = useState(EMPTY_FILTER);
373
- const filteredRows = useMemo(() => {
374
- const terms = flattenFilterExpr(tableExpr);
375
- if (terms.length === 0) return ALL_ROWS;
376
- return ALL_ROWS.filter(
377
- (row) => terms.every(({ key, value }) => {
378
- const v = value.toLowerCase();
379
- if (key === "status") return row.status.toLowerCase().includes(v);
380
- if (key === "role") return row.role.toLowerCase().includes(v);
381
- return row.name.toLowerCase().includes(v);
382
- })
383
- );
384
- }, [tableExpr]);
385
- const tableData = useMemo(
386
- () => ({
387
- data: filteredRows,
388
- meta: {
389
- total: filteredRows.length,
390
- limit: filteredRows.length,
391
- offset: 0,
392
- has_next: false,
393
- has_prev: false
394
- }
395
- }),
396
- [filteredRows]
397
- );
398
- const [selectedPatient, setSelectedPatient] = useState(null);
399
- return /* @__PURE__ */ jsxs("div", { className: "w-full max-w-4xl space-y-6", children: [
400
- /* @__PURE__ */ jsxs("div", { children: [
401
- /* @__PURE__ */ jsx("h1", { children: "Data Components" }),
402
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Interactive sandbox for SearchInput (simple, multi-field, faceted), EntityTable (with schema editor and custom renderers), EntitySelect, and EntityTree." })
403
- ] }),
404
- /* @__PURE__ */ jsxs(
405
- PlaygroundSection,
406
- {
407
- title: "SearchInput \u2014 simple mode",
408
- description: "No fields prop. Produces a single search term under the key 'search'.",
409
- variant: "card",
410
- children: [
411
- /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-4 mb-3", children: [
412
- /* @__PURE__ */ jsx(
413
- ToggleStrip,
414
- {
415
- label: "Mode",
416
- options: MODE_OPTIONS,
417
- value: simpleMode,
418
- onChange: (m) => {
419
- setSimpleMode(m);
420
- setSimpleExpr(EMPTY_FILTER);
421
- },
422
- format: (m) => MODE_LABELS[m]
423
- }
424
- ),
425
- /* @__PURE__ */ jsx(
426
- ToggleStrip,
427
- {
428
- label: "Min chars",
429
- options: MIN_CHARS_OPTIONS,
430
- value: simpleMinChars,
431
- onChange: setSimpleMinChars,
432
- format: (n) => n === 0 ? "off" : String(n)
433
- }
434
- )
435
- ] }),
436
- /* @__PURE__ */ jsx(
437
- SearchInput,
438
- {
439
- value: simpleExpr,
440
- onChange: setSimpleExpr,
441
- mode: simpleMode,
442
- minChars: simpleMinChars,
443
- placeholder: "Search...",
444
- className: "max-w-sm"
445
- }
446
- ),
447
- /* @__PURE__ */ jsx(FlatTermsInspector, { expr: simpleExpr })
448
- ]
449
- }
450
- ),
451
- /* @__PURE__ */ jsxs(
452
- PlaygroundSection,
453
- {
454
- title: "SearchInput \u2014 searchFields (multi-field OR)",
455
- description: "Produces a FilterOr with one term per field. Toggle field sets, mode, and minChars to explore different behaviours.",
456
- variant: "card",
457
- children: [
458
- /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-4 mb-3", children: [
459
- /* @__PURE__ */ jsx(
460
- ToggleStrip,
461
- {
462
- label: "Fields",
463
- options: FIELD_PRESET_INDICES,
464
- value: fieldsPresetIdx,
465
- onChange: (idx) => {
466
- setFieldsPresetIdx(idx);
467
- setFieldsExpr(EMPTY_FILTER);
468
- },
469
- format: (idx) => SEARCH_FIELD_PRESETS[idx].label
470
- }
471
- ),
472
- /* @__PURE__ */ jsx(
473
- ToggleStrip,
474
- {
475
- label: "Mode",
476
- options: MODE_OPTIONS,
477
- value: fieldsMode,
478
- onChange: (m) => {
479
- setFieldsMode(m);
480
- setFieldsExpr(EMPTY_FILTER);
481
- },
482
- format: (m) => MODE_LABELS[m]
483
- }
484
- ),
485
- /* @__PURE__ */ jsx(
486
- ToggleStrip,
487
- {
488
- label: "Min chars",
489
- options: MIN_CHARS_OPTIONS,
490
- value: fieldsMinChars,
491
- onChange: setFieldsMinChars,
492
- format: (n) => n === 0 ? "off" : String(n)
493
- }
494
- )
495
- ] }),
496
- /* @__PURE__ */ jsx(
497
- SearchInput,
498
- {
499
- value: fieldsExpr,
500
- onChange: setFieldsExpr,
501
- searchFields: activeSearchFields,
502
- mode: fieldsMode,
503
- minChars: fieldsMinChars,
504
- placeholder: `Search by ${activeSearchFields.join(" or ")}...`,
505
- className: "max-w-sm"
506
- }
507
- ),
508
- /* @__PURE__ */ jsxs("div", { className: "mt-3 space-y-2", children: [
509
- /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
510
- "searchFields: [",
511
- activeSearchFields.map((f) => `"${f}"`).join(", "),
512
- "]"
513
- ] }),
514
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "FilterExpr AST:" }),
515
- /* @__PURE__ */ jsx(FilterExprInspector, { expr: fieldsExpr }),
516
- !isEmptyFilterExpr(fieldsExpr) && /* @__PURE__ */ jsxs(Fragment, { children: [
517
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Serialized q= string:" }),
518
- /* @__PURE__ */ jsx("pre", { className: "rounded-md bg-muted px-4 py-3 text-xs overflow-auto", children: serializeFilterExpr(fieldsExpr) })
519
- ] })
520
- ] })
521
- ]
522
- }
523
- ),
524
- /* @__PURE__ */ jsx(
525
- PlaygroundSection,
526
- {
527
- title: "SearchInput \u2014 faceted mode",
528
- 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.",
529
- variant: "card",
530
- children: /* @__PURE__ */ jsxs("div", { className: "flex gap-4 items-start", children: [
531
- /* @__PURE__ */ jsxs(Card, { className: "flex-1 min-w-0 p-3 flex flex-col gap-2", children: [
532
- /* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-muted-foreground", children: "JSON Schema" }),
533
- schemaError && /* @__PURE__ */ jsx(Badge, { variant: "destructive", className: "text-xs self-start", children: schemaError }),
534
- /* @__PURE__ */ jsx(
535
- FormTextarea,
536
- {
537
- value: schemaText,
538
- onChange: (e) => handleSchemaTextChange(e.target.value),
539
- className: "font-mono text-xs",
540
- rows: 18
541
- }
542
- )
543
- ] }),
544
- /* @__PURE__ */ jsx("div", { className: "flex items-center self-center", children: /* @__PURE__ */ jsx(SimpleTooltip, { label: "Load schema into search", children: /* @__PURE__ */ jsx(
545
- Button,
546
- {
547
- variant: "default",
548
- size: "icon",
549
- onClick: handleLoadSchema,
550
- disabled: !!schemaError,
551
- children: /* @__PURE__ */ jsx(ArrowRight, { size: 18 })
552
- }
553
- ) }) }),
554
- /* @__PURE__ */ jsxs(Card, { className: "flex-1 min-w-0 p-3 flex flex-col gap-3", children: [
555
- /* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-muted-foreground", children: "Live search" }),
556
- /* @__PURE__ */ jsx(
557
- SearchInput,
558
- {
559
- value: facetedExpr,
560
- onChange: handleFacetedChange,
561
- schema: activeSchema,
562
- mode: "explicit",
563
- placeholder: "Add filter..."
564
- }
565
- ),
566
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
567
- /* @__PURE__ */ jsx("span", { children: "onChange fired:" }),
568
- /* @__PURE__ */ jsxs("span", { className: "font-mono font-medium text-foreground", children: [
569
- facetedSubmitCount,
570
- "x"
571
- ] })
572
- ] }),
573
- /* @__PURE__ */ jsx(FilterExprInspector, { expr: facetedExpr })
574
- ] })
575
- ] })
576
- }
577
- ),
578
- /* @__PURE__ */ jsxs(
579
- PlaygroundSection,
580
- {
581
- title: "EntityTable with SearchInput",
582
- 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.",
583
- variant: "card",
584
- children: [
585
- /* @__PURE__ */ jsx(
586
- SearchInput,
587
- {
588
- value: tableExpr,
589
- onChange: setTableExpr,
590
- schema: SEARCH_FACET_SCHEMA,
591
- mode: "explicit",
592
- placeholder: "Filter users... (press Enter to apply)",
593
- className: "mb-4 max-w-sm"
594
- }
595
- ),
596
- /* @__PURE__ */ jsx(
597
- EntityTable,
598
- {
599
- schema: activeTableSchema,
600
- uiSchema: activeTableUiSchema,
601
- data: tableData,
602
- isLoading: false,
603
- isError: false,
604
- entityLabel: "users",
605
- isFiltered: !isEmptyFilterExpr(tableExpr)
606
- }
607
- ),
608
- /* @__PURE__ */ jsx("div", { className: "mt-4", children: /* @__PURE__ */ jsx(Card, { className: "border shadow-sm p-4 flex flex-col", children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between mb-2", children: /* @__PURE__ */ jsxs(
609
- Tabs,
610
- {
611
- value: tableSchemaTab,
612
- onValueChange: setTableSchemaTab,
613
- className: "flex flex-col flex-1",
614
- children: [
615
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
616
- /* @__PURE__ */ jsxs(TabsList, { children: [
617
- /* @__PURE__ */ jsx(TabsTrigger, { value: "schema", children: "JSON Schema" }),
618
- /* @__PURE__ */ jsx(TabsTrigger, { value: "uischema", children: "UI Schema" })
619
- ] }),
620
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
621
- tableSchemaError && /* @__PURE__ */ jsx(Badge, { variant: "destructive", className: "text-xs", children: tableSchemaError }),
622
- /* @__PURE__ */ jsx(SimpleTooltip, { label: "Apply schema to table above", children: /* @__PURE__ */ jsx(
623
- Button,
624
- {
625
- variant: "default",
626
- size: "icon",
627
- onClick: handleApplyTableSchema,
628
- disabled: !!tableSchemaError,
629
- children: /* @__PURE__ */ jsx(ArrowUp, { size: 18 })
630
- }
631
- ) })
632
- ] })
633
- ] }),
634
- /* @__PURE__ */ jsx(TabsContent, { value: "schema", className: "mt-2", children: /* @__PURE__ */ jsx(
635
- JsonEditor,
636
- {
637
- value: tableSchemaText,
638
- editablePaths: ["/"],
639
- onChange: handleTableSchemaTextChange,
640
- height: "280px",
641
- className: "rounded-md border overflow-hidden"
642
- }
643
- ) }),
644
- /* @__PURE__ */ jsx(TabsContent, { value: "uischema", className: "mt-2", children: /* @__PURE__ */ jsx(
645
- JsonEditor,
646
- {
647
- value: tableUiSchemaText,
648
- editablePaths: ["/"],
649
- onChange: handleTableUiSchemaTextChange,
650
- height: "280px",
651
- className: "rounded-md border overflow-hidden"
652
- }
653
- ) })
654
- ]
655
- }
656
- ) }) }) })
657
- ]
658
- }
659
- ),
660
- /* @__PURE__ */ jsx(
661
- PlaygroundSection,
662
- {
663
- title: "EntityTable with Local Renderers",
664
- 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).",
665
- variant: "card",
666
- children: /* @__PURE__ */ jsx(
667
- EntityTable,
668
- {
669
- schema: CUSTOM_RENDERER_SCHEMA,
670
- renderers: CUSTOM_RENDERERS,
671
- data: {
672
- data: ALL_ROWS,
673
- meta: {
674
- total: ALL_ROWS.length,
675
- limit: ALL_ROWS.length,
676
- offset: 0,
677
- has_next: false,
678
- has_prev: false
679
- }
680
- },
681
- isLoading: false,
682
- isError: false,
683
- entityLabel: "users"
684
- }
685
- )
686
- }
687
- ),
688
- /* @__PURE__ */ jsx(
689
- PlaygroundSection,
690
- {
691
- title: "EntitySelect",
692
- 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'.",
693
- variant: "card",
694
- children: /* @__PURE__ */ jsxs("div", { className: "flex gap-6 items-start", children: [
695
- /* @__PURE__ */ jsx(
696
- EntitySelect,
697
- {
698
- fetcher: patientFetcher,
699
- queryKey: "playground-patients",
700
- value: selectedPatient,
701
- onChange: setSelectedPatient,
702
- label: "Patient",
703
- placeholder: "Select patient...",
704
- searchPlaceholder: "Search patients...",
705
- className: "max-w-xs"
706
- }
707
- ),
708
- /* @__PURE__ */ jsxs(Card, { className: "flex-1 min-w-0 p-3", children: [
709
- /* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-muted-foreground mb-2", children: "Selected value" }),
710
- /* @__PURE__ */ jsx("pre", { className: "rounded-md bg-muted px-4 py-3 text-xs overflow-auto", children: JSON.stringify(selectedPatient, null, 2) })
711
- ] })
712
- ] })
713
- }
714
- ),
715
- /* @__PURE__ */ jsx(
716
- PlaygroundSection,
717
- {
718
- title: "EntityTree",
719
- 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.",
720
- variant: "card",
721
- children: /* @__PURE__ */ jsx(EntityTreeDemo, {})
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
- }
732
- )
733
- ] });
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
- }
775
- var OrgSchema = z.object({
776
- name: z.string().meta({ title: "Name", "x-ui-column": { order: 0 } }),
777
- type: z.string().meta({ title: "Type", "x-ui-column": { order: 1 } }),
778
- headcount: z.number().meta({ title: "Headcount", "x-ui-column": { order: 2 } })
779
- });
780
- var ORG_TREE_SCHEMA = toJsonSchema(OrgSchema);
781
- var ORG_NODES = [
782
- {
783
- id: "eng",
784
- data: { name: "Engineering", type: "Division", headcount: 120 },
785
- hasChildren: true,
786
- children: [
787
- {
788
- id: "frontend",
789
- data: { name: "Frontend", type: "Team", headcount: 18 },
790
- hasChildren: true,
791
- children: [
792
- {
793
- id: "design-sys",
794
- data: { name: "Design System", type: "Squad", headcount: 5 },
795
- hasChildren: false
796
- }
797
- ]
798
- },
799
- {
800
- id: "backend",
801
- data: { name: "Backend", type: "Team", headcount: 32 },
802
- hasChildren: false
803
- },
804
- {
805
- id: "infra",
806
- data: { name: "Infrastructure", type: "Team", headcount: 14 },
807
- hasChildren: false
808
- }
809
- ]
810
- },
811
- {
812
- id: "product",
813
- data: { name: "Product", type: "Division", headcount: 45 },
814
- hasChildren: true,
815
- children: [
816
- {
817
- id: "research",
818
- data: { name: "Research", type: "Team", headcount: 8 },
819
- hasChildren: false
820
- },
821
- {
822
- id: "pm",
823
- data: { name: "Product Management", type: "Team", headcount: 12 },
824
- hasChildren: false
825
- }
826
- ]
827
- },
828
- {
829
- id: "ops",
830
- data: { name: "Operations", type: "Division", headcount: 30 },
831
- hasChildren: false
832
- }
833
- ];
834
- function EntityTreeDemo() {
835
- const {
836
- expandedIds: treeExpandedIds,
837
- onExpand: onTreeExpand,
838
- onCollapse: onTreeCollapse
839
- } = useTreeExpansion();
840
- const [selectedIds, setSelectedIds] = useState(/* @__PURE__ */ new Set());
841
- const [activeId, setActiveId] = useState(null);
842
- return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
843
- /* @__PURE__ */ jsx(
844
- EntityTree,
845
- {
846
- schema: ORG_TREE_SCHEMA,
847
- nodes: ORG_NODES,
848
- expandedIds: treeExpandedIds,
849
- onExpand: onTreeExpand,
850
- onCollapse: onTreeCollapse,
851
- onNodeSelect: (node) => setActiveId(node.id),
852
- onNodeEdit: (node) => setActiveId(node.id),
853
- activeNodeId: activeId ?? void 0,
854
- selectedIds,
855
- onSelectionChange: (id, selected) => setSelectedIds((prev) => {
856
- const next = new Set(prev);
857
- if (selected) next.add(id);
858
- else next.delete(id);
859
- return next;
860
- }),
861
- entityLabel: "departments"
862
- }
863
- ),
864
- /* @__PURE__ */ jsxs("div", { className: "flex gap-6 text-xs text-muted-foreground", children: [
865
- activeId && /* @__PURE__ */ jsxs("span", { children: [
866
- "Active: ",
867
- /* @__PURE__ */ jsx("span", { className: "font-mono", children: activeId })
868
- ] }),
869
- selectedIds.size > 0 && /* @__PURE__ */ jsxs("span", { children: [
870
- "Selected:",
871
- " ",
872
- /* @__PURE__ */ jsx("span", { className: "font-mono", children: [...selectedIds].join(", ") })
873
- ] })
874
- ] })
875
- ] });
876
- }
877
-
878
- export {
879
- PlayDataComponents
880
- };
881
- //# sourceMappingURL=chunk-O2QMWJZI.js.map