@charcuterie/ui 2.12.1 → 2.14.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/dist/QueryBuilder/QueryBuilder.d.ts +95 -0
- package/dist/QueryBuilder/QueryBuilder.d.ts.map +1 -0
- package/dist/QueryBuilder/QueryBuilder.js +38 -0
- package/dist/QueryBuilder/QueryBuilder.js.map +1 -0
- package/dist/QueryBuilder/QueryBuilderCombinator.d.ts +53 -0
- package/dist/QueryBuilder/QueryBuilderCombinator.d.ts.map +1 -0
- package/dist/QueryBuilder/QueryBuilderCombinator.js +59 -0
- package/dist/QueryBuilder/QueryBuilderCombinator.js.map +1 -0
- package/dist/QueryBuilder/QueryBuilderGroup.d.ts +42 -0
- package/dist/QueryBuilder/QueryBuilderGroup.d.ts.map +1 -0
- package/dist/QueryBuilder/QueryBuilderGroup.js +51 -0
- package/dist/QueryBuilder/QueryBuilderGroup.js.map +1 -0
- package/dist/QueryBuilder/QueryBuilderRow.d.ts +28 -0
- package/dist/QueryBuilder/QueryBuilderRow.d.ts.map +1 -0
- package/dist/QueryBuilder/QueryBuilderRow.js +16 -0
- package/dist/QueryBuilder/QueryBuilderRow.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/QueryBuilder/QueryBuilder.mdx +70 -0
- package/src/QueryBuilder/QueryBuilder.stories.tsx +429 -0
- package/src/QueryBuilder/QueryBuilder.test.tsx +204 -0
- package/src/QueryBuilder/QueryBuilder.tsx +136 -0
- package/src/QueryBuilder/QueryBuilderCombinator.tsx +108 -0
- package/src/QueryBuilder/QueryBuilderGroup.tsx +189 -0
- package/src/QueryBuilder/QueryBuilderRow.tsx +54 -0
- package/src/index.ts +5 -0
- package/src/sourceRules.test.ts +10 -1
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { Tree } from "@charcuterie/logic";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
export type QueryBuilderLabels = {
|
|
4
|
+
addGroup?: string;
|
|
5
|
+
addLeaf?: string;
|
|
6
|
+
/** The caption over each group's combinator picker. */
|
|
7
|
+
match?: string;
|
|
8
|
+
removeGroup?: string;
|
|
9
|
+
removeLeaf?: string;
|
|
10
|
+
};
|
|
11
|
+
export type QueryBuilderProps<Combinator, Leaf> = {
|
|
12
|
+
/**
|
|
13
|
+
* The combinator choices offered in every group's "Match" select.
|
|
14
|
+
* The `value` is opaque — `and`/`or` for a mail rule, `any`/`all`/
|
|
15
|
+
* `none` for a DSL — and the `label` is what a user reads.
|
|
16
|
+
*/
|
|
17
|
+
combinatorOptions: readonly {
|
|
18
|
+
label: string;
|
|
19
|
+
value: Combinator;
|
|
20
|
+
}[];
|
|
21
|
+
/** The value a fresh leaf is born with when "+ Condition" is pressed. */
|
|
22
|
+
createLeafValue: () => Leaf;
|
|
23
|
+
labels?: QueryBuilderLabels;
|
|
24
|
+
/**
|
|
25
|
+
* The group's combinator control, when one `Listbox` over a flat
|
|
26
|
+
* option list is the wrong shape for it.
|
|
27
|
+
*
|
|
28
|
+
* Optional, and the default is the right answer for most consumers:
|
|
29
|
+
* a combinator that is a plain enum reads as one picker. But a
|
|
30
|
+
* combinator can be a *composite* — mux-magic's is a quantifier
|
|
31
|
+
* (ANY/ALL/NO) crossed with a target (a nested group, a style row,
|
|
32
|
+
* a script-info block), and the legal pairs are asymmetric
|
|
33
|
+
* (`notAllScriptInfo` exists, `notAllStyle` does not). Flattened
|
|
34
|
+
* into one list that is nine options where the user is making two
|
|
35
|
+
* choices, and the illegal pairs are invisible until they are
|
|
36
|
+
* missing.
|
|
37
|
+
*
|
|
38
|
+
* So the combinator is app-ownable for the same reason `renderLeaf`
|
|
39
|
+
* is: `Combinator` is opaque here, and only the app knows whether
|
|
40
|
+
* its shape is an enum or a product. `options` and the current
|
|
41
|
+
* `value` are handed over unchanged; the app calls `onChange` with a
|
|
42
|
+
* real `Combinator`.
|
|
43
|
+
*/
|
|
44
|
+
renderCombinator?: (args: {
|
|
45
|
+
nodeId: string;
|
|
46
|
+
onChange: (combinator: Combinator) => void;
|
|
47
|
+
options: readonly {
|
|
48
|
+
label: string;
|
|
49
|
+
value: Combinator;
|
|
50
|
+
}[];
|
|
51
|
+
value: Combinator;
|
|
52
|
+
}) => ReactNode;
|
|
53
|
+
/**
|
|
54
|
+
* The leaf UI, owned by the app. `QueryBuilder` knows nothing about
|
|
55
|
+
* what a condition *is* — a field/operator/value triple, a
|
|
56
|
+
* non-uniform per-kind shape — only that it can be rendered and
|
|
57
|
+
* patched. The delete control around each leaf is the builder's.
|
|
58
|
+
*/
|
|
59
|
+
renderLeaf: (args: {
|
|
60
|
+
nodeId: string;
|
|
61
|
+
onChange: (value: Leaf) => void;
|
|
62
|
+
value: Leaf;
|
|
63
|
+
}) => ReactNode;
|
|
64
|
+
/**
|
|
65
|
+
* The `Tree` core from `useTree`, owned by the consumer — the same
|
|
66
|
+
* arrangement as a `Listbox`'s parent owning `useVisibility`.
|
|
67
|
+
* `QueryBuilder` subscribes to it and drives it; it never creates
|
|
68
|
+
* one, so a consumer keeps `serialize()` and the initial tree.
|
|
69
|
+
*/
|
|
70
|
+
tree: Tree<Combinator, Leaf>;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* The generic, nestable AND/OR — and any-combinator — group editor.
|
|
74
|
+
*
|
|
75
|
+
* Two apps in the fleet grow the same widget: Mail Sifter's nested
|
|
76
|
+
* mail rules (leaf = field/operator/value, combinators AND/OR) and
|
|
77
|
+
* mux-magic's job DSL (non-uniform leaves, combinators any/all/none).
|
|
78
|
+
* Both are a recursive group of conditions with a combinator, so the
|
|
79
|
+
* value **and** the combinator are opaque here — `Combinator` and
|
|
80
|
+
* `Leaf` never appear except passed through to the consumer's
|
|
81
|
+
* `renderLeaf` and its `combinatorOptions`.
|
|
82
|
+
*
|
|
83
|
+
* State lives entirely in the `Tree` core from `@charcuterie/logic`;
|
|
84
|
+
* this component holds none of its own. It subscribes with
|
|
85
|
+
* `useStoreValue`, so a `patchLeaf` deep in the tree re-renders only
|
|
86
|
+
* the rows whose node identity changed — the same identity discipline
|
|
87
|
+
* the state layer is built on.
|
|
88
|
+
*
|
|
89
|
+
* The recursion and the per-leaf row each live in their own file
|
|
90
|
+
* (`QueryBuilderGroup`, `QueryBuilderRow`), not exported: a group
|
|
91
|
+
* renders groups, and both are rendered inside a `.map`, which is
|
|
92
|
+
* exactly the shape the member-file rule is for.
|
|
93
|
+
*/
|
|
94
|
+
export declare const QueryBuilder: <Combinator, Leaf>({ combinatorOptions, createLeafValue, labels, renderCombinator, renderLeaf, tree, }: QueryBuilderProps<Combinator, Leaf>) => ReactNode;
|
|
95
|
+
//# sourceMappingURL=QueryBuilder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryBuilder.d.ts","sourceRoot":"","sources":["../../src/QueryBuilder/QueryBuilder.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAA;AAK9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAItC,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,iBAAiB,CAAC,UAAU,EAAE,IAAI,IAAI;IAChD;;;;OAIG;IACH,iBAAiB,EAAE,SAAS;QAC1B,KAAK,EAAE,MAAM,CAAA;QACb,KAAK,EAAE,UAAU,CAAA;KAClB,EAAE,CAAA;IACH,yEAAyE;IACzE,eAAe,EAAE,MAAM,IAAI,CAAA;IAC3B,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAC3B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE;QACxB,MAAM,EAAE,MAAM,CAAA;QACd,QAAQ,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAA;QAC1C,OAAO,EAAE,SAAS;YAChB,KAAK,EAAE,MAAM,CAAA;YACb,KAAK,EAAE,UAAU,CAAA;SAClB,EAAE,CAAA;QACH,KAAK,EAAE,UAAU,CAAA;KAClB,KAAK,SAAS,CAAA;IACf;;;;;OAKG;IACH,UAAU,EAAE,CAAC,IAAI,EAAE;QACjB,MAAM,EAAE,MAAM,CAAA;QACd,QAAQ,EAAE,CAAC,KAAK,EAAE,IAAI,KAAK,IAAI,CAAA;QAC/B,KAAK,EAAE,IAAI,CAAA;KACZ,KAAK,SAAS,CAAA;IACf;;;;;OAKG;IACH,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;CAC7B,CAAA;AAUD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,YAAY,GAAI,UAAU,EAAE,IAAI,EAAE,qFAO5C,iBAAiB,CAAC,UAAU,EAAE,IAAI,CAAC,KAAG,SAkBxC,CAAA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { selectRootGroup, useStoreValue, } from "@charcuterie/logic";
|
|
3
|
+
import { QueryBuilderGroup } from "./QueryBuilderGroup.js";
|
|
4
|
+
const DEFAULT_LABELS = {
|
|
5
|
+
addGroup: "Add group",
|
|
6
|
+
addLeaf: "Add condition",
|
|
7
|
+
match: "Match",
|
|
8
|
+
removeGroup: "Remove group",
|
|
9
|
+
removeLeaf: "Remove condition",
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* The generic, nestable AND/OR — and any-combinator — group editor.
|
|
13
|
+
*
|
|
14
|
+
* Two apps in the fleet grow the same widget: Mail Sifter's nested
|
|
15
|
+
* mail rules (leaf = field/operator/value, combinators AND/OR) and
|
|
16
|
+
* mux-magic's job DSL (non-uniform leaves, combinators any/all/none).
|
|
17
|
+
* Both are a recursive group of conditions with a combinator, so the
|
|
18
|
+
* value **and** the combinator are opaque here — `Combinator` and
|
|
19
|
+
* `Leaf` never appear except passed through to the consumer's
|
|
20
|
+
* `renderLeaf` and its `combinatorOptions`.
|
|
21
|
+
*
|
|
22
|
+
* State lives entirely in the `Tree` core from `@charcuterie/logic`;
|
|
23
|
+
* this component holds none of its own. It subscribes with
|
|
24
|
+
* `useStoreValue`, so a `patchLeaf` deep in the tree re-renders only
|
|
25
|
+
* the rows whose node identity changed — the same identity discipline
|
|
26
|
+
* the state layer is built on.
|
|
27
|
+
*
|
|
28
|
+
* The recursion and the per-leaf row each live in their own file
|
|
29
|
+
* (`QueryBuilderGroup`, `QueryBuilderRow`), not exported: a group
|
|
30
|
+
* renders groups, and both are rendered inside a `.map`, which is
|
|
31
|
+
* exactly the shape the member-file rule is for.
|
|
32
|
+
*/
|
|
33
|
+
export const QueryBuilder = ({ combinatorOptions, createLeafValue, labels, renderCombinator, renderLeaf, tree, }) => {
|
|
34
|
+
const state = useStoreValue(tree);
|
|
35
|
+
const resolvedLabels = { ...DEFAULT_LABELS, ...labels };
|
|
36
|
+
return (_jsx(QueryBuilderGroup, { combinatorOptions: combinatorOptions, createLeafValue: createLeafValue, depth: 0, labels: resolvedLabels, node: selectRootGroup(state), renderCombinator: renderCombinator, renderLeaf: renderLeaf, state: state, tree: tree }));
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=QueryBuilder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryBuilder.js","sourceRoot":"","sources":["../../src/QueryBuilder/QueryBuilder.tsx"],"names":[],"mappings":";AACA,OAAO,EACL,eAAe,EACf,aAAa,GACd,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAyB,CAAA;AAyE3D,MAAM,cAAc,GAAG;IACrB,QAAQ,EAAE,WAAW;IACrB,OAAO,EAAE,eAAe;IACxB,KAAK,EAAE,OAAO;IACd,WAAW,EAAE,cAAc;IAC3B,UAAU,EAAE,kBAAkB;CACQ,CAAA;AAExC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAmB,EAC7C,iBAAiB,EACjB,eAAe,EACf,MAAM,EACN,gBAAgB,EAChB,UAAU,EACV,IAAI,GACgC,EAAa,EAAE;IACnD,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,CAAA;IAEjC,MAAM,cAAc,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,MAAM,EAAE,CAAA;IAEvD,OAAO,CACL,KAAC,iBAAiB,IAChB,iBAAiB,EAAE,iBAAiB,EACpC,eAAe,EAAE,eAAe,EAChC,KAAK,EAAE,CAAC,EACR,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,eAAe,CAAC,KAAK,CAAC,EAC5B,gBAAgB,EAAE,gBAAgB,EAClC,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,IAAI,GACV,CACH,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export type QueryBuilderCombinatorProps<Combinator> = {
|
|
3
|
+
/** The visible caption above the control, e.g. "Match". */
|
|
4
|
+
label: string;
|
|
5
|
+
onChange: (combinator: Combinator) => void;
|
|
6
|
+
options: readonly {
|
|
7
|
+
label: string;
|
|
8
|
+
value: Combinator;
|
|
9
|
+
}[];
|
|
10
|
+
value: Combinator;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* One group's combinator picker.
|
|
14
|
+
*
|
|
15
|
+
* A `Listbox`, not a native `Select`, per
|
|
16
|
+
* [the 2026-08-10 demotion](../../../../docs/decisions/2026-08-10-listbox-and-combobox-are-the-default-and-select-is-demoted.md).
|
|
17
|
+
* `QueryBuilder` shipped in #84 with a `Select` the day after that
|
|
18
|
+
* record landed; `charcuterie/prefer-listbox-over-select` did not
|
|
19
|
+
* catch it because the component-choice block is scoped to app
|
|
20
|
+
* packages and exempts this one — right for a primitive, wrong for a
|
|
21
|
+
* composite an app consumes whole.
|
|
22
|
+
*
|
|
23
|
+
* ### Why this is its own file
|
|
24
|
+
*
|
|
25
|
+
* `Listbox` needs a visibility state, and a group renders one picker
|
|
26
|
+
* per group inside a recursive `.map`. A hook cannot be called there,
|
|
27
|
+
* so the picker becomes a component — the same member-file case as
|
|
28
|
+
* `QueryBuilderRow`.
|
|
29
|
+
*
|
|
30
|
+
* ### The name, and why it is not a `Field`
|
|
31
|
+
*
|
|
32
|
+
* `Field` wires `<label htmlFor>` by cloning its `id` onto the
|
|
33
|
+
* control. `Listbox`'s trigger cannot take one: `useAnchoredOverlay`
|
|
34
|
+
* overwrites the cloned trigger's `id` with the one the panel points
|
|
35
|
+
* `aria-labelledby` at, so the label would address an element that no
|
|
36
|
+
* longer carries that id — the exact defect `Field` exists to
|
|
37
|
+
* prevent. So the caption is plain text and the trigger is named with
|
|
38
|
+
* `aria-label`.
|
|
39
|
+
*
|
|
40
|
+
* That name is `"<label>: <current value>"` rather than bare
|
|
41
|
+
* `"<label>"` on purpose: the button's visible text is the current
|
|
42
|
+
* combinator, and WCAG 2.5.3 wants the visible text contained in the
|
|
43
|
+
* accessible name. "Match" alone would fail it; "Match: ALL — every
|
|
44
|
+
* condition" reads correctly and keeps each group's control findable
|
|
45
|
+
* by name.
|
|
46
|
+
*
|
|
47
|
+
* The combinator stays opaque here exactly as it is in the rest of
|
|
48
|
+
* the component: `String(value)` bridges it to the string-valued
|
|
49
|
+
* `Listbox`, and a selection is mapped back to the real `Combinator`
|
|
50
|
+
* before it leaves.
|
|
51
|
+
*/
|
|
52
|
+
export declare const QueryBuilderCombinator: <Combinator>({ label, onChange, options, value, }: QueryBuilderCombinatorProps<Combinator>) => ReactNode;
|
|
53
|
+
//# sourceMappingURL=QueryBuilderCombinator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryBuilderCombinator.d.ts","sourceRoot":"","sources":["../../src/QueryBuilder/QueryBuilderCombinator.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAKtC,MAAM,MAAM,2BAA2B,CAAC,UAAU,IAAI;IACpD,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAA;IAC1C,OAAO,EAAE,SAAS;QAChB,KAAK,EAAE,MAAM,CAAA;QACb,KAAK,EAAE,UAAU,CAAA;KAClB,EAAE,CAAA;IACH,KAAK,EAAE,UAAU,CAAA;CAClB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,eAAO,MAAM,sBAAsB,GAAI,UAAU,EAAG,sCAKjD,2BAA2B,CAAC,UAAU,CAAC,KAAG,SA6C5C,CAAA"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useVisibility } from "@charcuterie/logic";
|
|
3
|
+
import { Button } from "../Button/Button.js";
|
|
4
|
+
import { Listbox } from "../Listbox/Listbox.js";
|
|
5
|
+
/**
|
|
6
|
+
* One group's combinator picker.
|
|
7
|
+
*
|
|
8
|
+
* A `Listbox`, not a native `Select`, per
|
|
9
|
+
* [the 2026-08-10 demotion](../../../../docs/decisions/2026-08-10-listbox-and-combobox-are-the-default-and-select-is-demoted.md).
|
|
10
|
+
* `QueryBuilder` shipped in #84 with a `Select` the day after that
|
|
11
|
+
* record landed; `charcuterie/prefer-listbox-over-select` did not
|
|
12
|
+
* catch it because the component-choice block is scoped to app
|
|
13
|
+
* packages and exempts this one — right for a primitive, wrong for a
|
|
14
|
+
* composite an app consumes whole.
|
|
15
|
+
*
|
|
16
|
+
* ### Why this is its own file
|
|
17
|
+
*
|
|
18
|
+
* `Listbox` needs a visibility state, and a group renders one picker
|
|
19
|
+
* per group inside a recursive `.map`. A hook cannot be called there,
|
|
20
|
+
* so the picker becomes a component — the same member-file case as
|
|
21
|
+
* `QueryBuilderRow`.
|
|
22
|
+
*
|
|
23
|
+
* ### The name, and why it is not a `Field`
|
|
24
|
+
*
|
|
25
|
+
* `Field` wires `<label htmlFor>` by cloning its `id` onto the
|
|
26
|
+
* control. `Listbox`'s trigger cannot take one: `useAnchoredOverlay`
|
|
27
|
+
* overwrites the cloned trigger's `id` with the one the panel points
|
|
28
|
+
* `aria-labelledby` at, so the label would address an element that no
|
|
29
|
+
* longer carries that id — the exact defect `Field` exists to
|
|
30
|
+
* prevent. So the caption is plain text and the trigger is named with
|
|
31
|
+
* `aria-label`.
|
|
32
|
+
*
|
|
33
|
+
* That name is `"<label>: <current value>"` rather than bare
|
|
34
|
+
* `"<label>"` on purpose: the button's visible text is the current
|
|
35
|
+
* combinator, and WCAG 2.5.3 wants the visible text contained in the
|
|
36
|
+
* accessible name. "Match" alone would fail it; "Match: ALL — every
|
|
37
|
+
* condition" reads correctly and keeps each group's control findable
|
|
38
|
+
* by name.
|
|
39
|
+
*
|
|
40
|
+
* The combinator stays opaque here exactly as it is in the rest of
|
|
41
|
+
* the component: `String(value)` bridges it to the string-valued
|
|
42
|
+
* `Listbox`, and a selection is mapped back to the real `Combinator`
|
|
43
|
+
* before it leaves.
|
|
44
|
+
*/
|
|
45
|
+
export const QueryBuilderCombinator = ({ label, onChange, options, value, }) => {
|
|
46
|
+
const { hide, isVisible, toggle } = useVisibility();
|
|
47
|
+
const currentOption = options.find((option) => String(option.value) === String(value));
|
|
48
|
+
const currentLabel = currentOption?.label ?? "";
|
|
49
|
+
return (_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx("span", { className: "font-medium text-content-primary text-sm", children: label }), _jsx(Listbox, { isVisible: isVisible, onDismiss: hide, onSelect: (nextValue) => {
|
|
50
|
+
const match = options.find((option) => String(option.value) === nextValue);
|
|
51
|
+
if (match) {
|
|
52
|
+
onChange(match.value);
|
|
53
|
+
}
|
|
54
|
+
}, options: options.map((option) => ({
|
|
55
|
+
label: option.label,
|
|
56
|
+
value: String(option.value),
|
|
57
|
+
})), selectedValue: String(value), trigger: _jsx(Button, { appearance: "outline", "aria-label": `${label}: ${currentLabel}`, intent: "neutral", onClick: toggle, children: currentLabel }) })] }));
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=QueryBuilderCombinator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryBuilderCombinator.js","sourceRoot":"","sources":["../../src/QueryBuilder/QueryBuilderCombinator.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAGlD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAsB,CAAA;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAwB,CAAA;AAahD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAc,EAClD,KAAK,EACL,QAAQ,EACR,OAAO,EACP,KAAK,GACmC,EAAa,EAAE;IACvD,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,CAAA;IAEnD,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAChC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,KAAK,CAAC,CACnD,CAAA;IAED,MAAM,YAAY,GAAG,aAAa,EAAE,KAAK,IAAI,EAAE,CAAA;IAE/C,OAAO,CACL,eAAK,SAAS,EAAC,uBAAuB,aACpC,eAAM,SAAS,EAAC,0CAA0C,YACvD,KAAK,GACD,EAEP,KAAC,OAAO,IACN,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,IAAI,EACf,QAAQ,EAAE,CAAC,SAAS,EAAE,EAAE;oBACtB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CACxB,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,SAAS,CAC/C,CAAA;oBAED,IAAI,KAAK,EAAE,CAAC;wBACV,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;oBACvB,CAAC;gBACH,CAAC,EACD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;oBAChC,KAAK,EAAE,MAAM,CAAC,KAAK;oBACnB,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;iBAC5B,CAAC,CAAC,EACH,aAAa,EAAE,MAAM,CAAC,KAAK,CAAC,EAC5B,OAAO,EACL,KAAC,MAAM,IACL,UAAU,EAAC,SAAS,gBACR,GAAG,KAAK,KAAK,YAAY,EAAE,EACvC,MAAM,EAAC,SAAS,EAChB,OAAO,EAAE,MAAM,YAEd,YAAY,GACN,GAEX,IACE,CACP,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Tree, TreeGroupNode, TreeState } from "@charcuterie/logic";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
import type { QueryBuilderLabels } from "./QueryBuilder.tsx";
|
|
4
|
+
export type QueryBuilderGroupProps<Combinator, Leaf> = {
|
|
5
|
+
combinatorOptions: readonly {
|
|
6
|
+
label: string;
|
|
7
|
+
value: Combinator;
|
|
8
|
+
}[];
|
|
9
|
+
createLeafValue: () => Leaf;
|
|
10
|
+
/** Root is `0`; nested groups deepen and gain the accent rail. */
|
|
11
|
+
depth: number;
|
|
12
|
+
labels: Required<QueryBuilderLabels>;
|
|
13
|
+
node: TreeGroupNode<Combinator>;
|
|
14
|
+
renderCombinator?: (args: {
|
|
15
|
+
nodeId: string;
|
|
16
|
+
onChange: (combinator: Combinator) => void;
|
|
17
|
+
options: readonly {
|
|
18
|
+
label: string;
|
|
19
|
+
value: Combinator;
|
|
20
|
+
}[];
|
|
21
|
+
value: Combinator;
|
|
22
|
+
}) => ReactNode;
|
|
23
|
+
renderLeaf: (args: {
|
|
24
|
+
nodeId: string;
|
|
25
|
+
onChange: (value: Leaf) => void;
|
|
26
|
+
value: Leaf;
|
|
27
|
+
}) => ReactNode;
|
|
28
|
+
state: TreeState<Combinator, Leaf>;
|
|
29
|
+
tree: Tree<Combinator, Leaf>;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* One match group: a "Match" combinator picker, its children (leaf
|
|
33
|
+
* rows and nested groups), and a toolbar to add either. Its own file
|
|
34
|
+
* because it renders itself recursively for nested groups and is
|
|
35
|
+
* itself rendered inside the parent's `.map` — the member-file case.
|
|
36
|
+
*
|
|
37
|
+
* The picker is `QueryBuilderCombinator`, a `Listbox` rather than the
|
|
38
|
+
* native `Select` this shipped with — see that file for why it is a
|
|
39
|
+
* component and how it stays generic over an opaque `Combinator`.
|
|
40
|
+
*/
|
|
41
|
+
export declare const QueryBuilderGroup: <Combinator, Leaf>({ combinatorOptions, createLeafValue, depth, labels, node, renderCombinator, renderLeaf, state, tree, }: QueryBuilderGroupProps<Combinator, Leaf>) => ReactNode;
|
|
42
|
+
//# sourceMappingURL=QueryBuilderGroup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryBuilderGroup.d.ts","sourceRoot":"","sources":["../../src/QueryBuilder/QueryBuilderGroup.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,IAAI,EACJ,aAAa,EACb,SAAS,EACV,MAAM,oBAAoB,CAAA;AAE3B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAMtC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAI5D,MAAM,MAAM,sBAAsB,CAAC,UAAU,EAAE,IAAI,IAAI;IACrD,iBAAiB,EAAE,SAAS;QAC1B,KAAK,EAAE,MAAM,CAAA;QACb,KAAK,EAAE,UAAU,CAAA;KAClB,EAAE,CAAA;IACH,eAAe,EAAE,MAAM,IAAI,CAAA;IAC3B,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,QAAQ,CAAC,kBAAkB,CAAC,CAAA;IACpC,IAAI,EAAE,aAAa,CAAC,UAAU,CAAC,CAAA;IAC/B,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE;QACxB,MAAM,EAAE,MAAM,CAAA;QACd,QAAQ,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAA;QAC1C,OAAO,EAAE,SAAS;YAChB,KAAK,EAAE,MAAM,CAAA;YACb,KAAK,EAAE,UAAU,CAAA;SAClB,EAAE,CAAA;QACH,KAAK,EAAE,UAAU,CAAA;KAClB,KAAK,SAAS,CAAA;IACf,UAAU,EAAE,CAAC,IAAI,EAAE;QACjB,MAAM,EAAE,MAAM,CAAA;QACd,QAAQ,EAAE,CAAC,KAAK,EAAE,IAAI,KAAK,IAAI,CAAA;QAC/B,KAAK,EAAE,IAAI,CAAA;KACZ,KAAK,SAAS,CAAA;IACf,KAAK,EAAE,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;IAClC,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;CAC7B,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAAI,UAAU,EAAE,IAAI,EAAE,yGAUjD,sBAAsB,CAAC,UAAU,EAAE,IAAI,CAAC,KAAG,SA4H7C,CAAA"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { selectChildNodes } from "@charcuterie/logic";
|
|
3
|
+
import { Button } from "../Button/Button.js";
|
|
4
|
+
import { Card } from "../Card/Card.js";
|
|
5
|
+
import { IconButton } from "../IconButton/IconButton.js";
|
|
6
|
+
import { toClassName } from "../toClassName.js";
|
|
7
|
+
import { QueryBuilderCombinator } from "./QueryBuilderCombinator.js";
|
|
8
|
+
import { QueryBuilderRow } from "./QueryBuilderRow.js";
|
|
9
|
+
/**
|
|
10
|
+
* One match group: a "Match" combinator picker, its children (leaf
|
|
11
|
+
* rows and nested groups), and a toolbar to add either. Its own file
|
|
12
|
+
* because it renders itself recursively for nested groups and is
|
|
13
|
+
* itself rendered inside the parent's `.map` — the member-file case.
|
|
14
|
+
*
|
|
15
|
+
* The picker is `QueryBuilderCombinator`, a `Listbox` rather than the
|
|
16
|
+
* native `Select` this shipped with — see that file for why it is a
|
|
17
|
+
* component and how it stays generic over an opaque `Combinator`.
|
|
18
|
+
*/
|
|
19
|
+
export const QueryBuilderGroup = ({ combinatorOptions, createLeafValue, depth, labels, node, renderCombinator, renderLeaf, state, tree, }) => {
|
|
20
|
+
const children = selectChildNodes(state, node.id);
|
|
21
|
+
const setCombinator = (nextCombinator) => {
|
|
22
|
+
tree.setCombinator(node.id, nextCombinator);
|
|
23
|
+
};
|
|
24
|
+
const card = (_jsx(Card
|
|
25
|
+
// Nested groups sit on the sunken surface so the depth reads as
|
|
26
|
+
// recession, not another raised card floating at the same level.
|
|
27
|
+
, {
|
|
28
|
+
// Nested groups sit on the sunken surface so the depth reads as
|
|
29
|
+
// recession, not another raised card floating at the same level.
|
|
30
|
+
surface: depth === 0 ? "raised" : "sunken", children: _jsxs("div", { className: "flex flex-col gap-3", children: [_jsxs("div", { className: "flex items-start justify-between gap-2", children: [_jsx("div", { className: "min-w-52", children: renderCombinator ? (renderCombinator({
|
|
31
|
+
nodeId: node.id,
|
|
32
|
+
onChange: setCombinator,
|
|
33
|
+
options: combinatorOptions,
|
|
34
|
+
value: node.combinator,
|
|
35
|
+
})) : (_jsx(QueryBuilderCombinator, { label: labels.match, onChange: setCombinator, options: combinatorOptions, value: node.combinator })) }), depth === 0 ? null : (_jsx(IconButton, { appearance: "ghost", intent: "danger", label: labels.removeGroup, onClick: () => {
|
|
36
|
+
tree.removeNode(node.id);
|
|
37
|
+
}, size: "sm", children: "\u2715" }))] }), children.length === 0 ? null : (_jsx("div", { className: "flex flex-col gap-2", children: children.map((child) => child.kind === "group" ? (_jsx(QueryBuilderGroup, { combinatorOptions: combinatorOptions, createLeafValue: createLeafValue, depth: depth + 1, labels: labels, node: child, renderCombinator: renderCombinator, renderLeaf: renderLeaf, state: state, tree: tree }, child.id)) : (_jsx(QueryBuilderRow, { label: labels.removeLeaf, nodeId: child.id, onChange: (value) => {
|
|
38
|
+
tree.patchLeaf(child.id, value);
|
|
39
|
+
}, onRemove: () => {
|
|
40
|
+
tree.removeNode(child.id);
|
|
41
|
+
}, renderLeaf: renderLeaf, value: child.value }, child.id))) })), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Button, { appearance: "outline", intent: "neutral", onClick: () => {
|
|
42
|
+
tree.addLeaf(node.id, createLeafValue());
|
|
43
|
+
}, size: "sm", children: `+ ${labels.addLeaf}` }), _jsx(Button, { appearance: "outline", intent: "neutral", onClick: () => {
|
|
44
|
+
tree.addGroup(node.id);
|
|
45
|
+
}, size: "sm", children: `+ ${labels.addGroup}` })] })] }) }));
|
|
46
|
+
// Depth is shown with a semantic-token inline-start rail. The colour
|
|
47
|
+
// utility paints all four sides, but only the inline-start edge has
|
|
48
|
+
// a width, so only it renders — no raw palette colour anywhere.
|
|
49
|
+
return depth === 0 ? (card) : (_jsx("div", { className: toClassName("border-intent-accent-border border-s-2 ps-3"), children: card }));
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=QueryBuilderGroup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryBuilderGroup.js","sourceRoot":"","sources":["../../src/QueryBuilder/QueryBuilderGroup.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export type QueryBuilderRowProps<Leaf> = {
|
|
3
|
+
/** The accessible name of the row's delete control. */
|
|
4
|
+
label: string;
|
|
5
|
+
nodeId: string;
|
|
6
|
+
onChange: (value: Leaf) => void;
|
|
7
|
+
onRemove: () => void;
|
|
8
|
+
renderLeaf: (args: {
|
|
9
|
+
nodeId: string;
|
|
10
|
+
onChange: (value: Leaf) => void;
|
|
11
|
+
value: Leaf;
|
|
12
|
+
}) => ReactNode;
|
|
13
|
+
value: Leaf;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* A single leaf row: the app's own leaf UI, plus the builder's delete
|
|
17
|
+
* control. Its own file for the same reason `ListboxOption` is —
|
|
18
|
+
* rendered inside the group's `.map`, so it cannot be an inline
|
|
19
|
+
* component — and it is a member file (`QueryBuilder*.tsx`, not
|
|
20
|
+
* `QueryBuilder/QueryBuilder.tsx`), so it stays out of the barrel and
|
|
21
|
+
* the component count by rule.
|
|
22
|
+
*
|
|
23
|
+
* The delete control is an `IconButton` because a bare glyph is not an
|
|
24
|
+
* accessible name; its required `label` is what makes each row's
|
|
25
|
+
* remove button findable and unique per condition.
|
|
26
|
+
*/
|
|
27
|
+
export declare const QueryBuilderRow: <Leaf>({ label, nodeId, onChange, onRemove, renderLeaf, value, }: QueryBuilderRowProps<Leaf>) => ReactNode;
|
|
28
|
+
//# sourceMappingURL=QueryBuilderRow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryBuilderRow.d.ts","sourceRoot":"","sources":["../../src/QueryBuilder/QueryBuilderRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAItC,MAAM,MAAM,oBAAoB,CAAC,IAAI,IAAI;IACvC,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,IAAI,KAAK,IAAI,CAAA;IAC/B,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,UAAU,EAAE,CAAC,IAAI,EAAE;QACjB,MAAM,EAAE,MAAM,CAAA;QACd,QAAQ,EAAE,CAAC,KAAK,EAAE,IAAI,KAAK,IAAI,CAAA;QAC/B,KAAK,EAAE,IAAI,CAAA;KACZ,KAAK,SAAS,CAAA;IACf,KAAK,EAAE,IAAI,CAAA;CACZ,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,eAAe,GAAI,IAAI,EAAG,2DAOpC,oBAAoB,CAAC,IAAI,CAAC,KAAG,SAgB/B,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { IconButton } from "../IconButton/IconButton.js";
|
|
3
|
+
/**
|
|
4
|
+
* A single leaf row: the app's own leaf UI, plus the builder's delete
|
|
5
|
+
* control. Its own file for the same reason `ListboxOption` is —
|
|
6
|
+
* rendered inside the group's `.map`, so it cannot be an inline
|
|
7
|
+
* component — and it is a member file (`QueryBuilder*.tsx`, not
|
|
8
|
+
* `QueryBuilder/QueryBuilder.tsx`), so it stays out of the barrel and
|
|
9
|
+
* the component count by rule.
|
|
10
|
+
*
|
|
11
|
+
* The delete control is an `IconButton` because a bare glyph is not an
|
|
12
|
+
* accessible name; its required `label` is what makes each row's
|
|
13
|
+
* remove button findable and unique per condition.
|
|
14
|
+
*/
|
|
15
|
+
export const QueryBuilderRow = ({ label, nodeId, onChange, onRemove, renderLeaf, value, }) => (_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("div", { className: "grow", children: renderLeaf({ nodeId, onChange, value }) }), _jsx(IconButton, { appearance: "ghost", intent: "danger", label: label, onClick: onRemove, size: "sm", children: "\u2715" })] }));
|
|
16
|
+
//# sourceMappingURL=QueryBuilderRow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryBuilderRow.js","sourceRoot":"","sources":["../../src/QueryBuilder/QueryBuilderRow.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA8B,CAAA;AAgBzD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAQ,EACrC,KAAK,EACL,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,KAAK,GACsB,EAAa,EAAE,CAAC,CAC3C,eAAK,SAAS,EAAC,wBAAwB,aACrC,cAAK,SAAS,EAAC,MAAM,YAClB,UAAU,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,GACpC,EAEN,KAAC,UAAU,IACT,UAAU,EAAC,OAAO,EAClB,MAAM,EAAC,QAAQ,EACf,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,QAAQ,EACjB,IAAI,EAAC,IAAI,uBAGE,IACT,CACP,CAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -98,6 +98,8 @@ export type { ProgressBarProps, ProgressBarSize, } from "./ProgressBar/ProgressB
|
|
|
98
98
|
export { ProgressBar } from "./ProgressBar/ProgressBar.tsx";
|
|
99
99
|
export type { ProgressThreshold } from "./ProgressBar/progressValue.ts";
|
|
100
100
|
export { getProgressIntent, toProgressPercent, toProgressValue, } from "./ProgressBar/progressValue.ts";
|
|
101
|
+
export type { QueryBuilderLabels, QueryBuilderProps, } from "./QueryBuilder/QueryBuilder.tsx";
|
|
102
|
+
export { QueryBuilder } from "./QueryBuilder/QueryBuilder.tsx";
|
|
101
103
|
export type { RadioGroupProps, RadioItem, } from "./RadioGroup/RadioGroup.tsx";
|
|
102
104
|
export { RadioGroup } from "./RadioGroup/RadioGroup.tsx";
|
|
103
105
|
export type { RailLandmark, RailProps, RailSide, } from "./Rail/Rail.tsx";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -64,6 +64,7 @@ export { Modal } from "./Modal/Modal.js";
|
|
|
64
64
|
export { Popover } from "./Popover/Popover.js";
|
|
65
65
|
export { ProgressBar } from "./ProgressBar/ProgressBar.js";
|
|
66
66
|
export { getProgressIntent, toProgressPercent, toProgressValue, } from "./ProgressBar/progressValue.js";
|
|
67
|
+
export { QueryBuilder } from "./QueryBuilder/QueryBuilder.js";
|
|
67
68
|
export { RadioGroup } from "./RadioGroup/RadioGroup.js";
|
|
68
69
|
export { Rail } from "./Rail/Rail.js";
|
|
69
70
|
export { AnchorLink } from "./RouterLink/AnchorLink.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@charcuterie/ui",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.14.0",
|
|
4
4
|
"description": "The Charcuterie components. Tokens for look, @charcuterie/logic for state, ARIA that agents can actually drive.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"typecheck": "tsc --noEmit"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@charcuterie/logic": "1.
|
|
51
|
+
"@charcuterie/logic": "1.5.0",
|
|
52
52
|
"@charcuterie/tokens": "1.5.0",
|
|
53
53
|
"@floating-ui/react": "^0.27.20",
|
|
54
54
|
"@tanstack/react-virtual": "^3.13.12"
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Canvas, Controls, Meta } from "@storybook/addon-docs/blocks";
|
|
2
|
+
|
|
3
|
+
import * as QueryBuilderStories from "./QueryBuilder.stories";
|
|
4
|
+
|
|
5
|
+
<Meta of={QueryBuilderStories} />
|
|
6
|
+
|
|
7
|
+
# QueryBuilder
|
|
8
|
+
|
|
9
|
+
The generic, nestable **AND/OR — and any-combinator — group editor**. A recursive group of
|
|
10
|
+
conditions, each group carrying a combinator the app owns and each leaf carrying a value the
|
|
11
|
+
app owns. Two apps in the fleet grow the same widget from opposite ends: Mail Sifter's nested
|
|
12
|
+
mail rules (leaf = field/operator/value, combinators AND/OR) and mux-magic's job DSL
|
|
13
|
+
(non-uniform leaves, combinators any/all/none). So both the **leaf value** and the **group
|
|
14
|
+
combinator** are fully opaque here — `Combinator` and `Leaf` only ever pass through to the
|
|
15
|
+
consumer's `renderLeaf` and `combinatorOptions`.
|
|
16
|
+
|
|
17
|
+
<Canvas of={QueryBuilderStories.Default} />
|
|
18
|
+
|
|
19
|
+
## Props
|
|
20
|
+
|
|
21
|
+
<Controls />
|
|
22
|
+
|
|
23
|
+
## The state is a `Tree`, and the consumer owns it
|
|
24
|
+
|
|
25
|
+
`QueryBuilder` holds no state of its own. It takes a `Tree` core from
|
|
26
|
+
[`useTree`](?path=/docs/state-usetree--docs) and subscribes to it, the same way a `Listbox`'s
|
|
27
|
+
parent owns `useVisibility` and hands it down. That is what leaves `serialize()` — the
|
|
28
|
+
YAML/DB round-trip — and the initial tree in the consumer's hands.
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
const tree = useTree<Combinator, Leaf>({
|
|
32
|
+
defaultCombinator: "and",
|
|
33
|
+
initialTree,
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
<QueryBuilder
|
|
37
|
+
combinatorOptions={COMBINATOR_OPTIONS}
|
|
38
|
+
createLeafValue={() => ({ field: "subject", operator: "contains", value: "" })}
|
|
39
|
+
renderLeaf={({ value, onChange }) => <ConditionFields value={value} onChange={onChange} />}
|
|
40
|
+
tree={tree}
|
|
41
|
+
/>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Because the tree is normalized and addressed by id, a `patchLeaf` deep in the tree re-renders
|
|
45
|
+
only the rows whose node identity changed — the same `useSyncExternalStore` identity
|
|
46
|
+
discipline the whole state layer rests on.
|
|
47
|
+
|
|
48
|
+
## Nesting, and depth
|
|
49
|
+
|
|
50
|
+
A group renders leaf rows and nested groups, recursively. The nested group wears a
|
|
51
|
+
semantic-token inline-start rail so depth reads without a raw palette colour, and it moves to
|
|
52
|
+
the sunken surface so it recedes rather than floating at the same level as its parent.
|
|
53
|
+
|
|
54
|
+
<Canvas of={QueryBuilderStories.AllStates} />
|
|
55
|
+
|
|
56
|
+
## Driving it
|
|
57
|
+
|
|
58
|
+
Every control is nameable, not a `data-testid`: the combinator picker is a `Listbox` whose
|
|
59
|
+
trigger is named `Match: <current combinator>`, the leaf controls by their own labels, and each
|
|
60
|
+
delete is an `IconButton` whose required `label` makes it findable. Add a condition, nest a
|
|
61
|
+
group, flip a combinator, delete a row — all reachable by role and name.
|
|
62
|
+
|
|
63
|
+
The picker is a `Listbox` rather than a native `Select`, per
|
|
64
|
+
[the 2026-08-10 demotion](../../../../docs/decisions/2026-08-10-listbox-and-combobox-are-the-default-and-select-is-demoted.md).
|
|
65
|
+
Its name carries the current value because the trigger's visible text *is* that value, and
|
|
66
|
+
WCAG 2.5.3 wants the visible text contained in the accessible name — so query it with
|
|
67
|
+
`getByRole("button", { name: /^Match: / })`, not by the bare caption. Rename the caption with
|
|
68
|
+
`labels.match`.
|
|
69
|
+
|
|
70
|
+
<Canvas of={QueryBuilderStories.Interactive} />
|