@flanksource/clicky-ui 0.3.18 → 0.3.19

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 (191) hide show
  1. package/dist/components/ComboboxMenu.cjs +5 -1
  2. package/dist/components/ComboboxMenu.cjs.map +1 -1
  3. package/dist/components/ComboboxMenu.d.ts.map +1 -1
  4. package/dist/components/ComboboxMenu.js +5 -1
  5. package/dist/components/ComboboxMenu.js.map +1 -1
  6. package/dist/components/EndpointSelector.model.cjs +96 -0
  7. package/dist/components/EndpointSelector.model.cjs.map +1 -0
  8. package/dist/components/EndpointSelector.model.d.ts +2 -0
  9. package/dist/components/EndpointSelector.model.d.ts.map +1 -1
  10. package/dist/components/EndpointSelector.model.js +96 -0
  11. package/dist/components/EndpointSelector.model.js.map +1 -0
  12. package/dist/components/FilterBar.cjs +52 -2
  13. package/dist/components/FilterBar.cjs.map +1 -1
  14. package/dist/components/FilterBar.d.ts +20 -2
  15. package/dist/components/FilterBar.d.ts.map +1 -1
  16. package/dist/components/FilterBar.js +52 -2
  17. package/dist/components/FilterBar.js.map +1 -1
  18. package/dist/components/JSONPathField.cjs +87 -66
  19. package/dist/components/JSONPathField.cjs.map +1 -1
  20. package/dist/components/JSONPathField.d.ts +26 -9
  21. package/dist/components/JSONPathField.d.ts.map +1 -1
  22. package/dist/components/JSONPathField.js +88 -67
  23. package/dist/components/JSONPathField.js.map +1 -1
  24. package/dist/components/JSONPathPlayground.cjs +225 -0
  25. package/dist/components/JSONPathPlayground.cjs.map +1 -0
  26. package/dist/components/JSONPathPlayground.d.ts +59 -0
  27. package/dist/components/JSONPathPlayground.d.ts.map +1 -0
  28. package/dist/components/JSONPathPlayground.js +225 -0
  29. package/dist/components/JSONPathPlayground.js.map +1 -0
  30. package/dist/components/OnePasswordSelector.cjs +178 -0
  31. package/dist/components/OnePasswordSelector.cjs.map +1 -0
  32. package/dist/components/OnePasswordSelector.d.ts +8 -0
  33. package/dist/components/OnePasswordSelector.d.ts.map +1 -0
  34. package/dist/components/OnePasswordSelector.js +178 -0
  35. package/dist/components/OnePasswordSelector.js.map +1 -0
  36. package/dist/components/OnePasswordSelector.model.cjs +31 -0
  37. package/dist/components/OnePasswordSelector.model.cjs.map +1 -0
  38. package/dist/components/OnePasswordSelector.model.d.ts +27 -0
  39. package/dist/components/OnePasswordSelector.model.d.ts.map +1 -0
  40. package/dist/components/OnePasswordSelector.model.js +31 -0
  41. package/dist/components/OnePasswordSelector.model.js.map +1 -0
  42. package/dist/components/SecretFormField.cjs +142 -0
  43. package/dist/components/SecretFormField.cjs.map +1 -0
  44. package/dist/components/SecretFormField.d.ts +9 -0
  45. package/dist/components/SecretFormField.d.ts.map +1 -0
  46. package/dist/components/SecretFormField.js +142 -0
  47. package/dist/components/SecretFormField.js.map +1 -0
  48. package/dist/components/SecretKeySelector.cjs +20 -14
  49. package/dist/components/SecretKeySelector.cjs.map +1 -1
  50. package/dist/components/SecretKeySelector.d.ts +4 -1
  51. package/dist/components/SecretKeySelector.d.ts.map +1 -1
  52. package/dist/components/SecretKeySelector.js +20 -14
  53. package/dist/components/SecretKeySelector.js.map +1 -1
  54. package/dist/components/TreePickerField.cjs +55 -29
  55. package/dist/components/TreePickerField.cjs.map +1 -1
  56. package/dist/components/TreePickerField.d.ts +10 -1
  57. package/dist/components/TreePickerField.d.ts.map +1 -1
  58. package/dist/components/TreePickerField.js +56 -30
  59. package/dist/components/TreePickerField.js.map +1 -1
  60. package/dist/components/combobox-types.d.ts +9 -0
  61. package/dist/components/combobox-types.d.ts.map +1 -1
  62. package/dist/components/filter-bar-utils.cjs +7 -0
  63. package/dist/components/filter-bar-utils.cjs.map +1 -1
  64. package/dist/components/filter-bar-utils.d.ts.map +1 -1
  65. package/dist/components/filter-bar-utils.js +7 -0
  66. package/dist/components/filter-bar-utils.js.map +1 -1
  67. package/dist/components/jotai-bindings-core.cjs.map +1 -1
  68. package/dist/components/jotai-bindings-core.d.ts +4 -1
  69. package/dist/components/jotai-bindings-core.d.ts.map +1 -1
  70. package/dist/components/jotai-bindings-core.js.map +1 -1
  71. package/dist/components/json-schema-form-render.cjs +2 -1
  72. package/dist/components/json-schema-form-render.cjs.map +1 -1
  73. package/dist/components/json-schema-form-render.d.ts.map +1 -1
  74. package/dist/components/json-schema-form-render.js +2 -1
  75. package/dist/components/json-schema-form-render.js.map +1 -1
  76. package/dist/components/json-schema-form-types.d.ts +9 -0
  77. package/dist/components/json-schema-form-types.d.ts.map +1 -1
  78. package/dist/components/jsonPathTree.cjs +189 -0
  79. package/dist/components/jsonPathTree.cjs.map +1 -0
  80. package/dist/components/jsonPathTree.d.ts +92 -0
  81. package/dist/components/jsonPathTree.d.ts.map +1 -0
  82. package/dist/components/jsonPathTree.js +189 -0
  83. package/dist/components/jsonPathTree.js.map +1 -0
  84. package/dist/components/secret-form-extension.cjs +30 -0
  85. package/dist/components/secret-form-extension.cjs.map +1 -0
  86. package/dist/components/secret-form-extension.d.ts +23 -0
  87. package/dist/components/secret-form-extension.d.ts.map +1 -0
  88. package/dist/components/secret-form-extension.js +30 -0
  89. package/dist/components/secret-form-extension.js.map +1 -0
  90. package/dist/components.cjs +16 -0
  91. package/dist/components.cjs.map +1 -1
  92. package/dist/components.d.ts +6 -0
  93. package/dist/components.d.ts.map +1 -1
  94. package/dist/components.js +16 -0
  95. package/dist/components.js.map +1 -1
  96. package/dist/data/TaskExecDetails.cjs +40 -0
  97. package/dist/data/TaskExecDetails.cjs.map +1 -0
  98. package/dist/data/TaskExecDetails.d.ts +5 -0
  99. package/dist/data/TaskExecDetails.d.ts.map +1 -0
  100. package/dist/data/TaskExecDetails.js +40 -0
  101. package/dist/data/TaskExecDetails.js.map +1 -0
  102. package/dist/data/TaskProgress.cjs +9 -3
  103. package/dist/data/TaskProgress.cjs.map +1 -1
  104. package/dist/data/TaskProgress.d.ts.map +1 -1
  105. package/dist/data/TaskProgress.js +9 -3
  106. package/dist/data/TaskProgress.js.map +1 -1
  107. package/dist/data/TaskSnapshot.cjs.map +1 -1
  108. package/dist/data/TaskSnapshot.d.ts +12 -1
  109. package/dist/data/TaskSnapshot.d.ts.map +1 -1
  110. package/dist/data/TaskSnapshot.js.map +1 -1
  111. package/dist/data/TreeNode.cjs +3 -0
  112. package/dist/data/TreeNode.cjs.map +1 -1
  113. package/dist/data/TreeNode.d.ts.map +1 -1
  114. package/dist/data/TreeNode.js +3 -0
  115. package/dist/data/TreeNode.js.map +1 -1
  116. package/dist/data/data-table-filter-values.cjs +20 -0
  117. package/dist/data/data-table-filter-values.cjs.map +1 -1
  118. package/dist/data/data-table-filter-values.d.ts +16 -0
  119. package/dist/data/data-table-filter-values.d.ts.map +1 -1
  120. package/dist/data/data-table-filter-values.js +20 -0
  121. package/dist/data/data-table-filter-values.js.map +1 -1
  122. package/dist/data/data-table-server-filters.cjs +23 -29
  123. package/dist/data/data-table-server-filters.cjs.map +1 -1
  124. package/dist/data/data-table-server-filters.d.ts.map +1 -1
  125. package/dist/data/data-table-server-filters.js +21 -27
  126. package/dist/data/data-table-server-filters.js.map +1 -1
  127. package/dist/data/query-browser/QueryBrowser.cjs +129 -157
  128. package/dist/data/query-browser/QueryBrowser.cjs.map +1 -1
  129. package/dist/data/query-browser/QueryBrowser.d.ts +1 -71
  130. package/dist/data/query-browser/QueryBrowser.d.ts.map +1 -1
  131. package/dist/data/query-browser/QueryBrowser.editor.cjs +88 -0
  132. package/dist/data/query-browser/QueryBrowser.editor.cjs.map +1 -0
  133. package/dist/data/query-browser/QueryBrowser.editor.d.ts +12 -0
  134. package/dist/data/query-browser/QueryBrowser.editor.d.ts.map +1 -0
  135. package/dist/data/query-browser/QueryBrowser.editor.js +88 -0
  136. package/dist/data/query-browser/QueryBrowser.editor.js.map +1 -0
  137. package/dist/data/query-browser/QueryBrowser.js +130 -158
  138. package/dist/data/query-browser/QueryBrowser.js.map +1 -1
  139. package/dist/data/query-browser/QueryBrowser.types.cjs +11 -0
  140. package/dist/data/query-browser/QueryBrowser.types.cjs.map +1 -0
  141. package/dist/data/query-browser/QueryBrowser.types.d.ts +92 -0
  142. package/dist/data/query-browser/QueryBrowser.types.d.ts.map +1 -0
  143. package/dist/data/query-browser/QueryBrowser.types.js +11 -0
  144. package/dist/data/query-browser/QueryBrowser.types.js.map +1 -0
  145. package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.cjs +56 -0
  146. package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.cjs.map +1 -0
  147. package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.d.ts +5 -0
  148. package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.d.ts.map +1 -0
  149. package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.js +56 -0
  150. package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.js.map +1 -0
  151. package/dist/data/query-browser/QueryBrowserResults.cjs +80 -0
  152. package/dist/data/query-browser/QueryBrowserResults.cjs.map +1 -0
  153. package/dist/data/query-browser/QueryBrowserResults.d.ts +16 -0
  154. package/dist/data/query-browser/QueryBrowserResults.d.ts.map +1 -0
  155. package/dist/data/query-browser/QueryBrowserResults.js +80 -0
  156. package/dist/data/query-browser/QueryBrowserResults.js.map +1 -0
  157. package/dist/data/query-browser/index.d.ts +2 -1
  158. package/dist/data/query-browser/index.d.ts.map +1 -1
  159. package/dist/data/task-exec-details.cjs +9 -0
  160. package/dist/data/task-exec-details.cjs.map +1 -0
  161. package/dist/data/task-exec-details.d.ts +3 -0
  162. package/dist/data/task-exec-details.d.ts.map +1 -0
  163. package/dist/data/task-exec-details.js +9 -0
  164. package/dist/data/task-exec-details.js.map +1 -0
  165. package/dist/data/version-info.cjs +3 -3
  166. package/dist/data/version-info.js +3 -3
  167. package/dist/data.cjs +2 -0
  168. package/dist/data.cjs.map +1 -1
  169. package/dist/data.d.ts +1 -1
  170. package/dist/data.d.ts.map +1 -1
  171. package/dist/data.js +2 -0
  172. package/dist/data.js.map +1 -1
  173. package/dist/index.cjs +18 -0
  174. package/dist/index.cjs.map +1 -1
  175. package/dist/index.js +18 -0
  176. package/dist/index.js.map +1 -1
  177. package/dist/rpc/FilterForm.cjs +20 -0
  178. package/dist/rpc/FilterForm.cjs.map +1 -1
  179. package/dist/rpc/FilterForm.js +20 -0
  180. package/dist/rpc/FilterForm.js.map +1 -1
  181. package/dist/rpc/formMetadata.cjs +34 -0
  182. package/dist/rpc/formMetadata.cjs.map +1 -1
  183. package/dist/rpc/formMetadata.d.ts.map +1 -1
  184. package/dist/rpc/formMetadata.js +35 -1
  185. package/dist/rpc/formMetadata.js.map +1 -1
  186. package/dist/rpc/types.cjs.map +1 -1
  187. package/dist/rpc/types.d.ts +9 -1
  188. package/dist/rpc/types.d.ts.map +1 -1
  189. package/dist/rpc/types.js.map +1 -1
  190. package/dist/styles.css +1 -1
  191. package/package.json +1 -1
@@ -2,13 +2,14 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const react = require("react");
5
+ const Icon = require("../data/Icon.cjs");
5
6
  const IconButton = require("./IconButton.cjs");
6
7
  const InputField = require("./InputField.cjs");
8
+ const jsonPathTree = require("./jsonPathTree.cjs");
9
+ const JSONPathPlayground = require("./JSONPathPlayground.cjs");
7
10
  const TreePickerField = require("./TreePickerField.cjs");
8
11
  const UiListTree = require("../icons/components/UiListTree.cjs");
9
- const MAX_DEPTH = 12;
10
- const MAX_OBJECT_PROPERTIES = 100;
11
- const SIMPLE_PROPERTY = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
12
+ const UiFullscreen = require("../icons/components/UiFullscreen.cjs");
12
13
  function JSONPathField({
13
14
  json,
14
15
  value,
@@ -16,76 +17,96 @@ function JSONPathField({
16
17
  isSelectable,
17
18
  getPath,
18
19
  pickerLabel,
20
+ rows,
21
+ evaluate,
22
+ onSelectPath,
23
+ source,
19
24
  disabled,
20
25
  className,
21
26
  "aria-label": ariaLabel,
22
27
  ...inputProps
23
28
  }) {
24
- const roots = react.useMemo(() => json === void 0 ? [] : [buildJSONPathNode(json, "$", 0)], [json]);
29
+ const [playgroundOpen, setPlaygroundOpen] = react.useState(false);
30
+ const roots = react.useMemo(() => json === void 0 ? [] : [jsonPathTree.buildJSONPathNode(json, "$", 0)], [json]);
31
+ const playgroundRows = react.useMemo(
32
+ () => rows ?? (json === void 0 ? [] : [json]),
33
+ [rows, json]
34
+ );
25
35
  const browseLabel = pickerLabel ?? `Browse ${ariaLabel ?? "JSONPath"} JSON paths`;
26
36
  const pickerDisabled = Boolean(disabled) || json === void 0;
27
- return /* @__PURE__ */ jsxRuntime.jsx(
28
- TreePickerField.TreePickerField,
29
- {
30
- className: "w-full",
31
- roots,
32
- getKey: (node) => node.key,
33
- getChildren: (node) => node.children,
34
- getSearchText: (node) => `${node.path} ${node.summary}`,
35
- defaultOpen: (_node, depth) => depth < 2,
36
- ...isSelectable ? { isSelectable } : {},
37
- disabled: pickerDisabled,
38
- onSelect: (node) => onChange((getPath == null ? void 0 : getPath(node)) ?? node.path),
39
- renderRow: ({ node }) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-density-2 font-mono text-xs", children: [
40
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-primary", children: node.path }),
41
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-muted-foreground", title: node.summary, children: node.summary })
42
- ] }),
43
- renderTrigger: ({ open, triggerRef, toggle }) => /* @__PURE__ */ jsxRuntime.jsx(
44
- InputField.InputField,
45
- {
46
- ...inputProps,
47
- ...disabled !== void 0 ? { disabled } : {},
48
- "aria-label": ariaLabel,
49
- className,
50
- value,
51
- onChange,
52
- suffix: /* @__PURE__ */ jsxRuntime.jsx(
53
- IconButton.IconButton,
54
- {
55
- ref: triggerRef,
56
- icon: UiListTree.UiListTree,
57
- label: browseLabel,
58
- disabled: pickerDisabled,
59
- "aria-haspopup": "tree",
60
- "aria-expanded": open,
61
- onClick: toggle
62
- }
63
- )
64
- }
65
- )
66
- }
67
- );
68
- }
69
- function buildJSONPathNode(value, path, depth) {
70
- const kind = Array.isArray(value) ? "array" : value !== null && typeof value === "object" ? "object" : "scalar";
71
- const node = { key: path, path, value, kind, summary: summarizeJSON(value) };
72
- if (kind === "scalar" || depth >= MAX_DEPTH) return node;
73
- const entries = Array.isArray(value) ? value.length > 0 ? [[0, value[0]]] : [] : Object.entries(value).slice(0, MAX_OBJECT_PROPERTIES);
74
- node.children = entries.map(([key, child]) => buildJSONPathNode(child, appendJSONPath(path, key), depth + 1));
75
- return node;
76
- }
77
- function appendJSONPath(path, key) {
78
- if (typeof key === "number") return `${path}[${key}]`;
79
- return SIMPLE_PROPERTY.test(key) ? `${path}.${key}` : `${path}[${JSON.stringify(key)}]`;
80
- }
81
- function summarizeJSON(value) {
82
- if (Array.isArray(value)) return `[${value.length} item${value.length === 1 ? "" : "s"}]`;
83
- if (value !== null && typeof value === "object") {
84
- const count = Object.keys(value).length;
85
- return `{${count} ${count === 1 ? "property" : "properties"}}`;
86
- }
87
- if (typeof value === "string") return JSON.stringify(value.length > 80 ? `${value.slice(0, 77)}…` : value);
88
- return String(value);
37
+ const commit = onSelectPath ?? ((path) => onChange(path));
38
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
39
+ /* @__PURE__ */ jsxRuntime.jsx(
40
+ TreePickerField.TreePickerField,
41
+ {
42
+ className: "w-full",
43
+ roots,
44
+ getKey: (node) => node.key,
45
+ getChildren: (node) => node.children,
46
+ getSearchText: (node) => `${node.path} ${node.summary}`,
47
+ defaultOpen: (_node, depth) => depth < 2,
48
+ ...isSelectable ? { isSelectable } : {},
49
+ disabled: pickerDisabled,
50
+ onSelect: (node) => onChange((getPath == null ? void 0 : getPath(node)) ?? node.path),
51
+ renderFooter: ({ close }) => /* @__PURE__ */ jsxRuntime.jsxs(
52
+ "button",
53
+ {
54
+ type: "button",
55
+ onClick: () => {
56
+ close();
57
+ setPlaygroundOpen(true);
58
+ },
59
+ className: "flex w-full items-center gap-2 px-3 py-2 text-left text-xs text-muted-foreground hover:bg-accent hover:text-accent-foreground",
60
+ children: [
61
+ /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiFullscreen.UiFullscreen, className: "text-xs" }),
62
+ "Open playground…"
63
+ ]
64
+ }
65
+ ),
66
+ renderRow: ({ node }) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-density-2 font-mono text-xs", children: [
67
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-primary", children: node.path }),
68
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-muted-foreground", title: node.summary, children: node.summary })
69
+ ] }),
70
+ renderTrigger: ({ open, triggerRef, toggle }) => /* @__PURE__ */ jsxRuntime.jsx(
71
+ InputField.InputField,
72
+ {
73
+ ...inputProps,
74
+ ...disabled !== void 0 ? { disabled } : {},
75
+ "aria-label": ariaLabel,
76
+ className,
77
+ value,
78
+ onChange,
79
+ suffix: /* @__PURE__ */ jsxRuntime.jsx(
80
+ IconButton.IconButton,
81
+ {
82
+ ref: triggerRef,
83
+ icon: UiListTree.UiListTree,
84
+ label: browseLabel,
85
+ disabled: pickerDisabled,
86
+ "aria-haspopup": "tree",
87
+ "aria-expanded": open,
88
+ onClick: toggle
89
+ }
90
+ )
91
+ }
92
+ )
93
+ }
94
+ ),
95
+ playgroundOpen && /* @__PURE__ */ jsxRuntime.jsx(
96
+ JSONPathPlayground.JSONPathPlayground,
97
+ {
98
+ open: true,
99
+ onClose: () => setPlaygroundOpen(false),
100
+ rows: playgroundRows,
101
+ value,
102
+ onCommit: commit,
103
+ assignsRoot: onSelectPath !== void 0,
104
+ ...source ? { source } : {},
105
+ ...evaluate ? { evaluate } : {},
106
+ title: `${ariaLabel ?? "JSONPath"} playground`
107
+ }
108
+ )
109
+ ] });
89
110
  }
90
111
  exports.JSONPathField = JSONPathField;
91
112
  //# sourceMappingURL=JSONPathField.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"JSONPathField.cjs","sources":["../../src/components/JSONPathField.tsx"],"sourcesContent":["import { useMemo } from \"react\";\nimport { UiListTree } from \"../icons\";\nimport { IconButton } from \"./IconButton\";\nimport { InputField, type InputFieldInputProps } from \"./InputField\";\nimport { TreePickerField } from \"./TreePickerField\";\n\nconst MAX_DEPTH = 12;\nconst MAX_OBJECT_PROPERTIES = 100;\nconst SIMPLE_PROPERTY = /^[A-Za-z_$][A-Za-z0-9_$]*$/;\n\nexport interface JSONPathNode {\n key: string;\n path: string;\n value: unknown;\n kind: \"array\" | \"object\" | \"scalar\";\n summary: string;\n children?: JSONPathNode[];\n}\n\nexport type JSONPathFieldProps = Omit<InputFieldInputProps, \"onChange\" | \"suffix\" | \"value\"> & {\n json?: unknown;\n value: string;\n onChange: (path: string) => void;\n isSelectable?: (node: JSONPathNode) => boolean;\n getPath?: (node: JSONPathNode) => string;\n pickerLabel?: string;\n};\n\nexport function JSONPathField({\n json,\n value,\n onChange,\n isSelectable,\n getPath,\n pickerLabel,\n disabled,\n className,\n \"aria-label\": ariaLabel,\n ...inputProps\n}: JSONPathFieldProps) {\n const roots = useMemo(() => json === undefined ? [] : [buildJSONPathNode(json, \"$\", 0)], [json]);\n const browseLabel = pickerLabel ?? `Browse ${ariaLabel ?? \"JSONPath\"} JSON paths`;\n const pickerDisabled = Boolean(disabled) || json === undefined;\n\n return (\n <TreePickerField<JSONPathNode>\n className=\"w-full\"\n roots={roots}\n getKey={(node) => node.key}\n getChildren={(node) => node.children}\n getSearchText={(node) => `${node.path} ${node.summary}`}\n defaultOpen={(_node, depth) => depth < 2}\n {...(isSelectable ? { isSelectable } : {})}\n disabled={pickerDisabled}\n onSelect={(node) => onChange(getPath?.(node) ?? node.path)}\n renderRow={({ node }) => (\n <span className=\"flex min-w-0 flex-1 items-center gap-density-2 font-mono text-xs\">\n <span className=\"shrink-0 text-primary\">{node.path}</span>\n <span className=\"truncate text-muted-foreground\" title={node.summary}>{node.summary}</span>\n </span>\n )}\n renderTrigger={({ open, triggerRef, toggle }) => (\n <InputField\n {...inputProps}\n {...(disabled !== undefined ? { disabled } : {})}\n aria-label={ariaLabel}\n className={className}\n value={value}\n onChange={onChange}\n suffix={(\n <IconButton\n ref={triggerRef}\n icon={UiListTree}\n label={browseLabel}\n disabled={pickerDisabled}\n aria-haspopup=\"tree\"\n aria-expanded={open}\n onClick={toggle}\n />\n )}\n />\n )}\n />\n );\n}\n\nfunction buildJSONPathNode(value: unknown, path: string, depth: number): JSONPathNode {\n const kind = Array.isArray(value) ? \"array\" : value !== null && typeof value === \"object\" ? \"object\" : \"scalar\";\n const node: JSONPathNode = { key: path, path, value, kind, summary: summarizeJSON(value) };\n if (kind === \"scalar\" || depth >= MAX_DEPTH) return node;\n const entries = Array.isArray(value)\n ? value.length > 0 ? [[0, value[0]] as const] : []\n : Object.entries(value as Record<string, unknown>).slice(0, MAX_OBJECT_PROPERTIES);\n node.children = entries.map(([key, child]) => buildJSONPathNode(child, appendJSONPath(path, key), depth + 1));\n return node;\n}\n\nfunction appendJSONPath(path: string, key: string | number): string {\n if (typeof key === \"number\") return `${path}[${key}]`;\n return SIMPLE_PROPERTY.test(key) ? `${path}.${key}` : `${path}[${JSON.stringify(key)}]`;\n}\n\nfunction summarizeJSON(value: unknown): string {\n if (Array.isArray(value)) return `[${value.length} item${value.length === 1 ? \"\" : \"s\"}]`;\n if (value !== null && typeof value === \"object\") {\n const count = Object.keys(value).length;\n return `{${count} ${count === 1 ? \"property\" : \"properties\"}}`;\n }\n if (typeof value === \"string\") return JSON.stringify(value.length > 80 ? `${value.slice(0, 77)}…` : value);\n return String(value);\n}\n"],"names":["useMemo","jsx","TreePickerField","jsxs","InputField","IconButton","UiListTree"],"mappings":"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"}
1
+ {"version":3,"file":"JSONPathField.cjs","sources":["../../src/components/JSONPathField.tsx"],"sourcesContent":["import { useMemo, useState } from \"react\";\nimport { UiFullscreen, UiListTree } from \"../icons\";\nimport { Icon } from \"../data/Icon\";\nimport { IconButton } from \"./IconButton\";\nimport { InputField, type InputFieldInputProps } from \"./InputField\";\nimport { buildJSONPathNode, type JSONPathNode } from \"./jsonPathTree\";\nimport {\n JSONPathPlayground,\n type JSONPathEvalRequest,\n type JSONPathEvalResult,\n} from \"./JSONPathPlayground\";\nimport { TreePickerField } from \"./TreePickerField\";\n\nexport type { JSONPathNode } from \"./jsonPathTree\";\n\nexport type JSONPathFieldProps = Omit<InputFieldInputProps, \"onChange\" | \"suffix\" | \"value\"> & {\n json?: unknown;\n value: string;\n onChange: (path: string) => void;\n isSelectable?: (node: JSONPathNode) => boolean;\n getPath?: (node: JSONPathNode) => string;\n pickerLabel?: string;\n /**\n * Every sampled row, for the playground's row switcher. Defaults to `json`\n * alone — a field absent from the first row cannot be browsed otherwise.\n */\n rows?: unknown[];\n /** Enables the playground's live match preview. See JSONPathPlaygroundProps. */\n evaluate?: (request: JSONPathEvalRequest) => Promise<JSONPathEvalResult>;\n /**\n * Commits a picked path together with the column it must be rooted at, set\n * when the path addresses a decoded JSON-encoded column. Consumers that own\n * the whole column can write `source` alongside `jsonpath`; the default just\n * calls `onChange`, leaving the pairing to whoever writes `source` by hand.\n */\n onSelectPath?: (path: string, context: { root?: string }) => void;\n /**\n * The column the current path is already rooted at — its saved `source`. The\n * playground browses and evaluates from there, so a column that already pairs\n * the two does not read as broken.\n */\n source?: string;\n};\n\nexport function JSONPathField({\n json,\n value,\n onChange,\n isSelectable,\n getPath,\n pickerLabel,\n rows,\n evaluate,\n onSelectPath,\n source,\n disabled,\n className,\n \"aria-label\": ariaLabel,\n ...inputProps\n}: JSONPathFieldProps) {\n const [playgroundOpen, setPlaygroundOpen] = useState(false);\n const roots = useMemo(() => json === undefined ? [] : [buildJSONPathNode(json, \"$\", 0)], [json]);\n const playgroundRows = useMemo(\n () => rows ?? (json === undefined ? [] : [json]),\n [rows, json],\n );\n const browseLabel = pickerLabel ?? `Browse ${ariaLabel ?? \"JSONPath\"} JSON paths`;\n const pickerDisabled = Boolean(disabled) || json === undefined;\n const commit = onSelectPath ?? ((path: string) => onChange(path));\n\n return (\n <>\n <TreePickerField<JSONPathNode>\n className=\"w-full\"\n roots={roots}\n getKey={(node) => node.key}\n getChildren={(node) => node.children}\n getSearchText={(node) => `${node.path} ${node.summary}`}\n defaultOpen={(_node, depth) => depth < 2}\n {...(isSelectable ? { isSelectable } : {})}\n disabled={pickerDisabled}\n onSelect={(node) => onChange(getPath?.(node) ?? node.path)}\n // The dropdown caps its walk to open instantly, so it can run out of\n // room on a document this row happens to be. The playground is where\n // that document is browsed in full.\n renderFooter={({ close }) => (\n <button\n type=\"button\"\n onClick={() => {\n close();\n setPlaygroundOpen(true);\n }}\n className=\"flex w-full items-center gap-2 px-3 py-2 text-left text-xs text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n >\n <Icon icon={UiFullscreen} className=\"text-xs\" />\n Open playground…\n </button>\n )}\n renderRow={({ node }) => (\n <span className=\"flex min-w-0 flex-1 items-center gap-density-2 font-mono text-xs\">\n <span className=\"shrink-0 text-primary\">{node.path}</span>\n <span className=\"truncate text-muted-foreground\" title={node.summary}>{node.summary}</span>\n </span>\n )}\n renderTrigger={({ open, triggerRef, toggle }) => (\n <InputField\n {...inputProps}\n {...(disabled !== undefined ? { disabled } : {})}\n aria-label={ariaLabel}\n className={className}\n value={value}\n onChange={onChange}\n suffix={(\n <IconButton\n ref={triggerRef}\n icon={UiListTree}\n label={browseLabel}\n disabled={pickerDisabled}\n aria-haspopup=\"tree\"\n aria-expanded={open}\n onClick={toggle}\n />\n )}\n />\n )}\n />\n {playgroundOpen && (\n <JSONPathPlayground\n open\n onClose={() => setPlaygroundOpen(false)}\n rows={playgroundRows}\n value={value}\n onCommit={commit}\n assignsRoot={onSelectPath !== undefined}\n {...(source ? { source } : {})}\n {...(evaluate ? { evaluate } : {})}\n title={`${ariaLabel ?? \"JSONPath\"} playground`}\n />\n )}\n </>\n );\n}\n"],"names":["useState","useMemo","buildJSONPathNode","jsxs","Fragment","jsx","TreePickerField","Icon","UiFullscreen","InputField","IconButton","UiListTree","JSONPathPlayground"],"mappings":"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"}
@@ -1,12 +1,7 @@
1
1
  import { InputFieldInputProps } from './InputField';
2
- export interface JSONPathNode {
3
- key: string;
4
- path: string;
5
- value: unknown;
6
- kind: "array" | "object" | "scalar";
7
- summary: string;
8
- children?: JSONPathNode[];
9
- }
2
+ import { JSONPathNode } from './jsonPathTree';
3
+ import { JSONPathEvalRequest, JSONPathEvalResult } from './JSONPathPlayground';
4
+ export type { JSONPathNode } from './jsonPathTree';
10
5
  export type JSONPathFieldProps = Omit<InputFieldInputProps, "onChange" | "suffix" | "value"> & {
11
6
  json?: unknown;
12
7
  value: string;
@@ -14,6 +9,28 @@ export type JSONPathFieldProps = Omit<InputFieldInputProps, "onChange" | "suffix
14
9
  isSelectable?: (node: JSONPathNode) => boolean;
15
10
  getPath?: (node: JSONPathNode) => string;
16
11
  pickerLabel?: string;
12
+ /**
13
+ * Every sampled row, for the playground's row switcher. Defaults to `json`
14
+ * alone — a field absent from the first row cannot be browsed otherwise.
15
+ */
16
+ rows?: unknown[];
17
+ /** Enables the playground's live match preview. See JSONPathPlaygroundProps. */
18
+ evaluate?: (request: JSONPathEvalRequest) => Promise<JSONPathEvalResult>;
19
+ /**
20
+ * Commits a picked path together with the column it must be rooted at, set
21
+ * when the path addresses a decoded JSON-encoded column. Consumers that own
22
+ * the whole column can write `source` alongside `jsonpath`; the default just
23
+ * calls `onChange`, leaving the pairing to whoever writes `source` by hand.
24
+ */
25
+ onSelectPath?: (path: string, context: {
26
+ root?: string;
27
+ }) => void;
28
+ /**
29
+ * The column the current path is already rooted at — its saved `source`. The
30
+ * playground browses and evaluates from there, so a column that already pairs
31
+ * the two does not read as broken.
32
+ */
33
+ source?: string;
17
34
  };
18
- export declare function JSONPathField({ json, value, onChange, isSelectable, getPath, pickerLabel, disabled, className, "aria-label": ariaLabel, ...inputProps }: JSONPathFieldProps): import("react/jsx-runtime").JSX.Element;
35
+ export declare function JSONPathField({ json, value, onChange, isSelectable, getPath, pickerLabel, rows, evaluate, onSelectPath, source, disabled, className, "aria-label": ariaLabel, ...inputProps }: JSONPathFieldProps): import("react/jsx-runtime").JSX.Element;
19
36
  //# sourceMappingURL=JSONPathField.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"JSONPathField.d.ts","sourceRoot":"","sources":["../../src/components/JSONPathField.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAc,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAOrE,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;CAC3B;AAED,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,oBAAoB,EAAE,UAAU,GAAG,QAAQ,GAAG,OAAO,CAAC,GAAG;IAC7F,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC;IAC/C,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,MAAM,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,OAAO,EACP,WAAW,EACX,QAAQ,EACR,SAAS,EACT,YAAY,EAAE,SAAS,EACvB,GAAG,UAAU,EACd,EAAE,kBAAkB,2CA6CpB"}
1
+ {"version":3,"file":"JSONPathField.d.ts","sourceRoot":"","sources":["../../src/components/JSONPathField.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAc,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACxB,MAAM,sBAAsB,CAAC;AAG9B,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,oBAAoB,EAAE,UAAU,GAAG,QAAQ,GAAG,OAAO,CAAC,GAAG;IAC7F,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC;IAC/C,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,MAAM,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;IACjB,gFAAgF;IAChF,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACzE;;;;;OAKG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAClE;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,OAAO,EACP,WAAW,EACX,IAAI,EACJ,QAAQ,EACR,YAAY,EACZ,MAAM,EACN,QAAQ,EACR,SAAS,EACT,YAAY,EAAE,SAAS,EACvB,GAAG,UAAU,EACd,EAAE,kBAAkB,2CAkFpB"}
@@ -1,12 +1,13 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
2
- import { useMemo } from "react";
1
+ import { jsxs, Fragment, jsx } from "react/jsx-runtime";
2
+ import { useState, useMemo } from "react";
3
+ import { Icon } from "../data/Icon.js";
3
4
  import { IconButton } from "./IconButton.js";
4
5
  import { InputField } from "./InputField.js";
6
+ import { buildJSONPathNode } from "./jsonPathTree.js";
7
+ import { JSONPathPlayground } from "./JSONPathPlayground.js";
5
8
  import { TreePickerField } from "./TreePickerField.js";
6
9
  import { UiListTree } from "../icons/components/UiListTree.js";
7
- const MAX_DEPTH = 12;
8
- const MAX_OBJECT_PROPERTIES = 100;
9
- const SIMPLE_PROPERTY = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
10
+ import { UiFullscreen } from "../icons/components/UiFullscreen.js";
10
11
  function JSONPathField({
11
12
  json,
12
13
  value,
@@ -14,76 +15,96 @@ function JSONPathField({
14
15
  isSelectable,
15
16
  getPath,
16
17
  pickerLabel,
18
+ rows,
19
+ evaluate,
20
+ onSelectPath,
21
+ source,
17
22
  disabled,
18
23
  className,
19
24
  "aria-label": ariaLabel,
20
25
  ...inputProps
21
26
  }) {
27
+ const [playgroundOpen, setPlaygroundOpen] = useState(false);
22
28
  const roots = useMemo(() => json === void 0 ? [] : [buildJSONPathNode(json, "$", 0)], [json]);
29
+ const playgroundRows = useMemo(
30
+ () => rows ?? (json === void 0 ? [] : [json]),
31
+ [rows, json]
32
+ );
23
33
  const browseLabel = pickerLabel ?? `Browse ${ariaLabel ?? "JSONPath"} JSON paths`;
24
34
  const pickerDisabled = Boolean(disabled) || json === void 0;
25
- return /* @__PURE__ */ jsx(
26
- TreePickerField,
27
- {
28
- className: "w-full",
29
- roots,
30
- getKey: (node) => node.key,
31
- getChildren: (node) => node.children,
32
- getSearchText: (node) => `${node.path} ${node.summary}`,
33
- defaultOpen: (_node, depth) => depth < 2,
34
- ...isSelectable ? { isSelectable } : {},
35
- disabled: pickerDisabled,
36
- onSelect: (node) => onChange((getPath == null ? void 0 : getPath(node)) ?? node.path),
37
- renderRow: ({ node }) => /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-density-2 font-mono text-xs", children: [
38
- /* @__PURE__ */ jsx("span", { className: "shrink-0 text-primary", children: node.path }),
39
- /* @__PURE__ */ jsx("span", { className: "truncate text-muted-foreground", title: node.summary, children: node.summary })
40
- ] }),
41
- renderTrigger: ({ open, triggerRef, toggle }) => /* @__PURE__ */ jsx(
42
- InputField,
43
- {
44
- ...inputProps,
45
- ...disabled !== void 0 ? { disabled } : {},
46
- "aria-label": ariaLabel,
47
- className,
48
- value,
49
- onChange,
50
- suffix: /* @__PURE__ */ jsx(
51
- IconButton,
52
- {
53
- ref: triggerRef,
54
- icon: UiListTree,
55
- label: browseLabel,
56
- disabled: pickerDisabled,
57
- "aria-haspopup": "tree",
58
- "aria-expanded": open,
59
- onClick: toggle
60
- }
61
- )
62
- }
63
- )
64
- }
65
- );
66
- }
67
- function buildJSONPathNode(value, path, depth) {
68
- const kind = Array.isArray(value) ? "array" : value !== null && typeof value === "object" ? "object" : "scalar";
69
- const node = { key: path, path, value, kind, summary: summarizeJSON(value) };
70
- if (kind === "scalar" || depth >= MAX_DEPTH) return node;
71
- const entries = Array.isArray(value) ? value.length > 0 ? [[0, value[0]]] : [] : Object.entries(value).slice(0, MAX_OBJECT_PROPERTIES);
72
- node.children = entries.map(([key, child]) => buildJSONPathNode(child, appendJSONPath(path, key), depth + 1));
73
- return node;
74
- }
75
- function appendJSONPath(path, key) {
76
- if (typeof key === "number") return `${path}[${key}]`;
77
- return SIMPLE_PROPERTY.test(key) ? `${path}.${key}` : `${path}[${JSON.stringify(key)}]`;
78
- }
79
- function summarizeJSON(value) {
80
- if (Array.isArray(value)) return `[${value.length} item${value.length === 1 ? "" : "s"}]`;
81
- if (value !== null && typeof value === "object") {
82
- const count = Object.keys(value).length;
83
- return `{${count} ${count === 1 ? "property" : "properties"}}`;
84
- }
85
- if (typeof value === "string") return JSON.stringify(value.length > 80 ? `${value.slice(0, 77)}…` : value);
86
- return String(value);
35
+ const commit = onSelectPath ?? ((path) => onChange(path));
36
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
37
+ /* @__PURE__ */ jsx(
38
+ TreePickerField,
39
+ {
40
+ className: "w-full",
41
+ roots,
42
+ getKey: (node) => node.key,
43
+ getChildren: (node) => node.children,
44
+ getSearchText: (node) => `${node.path} ${node.summary}`,
45
+ defaultOpen: (_node, depth) => depth < 2,
46
+ ...isSelectable ? { isSelectable } : {},
47
+ disabled: pickerDisabled,
48
+ onSelect: (node) => onChange((getPath == null ? void 0 : getPath(node)) ?? node.path),
49
+ renderFooter: ({ close }) => /* @__PURE__ */ jsxs(
50
+ "button",
51
+ {
52
+ type: "button",
53
+ onClick: () => {
54
+ close();
55
+ setPlaygroundOpen(true);
56
+ },
57
+ className: "flex w-full items-center gap-2 px-3 py-2 text-left text-xs text-muted-foreground hover:bg-accent hover:text-accent-foreground",
58
+ children: [
59
+ /* @__PURE__ */ jsx(Icon, { icon: UiFullscreen, className: "text-xs" }),
60
+ "Open playground…"
61
+ ]
62
+ }
63
+ ),
64
+ renderRow: ({ node }) => /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-density-2 font-mono text-xs", children: [
65
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 text-primary", children: node.path }),
66
+ /* @__PURE__ */ jsx("span", { className: "truncate text-muted-foreground", title: node.summary, children: node.summary })
67
+ ] }),
68
+ renderTrigger: ({ open, triggerRef, toggle }) => /* @__PURE__ */ jsx(
69
+ InputField,
70
+ {
71
+ ...inputProps,
72
+ ...disabled !== void 0 ? { disabled } : {},
73
+ "aria-label": ariaLabel,
74
+ className,
75
+ value,
76
+ onChange,
77
+ suffix: /* @__PURE__ */ jsx(
78
+ IconButton,
79
+ {
80
+ ref: triggerRef,
81
+ icon: UiListTree,
82
+ label: browseLabel,
83
+ disabled: pickerDisabled,
84
+ "aria-haspopup": "tree",
85
+ "aria-expanded": open,
86
+ onClick: toggle
87
+ }
88
+ )
89
+ }
90
+ )
91
+ }
92
+ ),
93
+ playgroundOpen && /* @__PURE__ */ jsx(
94
+ JSONPathPlayground,
95
+ {
96
+ open: true,
97
+ onClose: () => setPlaygroundOpen(false),
98
+ rows: playgroundRows,
99
+ value,
100
+ onCommit: commit,
101
+ assignsRoot: onSelectPath !== void 0,
102
+ ...source ? { source } : {},
103
+ ...evaluate ? { evaluate } : {},
104
+ title: `${ariaLabel ?? "JSONPath"} playground`
105
+ }
106
+ )
107
+ ] });
87
108
  }
88
109
  export {
89
110
  JSONPathField
@@ -1 +1 @@
1
- {"version":3,"file":"JSONPathField.js","sources":["../../src/components/JSONPathField.tsx"],"sourcesContent":["import { useMemo } from \"react\";\nimport { UiListTree } from \"../icons\";\nimport { IconButton } from \"./IconButton\";\nimport { InputField, type InputFieldInputProps } from \"./InputField\";\nimport { TreePickerField } from \"./TreePickerField\";\n\nconst MAX_DEPTH = 12;\nconst MAX_OBJECT_PROPERTIES = 100;\nconst SIMPLE_PROPERTY = /^[A-Za-z_$][A-Za-z0-9_$]*$/;\n\nexport interface JSONPathNode {\n key: string;\n path: string;\n value: unknown;\n kind: \"array\" | \"object\" | \"scalar\";\n summary: string;\n children?: JSONPathNode[];\n}\n\nexport type JSONPathFieldProps = Omit<InputFieldInputProps, \"onChange\" | \"suffix\" | \"value\"> & {\n json?: unknown;\n value: string;\n onChange: (path: string) => void;\n isSelectable?: (node: JSONPathNode) => boolean;\n getPath?: (node: JSONPathNode) => string;\n pickerLabel?: string;\n};\n\nexport function JSONPathField({\n json,\n value,\n onChange,\n isSelectable,\n getPath,\n pickerLabel,\n disabled,\n className,\n \"aria-label\": ariaLabel,\n ...inputProps\n}: JSONPathFieldProps) {\n const roots = useMemo(() => json === undefined ? [] : [buildJSONPathNode(json, \"$\", 0)], [json]);\n const browseLabel = pickerLabel ?? `Browse ${ariaLabel ?? \"JSONPath\"} JSON paths`;\n const pickerDisabled = Boolean(disabled) || json === undefined;\n\n return (\n <TreePickerField<JSONPathNode>\n className=\"w-full\"\n roots={roots}\n getKey={(node) => node.key}\n getChildren={(node) => node.children}\n getSearchText={(node) => `${node.path} ${node.summary}`}\n defaultOpen={(_node, depth) => depth < 2}\n {...(isSelectable ? { isSelectable } : {})}\n disabled={pickerDisabled}\n onSelect={(node) => onChange(getPath?.(node) ?? node.path)}\n renderRow={({ node }) => (\n <span className=\"flex min-w-0 flex-1 items-center gap-density-2 font-mono text-xs\">\n <span className=\"shrink-0 text-primary\">{node.path}</span>\n <span className=\"truncate text-muted-foreground\" title={node.summary}>{node.summary}</span>\n </span>\n )}\n renderTrigger={({ open, triggerRef, toggle }) => (\n <InputField\n {...inputProps}\n {...(disabled !== undefined ? { disabled } : {})}\n aria-label={ariaLabel}\n className={className}\n value={value}\n onChange={onChange}\n suffix={(\n <IconButton\n ref={triggerRef}\n icon={UiListTree}\n label={browseLabel}\n disabled={pickerDisabled}\n aria-haspopup=\"tree\"\n aria-expanded={open}\n onClick={toggle}\n />\n )}\n />\n )}\n />\n );\n}\n\nfunction buildJSONPathNode(value: unknown, path: string, depth: number): JSONPathNode {\n const kind = Array.isArray(value) ? \"array\" : value !== null && typeof value === \"object\" ? \"object\" : \"scalar\";\n const node: JSONPathNode = { key: path, path, value, kind, summary: summarizeJSON(value) };\n if (kind === \"scalar\" || depth >= MAX_DEPTH) return node;\n const entries = Array.isArray(value)\n ? value.length > 0 ? [[0, value[0]] as const] : []\n : Object.entries(value as Record<string, unknown>).slice(0, MAX_OBJECT_PROPERTIES);\n node.children = entries.map(([key, child]) => buildJSONPathNode(child, appendJSONPath(path, key), depth + 1));\n return node;\n}\n\nfunction appendJSONPath(path: string, key: string | number): string {\n if (typeof key === \"number\") return `${path}[${key}]`;\n return SIMPLE_PROPERTY.test(key) ? `${path}.${key}` : `${path}[${JSON.stringify(key)}]`;\n}\n\nfunction summarizeJSON(value: unknown): string {\n if (Array.isArray(value)) return `[${value.length} item${value.length === 1 ? \"\" : \"s\"}]`;\n if (value !== null && typeof value === \"object\") {\n const count = Object.keys(value).length;\n return `{${count} ${count === 1 ? \"property\" : \"properties\"}}`;\n }\n if (typeof value === \"string\") return JSON.stringify(value.length > 80 ? `${value.slice(0, 77)}…` : value);\n return String(value);\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"JSONPathField.js","sources":["../../src/components/JSONPathField.tsx"],"sourcesContent":["import { useMemo, useState } from \"react\";\nimport { UiFullscreen, UiListTree } from \"../icons\";\nimport { Icon } from \"../data/Icon\";\nimport { IconButton } from \"./IconButton\";\nimport { InputField, type InputFieldInputProps } from \"./InputField\";\nimport { buildJSONPathNode, type JSONPathNode } from \"./jsonPathTree\";\nimport {\n JSONPathPlayground,\n type JSONPathEvalRequest,\n type JSONPathEvalResult,\n} from \"./JSONPathPlayground\";\nimport { TreePickerField } from \"./TreePickerField\";\n\nexport type { JSONPathNode } from \"./jsonPathTree\";\n\nexport type JSONPathFieldProps = Omit<InputFieldInputProps, \"onChange\" | \"suffix\" | \"value\"> & {\n json?: unknown;\n value: string;\n onChange: (path: string) => void;\n isSelectable?: (node: JSONPathNode) => boolean;\n getPath?: (node: JSONPathNode) => string;\n pickerLabel?: string;\n /**\n * Every sampled row, for the playground's row switcher. Defaults to `json`\n * alone — a field absent from the first row cannot be browsed otherwise.\n */\n rows?: unknown[];\n /** Enables the playground's live match preview. See JSONPathPlaygroundProps. */\n evaluate?: (request: JSONPathEvalRequest) => Promise<JSONPathEvalResult>;\n /**\n * Commits a picked path together with the column it must be rooted at, set\n * when the path addresses a decoded JSON-encoded column. Consumers that own\n * the whole column can write `source` alongside `jsonpath`; the default just\n * calls `onChange`, leaving the pairing to whoever writes `source` by hand.\n */\n onSelectPath?: (path: string, context: { root?: string }) => void;\n /**\n * The column the current path is already rooted at — its saved `source`. The\n * playground browses and evaluates from there, so a column that already pairs\n * the two does not read as broken.\n */\n source?: string;\n};\n\nexport function JSONPathField({\n json,\n value,\n onChange,\n isSelectable,\n getPath,\n pickerLabel,\n rows,\n evaluate,\n onSelectPath,\n source,\n disabled,\n className,\n \"aria-label\": ariaLabel,\n ...inputProps\n}: JSONPathFieldProps) {\n const [playgroundOpen, setPlaygroundOpen] = useState(false);\n const roots = useMemo(() => json === undefined ? [] : [buildJSONPathNode(json, \"$\", 0)], [json]);\n const playgroundRows = useMemo(\n () => rows ?? (json === undefined ? [] : [json]),\n [rows, json],\n );\n const browseLabel = pickerLabel ?? `Browse ${ariaLabel ?? \"JSONPath\"} JSON paths`;\n const pickerDisabled = Boolean(disabled) || json === undefined;\n const commit = onSelectPath ?? ((path: string) => onChange(path));\n\n return (\n <>\n <TreePickerField<JSONPathNode>\n className=\"w-full\"\n roots={roots}\n getKey={(node) => node.key}\n getChildren={(node) => node.children}\n getSearchText={(node) => `${node.path} ${node.summary}`}\n defaultOpen={(_node, depth) => depth < 2}\n {...(isSelectable ? { isSelectable } : {})}\n disabled={pickerDisabled}\n onSelect={(node) => onChange(getPath?.(node) ?? node.path)}\n // The dropdown caps its walk to open instantly, so it can run out of\n // room on a document this row happens to be. The playground is where\n // that document is browsed in full.\n renderFooter={({ close }) => (\n <button\n type=\"button\"\n onClick={() => {\n close();\n setPlaygroundOpen(true);\n }}\n className=\"flex w-full items-center gap-2 px-3 py-2 text-left text-xs text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n >\n <Icon icon={UiFullscreen} className=\"text-xs\" />\n Open playground…\n </button>\n )}\n renderRow={({ node }) => (\n <span className=\"flex min-w-0 flex-1 items-center gap-density-2 font-mono text-xs\">\n <span className=\"shrink-0 text-primary\">{node.path}</span>\n <span className=\"truncate text-muted-foreground\" title={node.summary}>{node.summary}</span>\n </span>\n )}\n renderTrigger={({ open, triggerRef, toggle }) => (\n <InputField\n {...inputProps}\n {...(disabled !== undefined ? { disabled } : {})}\n aria-label={ariaLabel}\n className={className}\n value={value}\n onChange={onChange}\n suffix={(\n <IconButton\n ref={triggerRef}\n icon={UiListTree}\n label={browseLabel}\n disabled={pickerDisabled}\n aria-haspopup=\"tree\"\n aria-expanded={open}\n onClick={toggle}\n />\n )}\n />\n )}\n />\n {playgroundOpen && (\n <JSONPathPlayground\n open\n onClose={() => setPlaygroundOpen(false)}\n rows={playgroundRows}\n value={value}\n onCommit={commit}\n assignsRoot={onSelectPath !== undefined}\n {...(source ? { source } : {})}\n {...(evaluate ? { evaluate } : {})}\n title={`${ariaLabel ?? \"JSONPath\"} playground`}\n />\n )}\n </>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;AA4CO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,GAAG;AACL,GAAuB;AACrB,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAS,KAAK;AAC1D,QAAM,QAAQ,QAAQ,MAAM,SAAS,SAAY,CAAA,IAAK,CAAC,kBAAkB,MAAM,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;AAC/F,QAAM,iBAAiB;AAAA,IACrB,MAAM,SAAS,SAAS,SAAY,CAAA,IAAK,CAAC,IAAI;AAAA,IAC9C,CAAC,MAAM,IAAI;AAAA,EAAA;AAEb,QAAM,cAAc,eAAe,UAAU,aAAa,UAAU;AACpE,QAAM,iBAAiB,QAAQ,QAAQ,KAAK,SAAS;AACrD,QAAM,SAAS,iBAAiB,CAAC,SAAiB,SAAS,IAAI;AAE/D,SACE,qBAAA,UAAA,EACE,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV;AAAA,QACA,QAAQ,CAAC,SAAS,KAAK;AAAA,QACvB,aAAa,CAAC,SAAS,KAAK;AAAA,QAC5B,eAAe,CAAC,SAAS,GAAG,KAAK,IAAI,IAAI,KAAK,OAAO;AAAA,QACrD,aAAa,CAAC,OAAO,UAAU,QAAQ;AAAA,QACtC,GAAI,eAAe,EAAE,aAAA,IAAiB,CAAA;AAAA,QACvC,UAAU;AAAA,QACV,UAAU,CAAC,SAAS,UAAS,mCAAU,UAAS,KAAK,IAAI;AAAA,QAIzD,cAAc,CAAC,EAAE,MAAA,MACf;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS,MAAM;AACb,oBAAA;AACA,gCAAkB,IAAI;AAAA,YACxB;AAAA,YACA,WAAU;AAAA,YAEV,UAAA;AAAA,cAAA,oBAAC,MAAA,EAAK,MAAM,cAAc,WAAU,WAAU;AAAA,cAAE;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAIpD,WAAW,CAAC,EAAE,WACZ,qBAAC,QAAA,EAAK,WAAU,oEACd,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAU,yBAAyB,UAAA,KAAK,MAAK;AAAA,UACnD,oBAAC,UAAK,WAAU,kCAAiC,OAAO,KAAK,SAAU,eAAK,QAAA,CAAQ;AAAA,QAAA,GACtF;AAAA,QAEF,eAAe,CAAC,EAAE,MAAM,YAAY,aAClC;AAAA,UAAC;AAAA,UAAA;AAAA,YACE,GAAG;AAAA,YACH,GAAI,aAAa,SAAY,EAAE,SAAA,IAAa,CAAA;AAAA,YAC7C,cAAY;AAAA,YACZ;AAAA,YACA;AAAA,YACA;AAAA,YACA,QACE;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,KAAK;AAAA,gBACL,MAAM;AAAA,gBACN,OAAO;AAAA,gBACP,UAAU;AAAA,gBACV,iBAAc;AAAA,gBACd,iBAAe;AAAA,gBACf,SAAS;AAAA,cAAA;AAAA,YAAA;AAAA,UACX;AAAA,QAAA;AAAA,MAEJ;AAAA,IAAA;AAAA,IAGH,kBACC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAI;AAAA,QACJ,SAAS,MAAM,kBAAkB,KAAK;AAAA,QACtC,MAAM;AAAA,QACN;AAAA,QACA,UAAU;AAAA,QACV,aAAa,iBAAiB;AAAA,QAC7B,GAAI,SAAS,EAAE,OAAA,IAAW,CAAA;AAAA,QAC1B,GAAI,WAAW,EAAE,SAAA,IAAa,CAAA;AAAA,QAC/B,OAAO,GAAG,aAAa,UAAU;AAAA,MAAA;AAAA,IAAA;AAAA,EACnC,GAEJ;AAEJ;"}