@pythia-software/query-table-ui 0.2.0 → 0.3.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.
package/README.md CHANGED
@@ -55,6 +55,11 @@ current query, including a saved default query. Configure `useQueryTable` with
55
55
  `syncUrl: true` so recipients load shared query URLs. Query tokens are encoded,
56
56
  not encrypted, and may contain raw filter values.
57
57
 
58
+ `SelectionToolbar` action callbacks receive `(selectedIds, selection)`, so
59
+ consumer-owned bulk actions can call `selection.replace(ids)` or
60
+ `selection.retain(ids)` atomically. Existing callbacks that use only the first
61
+ argument remain compatible.
62
+
58
63
  ## Mobile behavior
59
64
 
60
65
  The bundled theme keeps the table as a horizontally scrollable grid on narrow
@@ -72,3 +77,7 @@ providing their own responsive and touch-target styles.
72
77
 
73
78
  See the [repository README](https://github.com/Pythia-Software/query-table#readme)
74
79
  for customization and backend integration details.
80
+
81
+ ## SELECT editor
82
+
83
+ `QueryBuilder` includes an **Edit columns** action. The exported `SelectColumnEditor` also accepts `{ api, onClose }` for standalone use. It supports draft column ordering, a searchable catalogue, sampled value frequencies, and a lazy-loaded CodeMirror formula editor with grouped live previews and regex inspection. Shared-definition saves and query-layout application are separate actions.
@@ -0,0 +1,251 @@
1
+ // src/FormulaEditor.tsx
2
+ import { useEffect, useRef, useState } from "react";
3
+ import { EditorState } from "@codemirror/state";
4
+ import {
5
+ EditorView,
6
+ keymap,
7
+ lineNumbers,
8
+ hoverTooltip
9
+ } from "@codemirror/view";
10
+ import { defaultKeymap, history, historyKeymap } from "@codemirror/commands";
11
+ import {
12
+ autocompletion,
13
+ completionKeymap,
14
+ closeBrackets,
15
+ closeBracketsKeymap
16
+ } from "@codemirror/autocomplete";
17
+ import { linter } from "@codemirror/lint";
18
+ import {
19
+ StreamLanguage,
20
+ syntaxHighlighting,
21
+ defaultHighlightStyle,
22
+ bracketMatching
23
+ } from "@codemirror/language";
24
+ import {
25
+ FORMULA_FUNCTIONS,
26
+ FormulaError
27
+ } from "@pythia-software/query-table-core";
28
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
29
+ var language = StreamLanguage.define({
30
+ token(stream) {
31
+ if (stream.eatSpace()) return null;
32
+ if (stream.match(/^"(?:[^"\\]|\\.)*"?/)) return "string";
33
+ if (stream.match(/^\[(?:[^\]]|\]\])*\]/)) return "variableName";
34
+ if (stream.match(/^(?:\d+(?:\.\d*)?|\.\d+)/)) return "number";
35
+ if (stream.match(/^(?:AND|OR|NOT|IN|BETWEEN|NULL|TRUE|FALSE)\b/i))
36
+ return "keyword";
37
+ if (stream.match(/^[a-zA-Z_][a-zA-Z_0-9]*/))
38
+ return "function(variableName)";
39
+ stream.next();
40
+ return "operator";
41
+ }
42
+ });
43
+ function signatureAt(text) {
44
+ const stack = [];
45
+ let quoted = false, field = false;
46
+ for (let i = 0; i < text.length; i++) {
47
+ const c = text[i];
48
+ if (quoted) {
49
+ if (c === "\\") i++;
50
+ else if (c === '"') quoted = false;
51
+ continue;
52
+ }
53
+ if (field) {
54
+ if (c === "]") {
55
+ if (text[i + 1] === "]") i++;
56
+ else field = false;
57
+ }
58
+ continue;
59
+ }
60
+ if (c === '"') {
61
+ quoted = true;
62
+ continue;
63
+ }
64
+ if (c === "[") {
65
+ field = true;
66
+ continue;
67
+ }
68
+ if (c === "(")
69
+ stack.push({
70
+ name: text.slice(0, i).match(/([A-Za-z_]+)\s*$/)?.[1]?.toUpperCase() ?? "",
71
+ argument: 1
72
+ });
73
+ else if (c === ")") stack.pop();
74
+ else if (c === "," && stack.length) stack[stack.length - 1].argument++;
75
+ }
76
+ const call = stack[stack.length - 1], spec = FORMULA_FUNCTIONS.find((f) => f.name === call?.name);
77
+ return spec && call ? `${spec.signature} \xB7 Argument ${call.argument} \u2014 ${spec.description}` : "Use [field] references. Ctrl+Space opens suggestions.";
78
+ }
79
+ function FormulaEditor({
80
+ value,
81
+ onChange,
82
+ fields,
83
+ compile
84
+ }) {
85
+ const [hint, setHint] = useState(
86
+ "Use [field] references. Ctrl+Space opens suggestions."
87
+ );
88
+ const parent = useRef(null), editor = useRef();
89
+ const latest = useRef({ onChange, fields, compile });
90
+ latest.current = { onChange, fields, compile };
91
+ useEffect(() => {
92
+ if (!parent.current) return;
93
+ const view = new EditorView({
94
+ parent: parent.current,
95
+ state: EditorState.create({
96
+ doc: value,
97
+ extensions: [
98
+ lineNumbers(),
99
+ history(),
100
+ language,
101
+ syntaxHighlighting(defaultHighlightStyle),
102
+ bracketMatching(),
103
+ closeBrackets(),
104
+ EditorView.lineWrapping,
105
+ EditorView.contentAttributes.of({
106
+ "aria-label": "Computed column formula",
107
+ spellcheck: "false"
108
+ }),
109
+ keymap.of([
110
+ ...closeBracketsKeymap,
111
+ ...completionKeymap,
112
+ ...defaultKeymap,
113
+ ...historyKeymap
114
+ ]),
115
+ autocompletion({
116
+ override: [
117
+ (context) => {
118
+ const word = context.matchBefore(
119
+ /\[[^\]]*|[a-zA-Z_][a-zA-Z_0-9]*/
120
+ );
121
+ if (!word && !context.explicit) return null;
122
+ return {
123
+ from: word?.from ?? context.pos,
124
+ options: [
125
+ ...latest.current.fields.map((f) => ({
126
+ label: `[${f.name.replace(/\]/g, "]]")}]`,
127
+ displayLabel: f.label,
128
+ detail: f.type,
129
+ type: "variable",
130
+ info: f.name
131
+ })),
132
+ ...FORMULA_FUNCTIONS.map((f) => ({
133
+ label: f.name,
134
+ type: "function",
135
+ detail: f.signature,
136
+ info: f.description,
137
+ apply: `${f.name}(`
138
+ })),
139
+ ...[
140
+ "TRUE",
141
+ "FALSE",
142
+ "NULL",
143
+ "AND",
144
+ "OR",
145
+ "NOT",
146
+ "IN",
147
+ "BETWEEN"
148
+ ].map((label) => ({ label, type: "keyword" }))
149
+ ]
150
+ };
151
+ }
152
+ ]
153
+ }),
154
+ linter(
155
+ (view2) => {
156
+ try {
157
+ latest.current.compile(view2.state.doc.toString());
158
+ return [];
159
+ } catch (e) {
160
+ return [
161
+ {
162
+ from: Math.min(
163
+ e instanceof FormulaError ? e.from : 0,
164
+ view2.state.doc.length
165
+ ),
166
+ to: Math.min(
167
+ e instanceof FormulaError ? e.to : view2.state.doc.length,
168
+ view2.state.doc.length
169
+ ),
170
+ severity: "error",
171
+ message: e instanceof Error ? e.message : String(e)
172
+ }
173
+ ];
174
+ }
175
+ },
176
+ { delay: 250 }
177
+ ),
178
+ hoverTooltip((view2, pos) => {
179
+ const line = view2.state.doc.lineAt(pos);
180
+ const left = line.text.slice(0, pos - line.from).match(/[A-Za-z_0-9]*$/)?.[0] ?? "";
181
+ const right = line.text.slice(pos - line.from).match(/^[A-Za-z_0-9]*/)?.[0] ?? "";
182
+ const spec = FORMULA_FUNCTIONS.find(
183
+ (f) => f.name === (left + right).toUpperCase()
184
+ );
185
+ if (!spec) return null;
186
+ return {
187
+ pos: pos - left.length,
188
+ end: pos + right.length,
189
+ create() {
190
+ const dom = document.createElement("div");
191
+ dom.className = "qt-function-help";
192
+ dom.textContent = `${spec.signature} \u2014 ${spec.description}`;
193
+ return { dom };
194
+ }
195
+ };
196
+ }),
197
+ EditorView.updateListener.of((update) => {
198
+ if (update.docChanged)
199
+ latest.current.onChange(update.state.doc.toString());
200
+ if (update.docChanged || update.selectionSet)
201
+ setHint(
202
+ signatureAt(
203
+ update.state.doc.sliceString(
204
+ 0,
205
+ update.state.selection.main.head
206
+ )
207
+ )
208
+ );
209
+ }),
210
+ EditorView.theme({
211
+ "&": {
212
+ fontSize: "13px",
213
+ border: "1px solid var(--qt-border, #cbd5e1)",
214
+ borderRadius: "6px"
215
+ },
216
+ ".cm-scroller": {
217
+ minHeight: "130px",
218
+ maxHeight: "260px",
219
+ fontFamily: "ui-monospace, monospace"
220
+ },
221
+ ".cm-content": { padding: "12px 0" },
222
+ ".cm-gutters": {
223
+ background: "var(--qt-bg-muted, #f8fafc)",
224
+ color: "var(--qt-muted, #64748b)"
225
+ }
226
+ })
227
+ ]
228
+ })
229
+ });
230
+ editor.current = view;
231
+ return () => {
232
+ view.destroy();
233
+ editor.current = void 0;
234
+ };
235
+ }, []);
236
+ useEffect(() => {
237
+ const view = editor.current;
238
+ if (view && view.state.doc.toString() !== value)
239
+ view.dispatch({
240
+ changes: { from: 0, to: view.state.doc.length, insert: value }
241
+ });
242
+ }, [value]);
243
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
244
+ /* @__PURE__ */ jsx("div", { ref: parent }),
245
+ /* @__PURE__ */ jsx("p", { className: "qt-formula-hint", "aria-live": "polite", children: hint })
246
+ ] });
247
+ }
248
+ export {
249
+ FormulaEditor as default
250
+ };
251
+ //# sourceMappingURL=FormulaEditor-YCPICDIH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/FormulaEditor.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { EditorState } from \"@codemirror/state\";\nimport {\n EditorView,\n keymap,\n lineNumbers,\n hoverTooltip,\n} from \"@codemirror/view\";\nimport { defaultKeymap, history, historyKeymap } from \"@codemirror/commands\";\nimport {\n autocompletion,\n completionKeymap,\n closeBrackets,\n closeBracketsKeymap,\n} from \"@codemirror/autocomplete\";\nimport { linter } from \"@codemirror/lint\";\nimport {\n StreamLanguage,\n syntaxHighlighting,\n defaultHighlightStyle,\n bracketMatching,\n} from \"@codemirror/language\";\nimport {\n FORMULA_FUNCTIONS,\n FormulaError,\n type FieldDef,\n type FormulaPlan,\n} from \"@pythia-software/query-table-core\";\n\nexport interface FormulaEditorProps {\n value: string;\n onChange: (value: string) => void;\n fields: FieldDef[];\n compile: (value: string) => FormulaPlan;\n}\nconst language = StreamLanguage.define({\n token(stream) {\n if (stream.eatSpace()) return null;\n if (stream.match(/^\"(?:[^\"\\\\]|\\\\.)*\"?/)) return \"string\";\n if (stream.match(/^\\[(?:[^\\]]|\\]\\])*\\]/)) return \"variableName\";\n if (stream.match(/^(?:\\d+(?:\\.\\d*)?|\\.\\d+)/)) return \"number\";\n if (stream.match(/^(?:AND|OR|NOT|IN|BETWEEN|NULL|TRUE|FALSE)\\b/i))\n return \"keyword\";\n if (stream.match(/^[a-zA-Z_][a-zA-Z_0-9]*/))\n return \"function(variableName)\";\n stream.next();\n return \"operator\";\n },\n});\nfunction signatureAt(text: string): string {\n const stack: { name: string; argument: number }[] = [];\n let quoted = false,\n field = false;\n for (let i = 0; i < text.length; i++) {\n const c = text[i];\n if (quoted) {\n if (c === \"\\\\\") i++;\n else if (c === '\"') quoted = false;\n continue;\n }\n if (field) {\n if (c === \"]\") {\n if (text[i + 1] === \"]\") i++;\n else field = false;\n }\n continue;\n }\n if (c === '\"') {\n quoted = true;\n continue;\n }\n if (c === \"[\") {\n field = true;\n continue;\n }\n if (c === \"(\")\n stack.push({\n name:\n text\n .slice(0, i)\n .match(/([A-Za-z_]+)\\s*$/)?.[1]\n ?.toUpperCase() ?? \"\",\n argument: 1,\n });\n else if (c === \")\") stack.pop();\n else if (c === \",\" && stack.length) stack[stack.length - 1]!.argument++;\n }\n const call = stack[stack.length - 1],\n spec = FORMULA_FUNCTIONS.find((f) => f.name === call?.name);\n return spec && call\n ? `${spec.signature} · Argument ${call.argument} — ${spec.description}`\n : \"Use [field] references. Ctrl+Space opens suggestions.\";\n}\nexport default function FormulaEditor({\n value,\n onChange,\n fields,\n compile,\n}: FormulaEditorProps) {\n const [hint, setHint] = useState(\n \"Use [field] references. Ctrl+Space opens suggestions.\",\n );\n const parent = useRef<HTMLDivElement>(null),\n editor = useRef<EditorView>();\n const latest = useRef({ onChange, fields, compile });\n latest.current = { onChange, fields, compile };\n useEffect(() => {\n if (!parent.current) return;\n const view = new EditorView({\n parent: parent.current,\n state: EditorState.create({\n doc: value,\n extensions: [\n lineNumbers(),\n history(),\n language,\n syntaxHighlighting(defaultHighlightStyle),\n bracketMatching(),\n closeBrackets(),\n EditorView.lineWrapping,\n EditorView.contentAttributes.of({\n \"aria-label\": \"Computed column formula\",\n spellcheck: \"false\",\n }),\n keymap.of([\n ...closeBracketsKeymap,\n ...completionKeymap,\n ...defaultKeymap,\n ...historyKeymap,\n ]),\n autocompletion({\n override: [\n (context) => {\n const word = context.matchBefore(\n /\\[[^\\]]*|[a-zA-Z_][a-zA-Z_0-9]*/,\n );\n if (!word && !context.explicit) return null;\n return {\n from: word?.from ?? context.pos,\n options: [\n ...latest.current.fields.map((f) => ({\n label: `[${f.name.replace(/\\]/g, \"]]\")}]`,\n displayLabel: f.label,\n detail: f.type,\n type: \"variable\",\n info: f.name,\n })),\n ...FORMULA_FUNCTIONS.map((f) => ({\n label: f.name,\n type: \"function\",\n detail: f.signature,\n info: f.description,\n apply: `${f.name}(`,\n })),\n ...[\n \"TRUE\",\n \"FALSE\",\n \"NULL\",\n \"AND\",\n \"OR\",\n \"NOT\",\n \"IN\",\n \"BETWEEN\",\n ].map((label) => ({ label, type: \"keyword\" })),\n ],\n };\n },\n ],\n }),\n linter(\n (view) => {\n try {\n latest.current.compile(view.state.doc.toString());\n return [];\n } catch (e) {\n return [\n {\n from: Math.min(\n e instanceof FormulaError ? e.from : 0,\n view.state.doc.length,\n ),\n to: Math.min(\n e instanceof FormulaError ? e.to : view.state.doc.length,\n view.state.doc.length,\n ),\n severity: \"error\" as const,\n message: e instanceof Error ? e.message : String(e),\n },\n ];\n }\n },\n { delay: 250 },\n ),\n hoverTooltip((view, pos) => {\n const line = view.state.doc.lineAt(pos);\n const left =\n line.text\n .slice(0, pos - line.from)\n .match(/[A-Za-z_0-9]*$/)?.[0] ?? \"\";\n const right =\n line.text.slice(pos - line.from).match(/^[A-Za-z_0-9]*/)?.[0] ??\n \"\";\n const spec = FORMULA_FUNCTIONS.find(\n (f) => f.name === (left + right).toUpperCase(),\n );\n if (!spec) return null;\n return {\n pos: pos - left.length,\n end: pos + right.length,\n create() {\n const dom = document.createElement(\"div\");\n dom.className = \"qt-function-help\";\n dom.textContent = `${spec.signature} — ${spec.description}`;\n return { dom };\n },\n };\n }),\n EditorView.updateListener.of((update) => {\n if (update.docChanged)\n latest.current.onChange(update.state.doc.toString());\n if (update.docChanged || update.selectionSet)\n setHint(\n signatureAt(\n update.state.doc.sliceString(\n 0,\n update.state.selection.main.head,\n ),\n ),\n );\n }),\n EditorView.theme({\n \"&\": {\n fontSize: \"13px\",\n border: \"1px solid var(--qt-border, #cbd5e1)\",\n borderRadius: \"6px\",\n },\n \".cm-scroller\": {\n minHeight: \"130px\",\n maxHeight: \"260px\",\n fontFamily: \"ui-monospace, monospace\",\n },\n \".cm-content\": { padding: \"12px 0\" },\n \".cm-gutters\": {\n background: \"var(--qt-bg-muted, #f8fafc)\",\n color: \"var(--qt-muted, #64748b)\",\n },\n }),\n ],\n }),\n });\n editor.current = view;\n return () => {\n view.destroy();\n editor.current = undefined;\n };\n }, []);\n useEffect(() => {\n const view = editor.current;\n if (view && view.state.doc.toString() !== value)\n view.dispatch({\n changes: { from: 0, to: view.state.doc.length, insert: value },\n });\n }, [value]);\n return (\n <>\n <div ref={parent} />\n <p className=\"qt-formula-hint\" aria-live=\"polite\">\n {hint}\n </p>\n </>\n );\n}\n"],"mappings":"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","names":["view"]}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { ReactNode, SetStateAction } from 'react';
2
2
  import { FieldDef, QueryState, RowId, FieldStats, WhereClause } from '@pythia-software/query-table-core';
3
3
  import { SelectionApi, ColumnDragApi, QueryTableApi, AggregationsApi, SavedQueriesApi } from '@pythia-software/query-table-react';
4
+ import * as react_jsx_runtime from 'react/jsx-runtime';
4
5
 
5
6
  interface CellContext<Row = any, V = unknown> {
6
7
  value: V;
@@ -153,9 +154,9 @@ declare function CellMenu<Row>({ field, value, x, y, onAddFilter, onClose, class
153
154
 
154
155
  interface SelectionToolbarProps {
155
156
  selection: SelectionApi;
156
- /** Consumer-rendered action buttons. Receives the selected ids so the consumer
157
- * can gate/enable actions (e.g. mixed-state rules). */
158
- actions: (selectedIds: RowId[]) => ReactNode;
157
+ /** Consumer-rendered action buttons. Receives the selected ids and the public
158
+ * selection API. Existing callbacks that accept only ids remain supported. */
159
+ actions: (selectedIds: RowId[], selection: SelectionApi) => ReactNode;
159
160
  /** Hidden when nothing is selected unless `alwaysShow`. */
160
161
  alwaysShow?: boolean;
161
162
  className?: string;
@@ -169,4 +170,10 @@ interface SavedQueriesModalProps {
169
170
  }
170
171
  declare function SavedQueriesModal({ saved, onClose, onLoad }: SavedQueriesModalProps): ReactNode;
171
172
 
172
- export { type CellContext, CellMenu, type CellMenuProps, type CellRenderer, DataTable, type DataTableProps, FieldPicker, type FieldPickerProps, type MenuClassNames, MetricsPanel, type MetricsPanelProps, QueryBuilder, type QueryBuilderClassNames, type QueryBuilderProps, type RenderRegistry, SavedQueriesModal, type SavedQueriesModalProps, SelectionToolbar, type SelectionToolbarProps, type TableClassNames, defaultRenderers, resolveRenderer, safeLinkHref };
173
+ interface SelectColumnEditorProps<Row> {
174
+ api: QueryTableApi<Row>;
175
+ onClose: () => void;
176
+ }
177
+ declare function SelectColumnEditor<Row>({ api, onClose, }: SelectColumnEditorProps<Row>): react_jsx_runtime.JSX.Element;
178
+
179
+ export { type CellContext, CellMenu, type CellMenuProps, type CellRenderer, DataTable, type DataTableProps, FieldPicker, type FieldPickerProps, type MenuClassNames, MetricsPanel, type MetricsPanelProps, QueryBuilder, type QueryBuilderClassNames, type QueryBuilderProps, type RenderRegistry, SavedQueriesModal, type SavedQueriesModalProps, SelectColumnEditor, type SelectColumnEditorProps, SelectionToolbar, type SelectionToolbarProps, type TableClassNames, defaultRenderers, resolveRenderer, safeLinkHref };