@pythia-software/query-table-ui 0.1.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 +36 -1
- package/dist/FormulaEditor-YCPICDIH.js +251 -0
- package/dist/FormulaEditor-YCPICDIH.js.map +1 -0
- package/dist/index.d.ts +18 -4
- package/dist/index.js +1853 -509
- package/dist/index.js.map +1 -1
- package/dist/theme.css +1084 -4
- package/dist/theme.css.map +1 -1
- package/package.json +13 -5
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ and selection toolbar.
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
npm install @pythia-software/query-table-core @pythia-software/query-table-react @pythia-software/query-table-ui react
|
|
10
|
+
npm install @pythia-software/query-table-core @pythia-software/query-table-react @pythia-software/query-table-ui react react-dom
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
## Use
|
|
@@ -40,9 +40,44 @@ export function OrdersTable({ table, schema }) {
|
|
|
40
40
|
}
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
+
`DataTable` virtualizes body rows and uses a 600px maximum-height scroll
|
|
44
|
+
viewport by default. Set `maxHeight` to match the surrounding layout;
|
|
45
|
+
`estimateRowHeight` (37px by default) and `overscan` (8 rows) are available for
|
|
46
|
+
unusually sized or expensive custom row renderers. Visible rows are measured,
|
|
47
|
+
so the estimate does not require every row to have a fixed height.
|
|
48
|
+
|
|
43
49
|
The bundled `link` renderer allows only HTTP(S), email, telephone, relative,
|
|
44
50
|
and fragment URLs. Applications remain responsible for validating URLs emitted
|
|
45
51
|
by custom renderers.
|
|
46
52
|
|
|
53
|
+
The query builder's **Share** button copies a URL containing the complete
|
|
54
|
+
current query, including a saved default query. Configure `useQueryTable` with
|
|
55
|
+
`syncUrl: true` so recipients load shared query URLs. Query tokens are encoded,
|
|
56
|
+
not encrypted, and may contain raw filter values.
|
|
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
|
+
|
|
63
|
+
## Mobile behavior
|
|
64
|
+
|
|
65
|
+
The bundled theme keeps the table as a horizontally scrollable grid on narrow
|
|
66
|
+
screens so columns remain comparable. It adds a scroll cue, touch-sized query
|
|
67
|
+
controls, button-based reordering alongside desktop drag-and-drop, sticky row
|
|
68
|
+
selection, single-column metric cards, and bottom-sheet menus and dialogs. Keep
|
|
69
|
+
the standard viewport meta tag in the host page:
|
|
70
|
+
|
|
71
|
+
```html
|
|
72
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Applications that omit `theme.css` and use only `classNames` are responsible for
|
|
76
|
+
providing their own responsive and touch-target styles.
|
|
77
|
+
|
|
47
78
|
See the [repository README](https://github.com/Pythia-Software/query-table#readme)
|
|
48
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;
|
|
@@ -29,6 +30,7 @@ interface TableClassNames {
|
|
|
29
30
|
headerRow?: string;
|
|
30
31
|
th?: string;
|
|
31
32
|
resizeHandle?: string;
|
|
33
|
+
resizeGuide?: string;
|
|
32
34
|
tbody?: string;
|
|
33
35
|
row?: string;
|
|
34
36
|
rowSelected?: string;
|
|
@@ -79,6 +81,12 @@ interface DataTableProps<Row> {
|
|
|
79
81
|
total?: number | null;
|
|
80
82
|
loading?: boolean;
|
|
81
83
|
emptyMessage?: string;
|
|
84
|
+
/** Maximum height of the scroll viewport. Defaults to 600px. */
|
|
85
|
+
maxHeight?: number | string;
|
|
86
|
+
/** Estimated row height in pixels; measured rows replace the estimate. Defaults to 37. */
|
|
87
|
+
estimateRowHeight?: number;
|
|
88
|
+
/** Extra rows rendered above and below the visible range. Defaults to 8. */
|
|
89
|
+
overscan?: number;
|
|
82
90
|
/** Tailwind / bespoke styling slots (Mode B). */
|
|
83
91
|
classNames?: TableClassNames;
|
|
84
92
|
}
|
|
@@ -146,9 +154,9 @@ declare function CellMenu<Row>({ field, value, x, y, onAddFilter, onClose, class
|
|
|
146
154
|
|
|
147
155
|
interface SelectionToolbarProps {
|
|
148
156
|
selection: SelectionApi;
|
|
149
|
-
/** Consumer-rendered action buttons. Receives the selected ids
|
|
150
|
-
*
|
|
151
|
-
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;
|
|
152
160
|
/** Hidden when nothing is selected unless `alwaysShow`. */
|
|
153
161
|
alwaysShow?: boolean;
|
|
154
162
|
className?: string;
|
|
@@ -162,4 +170,10 @@ interface SavedQueriesModalProps {
|
|
|
162
170
|
}
|
|
163
171
|
declare function SavedQueriesModal({ saved, onClose, onLoad }: SavedQueriesModalProps): ReactNode;
|
|
164
172
|
|
|
165
|
-
|
|
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 };
|