@es-joy/jsoe 0.28.2 → 0.29.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/CHANGES.md +19 -0
- package/README.md +2 -0
- package/dist/formatAndTypeChoices.d.ts +6 -6
- package/dist/formatAndTypeChoices.d.ts.map +1 -1
- package/dist/formats/schema.d.ts +5 -0
- package/dist/formats/schema.d.ts.map +1 -1
- package/dist/formats.d.ts +2 -2
- package/dist/formats.d.ts.map +1 -1
- package/dist/fundamentalTypes/dateType.d.ts +21 -2
- package/dist/fundamentalTypes/dateType.d.ts.map +1 -1
- package/dist/fundamentalTypes/domexceptionType.d.ts +7 -0
- package/dist/fundamentalTypes/domexceptionType.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/jtltExtensions.d.ts +112 -0
- package/dist/jtltExtensions.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/arraySearchType.d.ts +15 -0
- package/dist/search/fundamentalTypes/arraySearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/bigintSearchType.d.ts +10 -0
- package/dist/search/fundamentalTypes/bigintSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/blobSearchType.d.ts +19 -0
- package/dist/search/fundamentalTypes/blobSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/booleanSearchType.d.ts +11 -0
- package/dist/search/fundamentalTypes/booleanSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/catchSearchType.d.ts +18 -0
- package/dist/search/fundamentalTypes/catchSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/dateSearchType.d.ts +10 -0
- package/dist/search/fundamentalTypes/dateSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/domexceptionSearchType.d.ts +16 -0
- package/dist/search/fundamentalTypes/domexceptionSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/enumSearchType.d.ts +22 -0
- package/dist/search/fundamentalTypes/enumSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/errorSearchType.d.ts +9 -0
- package/dist/search/fundamentalTypes/errorSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/fileSearchType.d.ts +19 -0
- package/dist/search/fundamentalTypes/fileSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/filelistSearchType.d.ts +32 -0
- package/dist/search/fundamentalTypes/filelistSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/functionSearchType.d.ts +18 -0
- package/dist/search/fundamentalTypes/functionSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/mapSearchType.d.ts +18 -0
- package/dist/search/fundamentalTypes/mapSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/nanSearchType.d.ts +7 -0
- package/dist/search/fundamentalTypes/nanSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/nullSearchType.d.ts +7 -0
- package/dist/search/fundamentalTypes/nullSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/numberSearchType.d.ts +11 -0
- package/dist/search/fundamentalTypes/numberSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/objectSearchType.d.ts +15 -0
- package/dist/search/fundamentalTypes/objectSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/promiseSearchType.d.ts +20 -0
- package/dist/search/fundamentalTypes/promiseSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/regexpSearchType.d.ts +14 -0
- package/dist/search/fundamentalTypes/regexpSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/setSearchType.d.ts +14 -0
- package/dist/search/fundamentalTypes/setSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/stringSearchType.d.ts +13 -0
- package/dist/search/fundamentalTypes/stringSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/symbolSearchType.d.ts +16 -0
- package/dist/search/fundamentalTypes/symbolSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/undefinedSearchType.d.ts +7 -0
- package/dist/search/fundamentalTypes/undefinedSearchType.d.ts.map +1 -0
- package/dist/search/index.d.ts +60 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/queryTree.d.ts.map +1 -1
- package/dist/search/queryTreeBuilders.d.ts +12 -0
- package/dist/search/queryTreeBuilders.d.ts.map +1 -1
- package/dist/search/searchDispatch.d.ts +44 -0
- package/dist/search/searchDispatch.d.ts.map +1 -1
- package/dist/search/searchElementUtils.d.ts +97 -0
- package/dist/search/searchElementUtils.d.ts.map +1 -0
- package/dist/search/searchUtils.d.ts +225 -0
- package/dist/search/searchUtils.d.ts.map +1 -0
- package/dist/search/subTypes/blobHTMLSearchType.d.ts +16 -0
- package/dist/search/subTypes/blobHTMLSearchType.d.ts.map +1 -0
- package/dist/search/subTypes/recordSearchType.d.ts +18 -0
- package/dist/search/subTypes/recordSearchType.d.ts.map +1 -0
- package/dist/search/subTypes/tupleSearchType.d.ts +21 -0
- package/dist/search/subTypes/tupleSearchType.d.ts.map +1 -0
- package/dist/search/superTypes/SpecialRealNumberSearchType.d.ts +14 -0
- package/dist/search/superTypes/SpecialRealNumberSearchType.d.ts.map +1 -0
- package/dist/search/superTypes/buffersourceSearchType.d.ts +17 -0
- package/dist/search/superTypes/buffersourceSearchType.d.ts.map +1 -0
- package/dist/search/superTypes/dommatrixSearchType.d.ts +11 -0
- package/dist/search/superTypes/dommatrixSearchType.d.ts.map +1 -0
- package/dist/search/superTypes/dompointSearchType.d.ts +9 -0
- package/dist/search/superTypes/dompointSearchType.d.ts.map +1 -0
- package/dist/search/superTypes/domrectSearchType.d.ts +9 -0
- package/dist/search/superTypes/domrectSearchType.d.ts.map +1 -0
- package/dist/search/superTypes/errorsSpecialSearchType.d.ts +11 -0
- package/dist/search/superTypes/errorsSpecialSearchType.d.ts.map +1 -0
- package/dist/search/unions/discriminatedUnionSearchType.d.ts +12 -0
- package/dist/search/unions/discriminatedUnionSearchType.d.ts.map +1 -0
- package/dist/search/unions/unionFamilySearchType.d.ts +36 -0
- package/dist/search/unions/unionFamilySearchType.d.ts.map +1 -0
- package/dist/search/unions/unionSearchType.d.ts +8 -0
- package/dist/search/unions/unionSearchType.d.ts.map +1 -0
- package/dist/search/unions/xorSearchType.d.ts +12 -0
- package/dist/search/unions/xorSearchType.d.ts.map +1 -0
- package/dist/superTypes/buffersourceType.d.ts.map +1 -1
- package/dist/typeChoices.d.ts +3 -3
- package/dist/typeChoices.d.ts.map +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -4
- package/pnpm-workspace.yaml +1 -1
- package/rollup.config.js +12 -0
- package/src/formatAndTypeChoices.js +4 -4
- package/src/formats/schema.js +1 -1
- package/src/formats.js +1 -1
- package/src/fundamentalTypes/dateType.js +35 -14
- package/src/fundamentalTypes/domexceptionType.js +41 -33
- package/src/index.js +6 -0
- package/src/jtltExtensions.js +103 -0
- package/src/search/fundamentalTypes/arraySearchType.js +66 -0
- package/src/search/fundamentalTypes/bigintSearchType.js +62 -0
- package/src/search/fundamentalTypes/blobSearchType.js +41 -0
- package/src/search/fundamentalTypes/booleanSearchType.js +40 -0
- package/src/search/fundamentalTypes/catchSearchType.js +59 -0
- package/src/search/fundamentalTypes/dateSearchType.js +73 -0
- package/src/search/fundamentalTypes/domexceptionSearchType.js +55 -0
- package/src/search/fundamentalTypes/enumSearchType.js +58 -0
- package/src/search/fundamentalTypes/errorSearchType.js +11 -0
- package/src/search/fundamentalTypes/fileSearchType.js +41 -0
- package/src/search/fundamentalTypes/filelistSearchType.js +78 -0
- package/src/search/fundamentalTypes/functionSearchType.js +78 -0
- package/src/search/fundamentalTypes/mapSearchType.js +87 -0
- package/src/search/fundamentalTypes/nanSearchType.js +11 -0
- package/src/search/fundamentalTypes/nullSearchType.js +11 -0
- package/src/search/fundamentalTypes/numberSearchType.js +52 -0
- package/src/search/fundamentalTypes/objectSearchType.js +148 -0
- package/src/search/fundamentalTypes/promiseSearchType.js +61 -0
- package/src/search/fundamentalTypes/regexpSearchType.js +48 -0
- package/src/search/fundamentalTypes/setSearchType.js +65 -0
- package/src/search/fundamentalTypes/stringSearchType.js +35 -0
- package/src/search/fundamentalTypes/symbolSearchType.js +38 -0
- package/src/search/fundamentalTypes/undefinedSearchType.js +11 -0
- package/src/search/index.js +79 -0
- package/src/search/queryTree.js +235 -0
- package/src/search/queryTreeBuilders.js +224 -0
- package/src/search/searchDispatch.js +291 -0
- package/src/search/searchElementUtils.js +289 -0
- package/src/search/searchUtils.js +355 -0
- package/src/search/subTypes/blobHTMLSearchType.js +65 -0
- package/src/search/subTypes/recordSearchType.js +84 -0
- package/src/search/subTypes/tupleSearchType.js +111 -0
- package/src/search/superTypes/SpecialRealNumberSearchType.js +42 -0
- package/src/search/superTypes/buffersourceSearchType.js +47 -0
- package/src/search/superTypes/dommatrixSearchType.js +24 -0
- package/src/search/superTypes/dompointSearchType.js +15 -0
- package/src/search/superTypes/domrectSearchType.js +15 -0
- package/src/search/superTypes/errorsSpecialSearchType.js +15 -0
- package/src/search/unions/discriminatedUnionSearchType.js +16 -0
- package/src/search/unions/unionFamilySearchType.js +160 -0
- package/src/search/unions/unionSearchType.js +12 -0
- package/src/search/unions/xorSearchType.js +16 -0
- package/src/superTypes/buffersourceType.js +13 -15
- package/src/typeChoices.js +2 -2
- package/src/types.js +2 -2
- package/tsconfig-prod.json +12 -0
- package/tsconfig.json +5 -10
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import {schemaLabel} from '../utils/schemaMeta.js';
|
|
2
|
+
import {getJSONPointerParts} from '../utils/jsonPointer.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {import('../types.js').JamilihArray} JamilihArray
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Label for a leaf/container's own control, preferring the schema's own
|
|
10
|
+
* `meta.title`/`meta.description`/`description` (via `schemaLabel`, same
|
|
11
|
+
* precedence the value-editing side uses) and falling back to the JSON
|
|
12
|
+
* Pointer path's final segment so every control still has a legible label
|
|
13
|
+
* even when the schema carries no metadata.
|
|
14
|
+
* @param {import('../formats/schema.js').ZodexSchema|undefined} schemaObject
|
|
15
|
+
* @param {string} path
|
|
16
|
+
* @returns {string}
|
|
17
|
+
*/
|
|
18
|
+
export function buildPathLabel (schemaObject, path) {
|
|
19
|
+
const label = schemaLabel(schemaObject);
|
|
20
|
+
if (label) {
|
|
21
|
+
return label;
|
|
22
|
+
}
|
|
23
|
+
const parts = getJSONPointerParts(path);
|
|
24
|
+
return parts.length ? String(parts.at(-1)) : path;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Finds a control belonging directly to `root`'s own widget - as opposed to
|
|
29
|
+
* one belonging to a search widget recursively nested inside it (e.g.
|
|
30
|
+
* `arraySearchType.js`'s own "size" input vs. a nested array-of-arrays'
|
|
31
|
+
* element widget's own "size" input, both reachable from `root` via a plain
|
|
32
|
+
* `querySelectorAll`). A match only counts if the nearest ancestor of the
|
|
33
|
+
* match carrying `data-search-path` is `root` itself; every search element
|
|
34
|
+
* carries that attribute (`searchElementUtils.js`'s `findSearchElement`), so
|
|
35
|
+
* this reliably stops at the first nested search element's boundary.
|
|
36
|
+
*
|
|
37
|
+
* This is also why every `build*`/`read*` pair below reads its class-based
|
|
38
|
+
* selector back through this helper rather than a raw
|
|
39
|
+
* `root.querySelector(...)`: a fixed class name is safe to reuse across
|
|
40
|
+
* every instance of a given control on the page precisely because lookups
|
|
41
|
+
* are always scoped this way, and - unlike a `name` built from a
|
|
42
|
+
* `typeNamespace` closed over inside a `$define` mixin, which is installed
|
|
43
|
+
* once on the shared custom-element prototype the first time a tag is
|
|
44
|
+
* defined - nothing here depends on a per-instance closure at all.
|
|
45
|
+
* @param {HTMLElement} root
|
|
46
|
+
* @param {string} selector
|
|
47
|
+
* @returns {HTMLElement|undefined}
|
|
48
|
+
*/
|
|
49
|
+
export function findOwnControl (root, selector) {
|
|
50
|
+
return /** @type {HTMLElement[]} */ (
|
|
51
|
+
[...root.querySelectorAll(selector)]
|
|
52
|
+
).find((el) => el.closest('[data-search-path]') === root);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* A "from"/"to" pair of native inputs sharing one `type`, for the OR-range/
|
|
57
|
+
* Is-Not-Range README affordance (number/bigint/buffersource; `date` uses
|
|
58
|
+
* `dateType.js`'s own `buildDateInputControl` instead, since a
|
|
59
|
+
* `datetime-local` input needs its own ISO-slicing).
|
|
60
|
+
*
|
|
61
|
+
* `key` distinguishes multiple range pairs *within one widget* (e.g.
|
|
62
|
+
* `domrectSearchType.js`'s `x`/`y`/`width`/`height` dimensions, or
|
|
63
|
+
* `errorSearchType.js`'s `lineNumber`/`columnNumber`): `findOwnControl`
|
|
64
|
+
* already isolates one widget's controls from another's, but can't tell
|
|
65
|
+
* apart two same-class controls belonging to the *same* widget, so those
|
|
66
|
+
* need distinct classes. Leave it at the default `''` for the common case
|
|
67
|
+
* of a widget with only one range pair.
|
|
68
|
+
* @param {{
|
|
69
|
+
* name: string,
|
|
70
|
+
* key?: string,
|
|
71
|
+
* type?: string,
|
|
72
|
+
* min?: string|number,
|
|
73
|
+
* max?: string|number,
|
|
74
|
+
* step?: string|number
|
|
75
|
+
* }} cfg
|
|
76
|
+
* @returns {JamilihArray[]}
|
|
77
|
+
*/
|
|
78
|
+
export function buildRangeInputsPair ({
|
|
79
|
+
name, key = '', type = 'number', min, max, step
|
|
80
|
+
}) {
|
|
81
|
+
return [
|
|
82
|
+
['label', [
|
|
83
|
+
'From: ',
|
|
84
|
+
['input', {name: `${name}-gte`, class: `jsoeSearchRangeGte--${key}`, type, min, max, step}]
|
|
85
|
+
]],
|
|
86
|
+
['label', [
|
|
87
|
+
'To: ',
|
|
88
|
+
['input', {name: `${name}-lte`, class: `jsoeSearchRangeLte--${key}`, type, min, max, step}]
|
|
89
|
+
]]
|
|
90
|
+
];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Reads back a `buildRangeInputsPair` - pass the same `key` it was built
|
|
95
|
+
* with.
|
|
96
|
+
* @param {HTMLElement} el
|
|
97
|
+
* @param {string} [key]
|
|
98
|
+
* @returns {{gte: string, lte: string}}
|
|
99
|
+
*/
|
|
100
|
+
export function readRangeInputsPair (el, key = '') {
|
|
101
|
+
const gte = /** @type {HTMLInputElement|undefined} */ (
|
|
102
|
+
findOwnControl(el, `input.jsoeSearchRangeGte--${key}`)
|
|
103
|
+
)?.value ?? '';
|
|
104
|
+
const lte = /** @type {HTMLInputElement|undefined} */ (
|
|
105
|
+
findOwnControl(el, `input.jsoeSearchRangeLte--${key}`)
|
|
106
|
+
)?.value ?? '';
|
|
107
|
+
return {gte, lte};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* A `<select multiple>` populated from a fixed candidate list - used by
|
|
112
|
+
* `enum`/`multiSelect`/`literalSet` leaf controls (README: "multiple
|
|
113
|
+
* select").
|
|
114
|
+
* @param {{
|
|
115
|
+
* name: string,
|
|
116
|
+
* options: (string|[value: string, title: string])[]
|
|
117
|
+
* }} cfg
|
|
118
|
+
* @returns {JamilihArray}
|
|
119
|
+
*/
|
|
120
|
+
export function buildMultiSelect ({name, options}) {
|
|
121
|
+
return ['select', {name, multiple: true, class: 'jsoeSearchMultiSelect'}, options.map((opt) => {
|
|
122
|
+
const [value, title] = Array.isArray(opt) ? opt : [opt, opt];
|
|
123
|
+
return ['option', {value}, [title]];
|
|
124
|
+
})];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Reads back a `buildMultiSelect` into the selected values, `[]` if none.
|
|
129
|
+
* @param {HTMLElement} el
|
|
130
|
+
* @returns {string[]}
|
|
131
|
+
*/
|
|
132
|
+
export function readMultiSelect (el) {
|
|
133
|
+
const select = /** @type {HTMLSelectElement|undefined} */ (
|
|
134
|
+
findOwnControl(el, 'select.jsoeSearchMultiSelect')
|
|
135
|
+
);
|
|
136
|
+
return [...(select?.selectedOptions ?? [])].map((opt) => opt.value);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* A tri-state "has property" control for one already-chosen property name
|
|
141
|
+
* (README: "Has property <property pull-down>", "avoid listing
|
|
142
|
+
* required"). `objectSearchType.js` supplies the additive pull-down that
|
|
143
|
+
* lets a user pick *which* property to add one of these for; this helper is
|
|
144
|
+
* only the fixed per-property toggle it adds each time, so the "any" state
|
|
145
|
+
* (no constraint entered) is distinguishable from an explicit "has"/
|
|
146
|
+
* "doesn't have" - matching `SearchTypeObject.getQuery`'s
|
|
147
|
+
* `undefined`-means-"no constraint" convention. Shares `readTriStateSelect`
|
|
148
|
+
* with `buildTriStateSelect` below - same three-value shape, just different
|
|
149
|
+
* option labels.
|
|
150
|
+
* @param {{name: string, propertyName: string}} cfg
|
|
151
|
+
* @returns {JamilihArray}
|
|
152
|
+
*/
|
|
153
|
+
export function buildHasPropertyToggle ({name, propertyName}) {
|
|
154
|
+
return ['label', [
|
|
155
|
+
`Has property "${propertyName}": `,
|
|
156
|
+
['select', {name, class: 'jsoeSearchTriState--'}, [
|
|
157
|
+
['option', {value: ''}, ['(any)']],
|
|
158
|
+
['option', {value: 'true'}, ['Has']],
|
|
159
|
+
['option', {value: 'false'}, ['Doesn’t have']]
|
|
160
|
+
]]
|
|
161
|
+
]];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* A generic "(any)"/true/false `<select>`, shared by every leaf whose only
|
|
166
|
+
* constraint is a plain boolean choice - `booleanSearchType.js`'s "true or
|
|
167
|
+
* false" (README) and `numberSearchType.js`'s "Is/Is Not Integer" both read
|
|
168
|
+
* back through this same three-way convention rather than each rolling
|
|
169
|
+
* their own.
|
|
170
|
+
*
|
|
171
|
+
* `key` distinguishes multiple tri-states *within one widget* (e.g.
|
|
172
|
+
* `dommatrixSearchType.js`'s "Is/Is not Readonly" and "Is/Is not 3d" side
|
|
173
|
+
* by side); see `buildRangeInputsPair`'s doc for why. Leave it at the
|
|
174
|
+
* default `''` for the common case of a widget with only one tri-state.
|
|
175
|
+
* @param {{name: string, key?: string, trueLabel: string, falseLabel: string}} cfg
|
|
176
|
+
* @returns {JamilihArray}
|
|
177
|
+
*/
|
|
178
|
+
export function buildTriStateSelect ({name, key = '', trueLabel, falseLabel}) {
|
|
179
|
+
return ['select', {name, class: `jsoeSearchTriState--${key}`}, [
|
|
180
|
+
['option', {value: ''}, ['(any)']],
|
|
181
|
+
['option', {value: 'true'}, [trueLabel]],
|
|
182
|
+
['option', {value: 'false'}, [falseLabel]]
|
|
183
|
+
]];
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Reads back a `buildTriStateSelect`/`buildHasPropertyToggle` - pass the
|
|
188
|
+
* same `key` it was built with. `''` (any) maps to `undefined`.
|
|
189
|
+
* @param {HTMLElement} el
|
|
190
|
+
* @param {string} [key]
|
|
191
|
+
* @returns {boolean|undefined}
|
|
192
|
+
*/
|
|
193
|
+
export function readTriStateSelect (el, key = '') {
|
|
194
|
+
const select = /** @type {HTMLSelectElement|undefined} */ (
|
|
195
|
+
findOwnControl(el, `select.jsoeSearchTriState--${key}`)
|
|
196
|
+
);
|
|
197
|
+
if (!select || select.value === '') {
|
|
198
|
+
return undefined;
|
|
199
|
+
}
|
|
200
|
+
return select.value === 'true';
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* A single checkbox - the only search affordance the README grants
|
|
205
|
+
* `undefined`/`void`/`null`/`NaN` ("Require present"; they have "no
|
|
206
|
+
* variants to allow for distinct search", since existence only becomes a
|
|
207
|
+
* meaningful question once the path is optional or nested in a union), and
|
|
208
|
+
* also used by `recordSearchType.js` for its "require same entry" toggle.
|
|
209
|
+
* @param {{name: string, label: string}} cfg
|
|
210
|
+
* @returns {JamilihArray}
|
|
211
|
+
*/
|
|
212
|
+
export function buildCheckbox ({name, label}) {
|
|
213
|
+
return ['label', [
|
|
214
|
+
`${label}: `,
|
|
215
|
+
['input', {type: 'checkbox', name, class: 'jsoeSearchCheckbox'}]
|
|
216
|
+
]];
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Reads back a `buildCheckbox`.
|
|
221
|
+
* @param {HTMLElement} el
|
|
222
|
+
* @returns {boolean}
|
|
223
|
+
*/
|
|
224
|
+
export function readCheckbox (el) {
|
|
225
|
+
return Boolean(/** @type {HTMLInputElement|undefined} */ (
|
|
226
|
+
findOwnControl(el, 'input.jsoeSearchCheckbox')
|
|
227
|
+
)?.checked);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* The mode selector for the README's "string, StringObject, Blob, File,
|
|
232
|
+
* regexp (source), symbol (description): OR literal or regex search/Does
|
|
233
|
+
* Not contain search" - one shared control (and reader, below) that
|
|
234
|
+
* `stringSearchType.js`, `symbolSearchType.js`, and `regexpSearchType.js`
|
|
235
|
+
* (for its source) each build their own custom element around, since the
|
|
236
|
+
* query semantics are identical and only the label/target facet differs.
|
|
237
|
+
*
|
|
238
|
+
* `key` distinguishes multiple literal/regex controls *within one widget*
|
|
239
|
+
* (e.g. `errorSearchType.js`'s `message`/`name`/`fileName`/`stack`); see
|
|
240
|
+
* `buildRangeInputsPair`'s doc for why. Leave it at the default `''` for
|
|
241
|
+
* the common case of a widget with only one such control.
|
|
242
|
+
* @param {{name: string, key?: string}} cfg
|
|
243
|
+
* @returns {JamilihArray}
|
|
244
|
+
*/
|
|
245
|
+
export function buildLiteralRegexControls ({name, key = ''}) {
|
|
246
|
+
return ['span', [
|
|
247
|
+
['label', [
|
|
248
|
+
'Mode: ',
|
|
249
|
+
['select', {name: `${name}-mode`, class: `jsoeSearchMode--${key}`}, [
|
|
250
|
+
['option', {value: 'literal'}, ['One of (comma-separated)']],
|
|
251
|
+
['option', {value: 'regex'}, ['Matches regex']],
|
|
252
|
+
['option', {value: 'notContains'}, ['Does not contain']]
|
|
253
|
+
]]
|
|
254
|
+
]],
|
|
255
|
+
['label', [
|
|
256
|
+
'Value: ',
|
|
257
|
+
['input', {type: 'text', name: `${name}-value`, class: `jsoeSearchValue--${key}`}]
|
|
258
|
+
]]
|
|
259
|
+
]];
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Reads back `buildLiteralRegexControls` into the corresponding
|
|
264
|
+
* `literalSet`/`regex`/`notContains` leaf - pass the same `key` it was
|
|
265
|
+
* built with.
|
|
266
|
+
* @param {HTMLElement} el
|
|
267
|
+
* @param {string} path
|
|
268
|
+
* @param {string} [key]
|
|
269
|
+
* @returns {import('./queryTree.js').QueryLiteralSetLeaf|
|
|
270
|
+
* import('./queryTree.js').QueryRegexLeaf|
|
|
271
|
+
* import('./queryTree.js').QueryNotContainsLeaf|undefined}
|
|
272
|
+
*/
|
|
273
|
+
export function readLiteralRegexQuery (el, path, key = '') {
|
|
274
|
+
const mode = /** @type {HTMLSelectElement|undefined} */ (
|
|
275
|
+
findOwnControl(el, `select.jsoeSearchMode--${key}`)
|
|
276
|
+
)?.value;
|
|
277
|
+
const value = /** @type {HTMLInputElement|undefined} */ (
|
|
278
|
+
findOwnControl(el, `input.jsoeSearchValue--${key}`)
|
|
279
|
+
)?.value;
|
|
280
|
+
if (!value) {
|
|
281
|
+
return undefined;
|
|
282
|
+
}
|
|
283
|
+
if (mode === 'regex') {
|
|
284
|
+
return {kind: 'regex', path, $regex: value};
|
|
285
|
+
}
|
|
286
|
+
if (mode === 'notContains') {
|
|
287
|
+
return {kind: 'notContains', path, value};
|
|
288
|
+
}
|
|
289
|
+
return {
|
|
290
|
+
kind: 'literalSet',
|
|
291
|
+
path,
|
|
292
|
+
$in: value.split(',').map((v) => v.trim()).filter(Boolean)
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Has length/size of <number> (README; array/set/tuple-with-rest/
|
|
298
|
+
* filelist), + "Is/Is not sparse" for arrays only. Returns `[]` (no
|
|
299
|
+
* control) when the schema pins an exact length/size, since searching on a
|
|
300
|
+
* constant is uninteresting - the schema's `min`/`max` otherwise become the
|
|
301
|
+
* input's HTML `min`/`max` attributes.
|
|
302
|
+
* @param {{
|
|
303
|
+
* name: string,
|
|
304
|
+
* min?: number,
|
|
305
|
+
* max?: number,
|
|
306
|
+
* includeSparse?: boolean
|
|
307
|
+
* }} cfg
|
|
308
|
+
* @returns {JamilihArray[]}
|
|
309
|
+
*/
|
|
310
|
+
export function buildLengthSizeControls ({name, min, max, includeSparse}) {
|
|
311
|
+
const fixed = min !== undefined && min === max;
|
|
312
|
+
/** @type {JamilihArray[]} */
|
|
313
|
+
const controls = [];
|
|
314
|
+
if (!fixed) {
|
|
315
|
+
controls.push(['label', [
|
|
316
|
+
'Has length/size of: ',
|
|
317
|
+
['input', {
|
|
318
|
+
type: 'number', name: `${name}-size`, class: 'jsoeSearchSize',
|
|
319
|
+
min, max, step: 1
|
|
320
|
+
}]
|
|
321
|
+
]]);
|
|
322
|
+
}
|
|
323
|
+
if (includeSparse) {
|
|
324
|
+
controls.push(['label', [
|
|
325
|
+
'Sparse: ',
|
|
326
|
+
buildTriStateSelect({
|
|
327
|
+
name: `${name}-sparse`, trueLabel: 'Sparse', falseLabel: 'Not sparse'
|
|
328
|
+
})
|
|
329
|
+
]]);
|
|
330
|
+
}
|
|
331
|
+
return controls;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Reads back `buildLengthSizeControls` into one `lengthSize` leaf, or
|
|
336
|
+
* `undefined` if neither the size nor the sparse control was set.
|
|
337
|
+
* @param {HTMLElement} el
|
|
338
|
+
* @param {string} path
|
|
339
|
+
* @returns {import('./queryTree.js').QueryLengthSizeLeaf|undefined}
|
|
340
|
+
*/
|
|
341
|
+
export function readLengthSizeQuery (el, path) {
|
|
342
|
+
const sizeStr = /** @type {HTMLInputElement|undefined} */ (
|
|
343
|
+
findOwnControl(el, 'input.jsoeSearchSize')
|
|
344
|
+
)?.value;
|
|
345
|
+
const sparseCheck = readTriStateSelect(el);
|
|
346
|
+
if (!sizeStr && sparseCheck === undefined) {
|
|
347
|
+
return undefined;
|
|
348
|
+
}
|
|
349
|
+
return {
|
|
350
|
+
kind: 'lengthSize',
|
|
351
|
+
path,
|
|
352
|
+
...(sizeStr ? {$size: Number(sizeStr)} : {}),
|
|
353
|
+
...(sparseCheck === undefined ? {} : {sparseCheck})
|
|
354
|
+
};
|
|
355
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import {buildPathLabel, findOwnControl} from '../searchUtils.js';
|
|
2
|
+
import {makeBlobHTMLLeaf} from '../queryTreeBuilders.js';
|
|
3
|
+
import {getQueryViaElement} from '../searchElementUtils.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {import('../searchDispatch.js').SearchTypeObject} SearchTypeObject
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Blob HTML: XPath, CSS selectors, full text search, regex search of raw
|
|
11
|
+
* HTML (README) - a mode `<select>` plus one text `<input>`, the same
|
|
12
|
+
* "pick a mode, give it one value" shape as `buildLiteralRegexControls`
|
|
13
|
+
* (`searchUtils.js`), but not built through it: the four modes and the
|
|
14
|
+
* `blobHTML` leaf kind they produce are specific to this one type, with no
|
|
15
|
+
* second caller to share the helper with.
|
|
16
|
+
* @type {SearchTypeObject}
|
|
17
|
+
*/
|
|
18
|
+
const blobHTMLSearchType = {
|
|
19
|
+
buildUI ({schemaObject, path, typeNamespace}) {
|
|
20
|
+
const label = buildPathLabel(schemaObject, path);
|
|
21
|
+
const name = `${typeNamespace}-blobHTML`;
|
|
22
|
+
return ['jsoe-search-blob-html', {
|
|
23
|
+
dataset: {searchPath: path, searchKind: 'blobHTML'},
|
|
24
|
+
title: label,
|
|
25
|
+
$define: {
|
|
26
|
+
/** @this {HTMLElement} */
|
|
27
|
+
getQuery () {
|
|
28
|
+
const searchPath = this.dataset.searchPath ?? '';
|
|
29
|
+
const mode = /** @type {HTMLSelectElement|undefined} */ (
|
|
30
|
+
findOwnControl(this, 'select.jsoeSearchBlobHTMLMode')
|
|
31
|
+
)?.value;
|
|
32
|
+
const value = /** @type {HTMLInputElement|undefined} */ (
|
|
33
|
+
findOwnControl(this, 'input.jsoeSearchBlobHTMLValue')
|
|
34
|
+
)?.value;
|
|
35
|
+
if (!value || !mode) {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
return makeBlobHTMLLeaf(
|
|
39
|
+
searchPath,
|
|
40
|
+
/** @type {import('../queryTree.js').QueryBlobHTMLLeaf['mode']} */ (mode),
|
|
41
|
+
value
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}, [
|
|
46
|
+
['span', {class: 'searchLabel'}, [label]],
|
|
47
|
+
['label', [
|
|
48
|
+
'Mode: ',
|
|
49
|
+
['select', {name: `${name}-mode`, class: 'jsoeSearchBlobHTMLMode'}, [
|
|
50
|
+
['option', {value: 'xpath'}, ['XPath']],
|
|
51
|
+
['option', {value: 'cssSelector'}, ['CSS selector']],
|
|
52
|
+
['option', {value: 'fullText'}, ['Full text search']],
|
|
53
|
+
['option', {value: 'rawHTMLRegex'}, ['Regex search of raw HTML']]
|
|
54
|
+
]]
|
|
55
|
+
]],
|
|
56
|
+
['label', [
|
|
57
|
+
'Value: ',
|
|
58
|
+
['input', {type: 'text', name: `${name}-value`, class: 'jsoeSearchBlobHTMLValue'}]
|
|
59
|
+
]]
|
|
60
|
+
]];
|
|
61
|
+
},
|
|
62
|
+
getQuery: getQueryViaElement
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export default blobHTMLSearchType;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import {buildPathLabel, buildCheckbox, readCheckbox} from '../searchUtils.js';
|
|
2
|
+
import {makeMapRecordJointLeaf} from '../queryTreeBuilders.js';
|
|
3
|
+
import {findSearchElement, getQueryViaElement, hasGetQuery} from '../searchElementUtils.js';
|
|
4
|
+
import {buildSearchWidget} from '../searchDispatch.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {import('../searchDispatch.js').SearchTypeObject} SearchTypeObject
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Record search is "key-schema search AND/OR value-schema search,"
|
|
12
|
+
* structurally unlike object's additive "has property" (search plan §1) -
|
|
13
|
+
* recurses into both the `key` and `value` schemas' own search widgets
|
|
14
|
+
* (`*key`/`*value` path segments, `queryTree.js`), and lets the user say
|
|
15
|
+
* whether a match must come from the *same* entry ("has key 2-4 and value
|
|
16
|
+
* 7-9", README) via the "joint" toggle on the resulting `mapRecordJoint`
|
|
17
|
+
* leaf - also used for `looseRecord`, aliased to this same module in
|
|
18
|
+
* `searchDispatch.js` since the search semantics are identical.
|
|
19
|
+
* @type {SearchTypeObject}
|
|
20
|
+
*/
|
|
21
|
+
const recordSearchType = {
|
|
22
|
+
buildUI ({schemaObject, path, typeNamespace, topRoot, types, originalJSON}) {
|
|
23
|
+
const label = buildPathLabel(schemaObject, path);
|
|
24
|
+
const name = `${typeNamespace}-record`;
|
|
25
|
+
const recordSchemaObject = /** @type {import('zodexy').SzRecord} */ (
|
|
26
|
+
schemaObject
|
|
27
|
+
);
|
|
28
|
+
const keyPath = `${path}/*key`;
|
|
29
|
+
const valuePath = `${path}/*value`;
|
|
30
|
+
const keyArr = buildSearchWidget({
|
|
31
|
+
schemaObject: recordSchemaObject.key,
|
|
32
|
+
path: keyPath,
|
|
33
|
+
typeNamespace,
|
|
34
|
+
topRoot,
|
|
35
|
+
types,
|
|
36
|
+
originalJSON
|
|
37
|
+
});
|
|
38
|
+
const valueArr = buildSearchWidget({
|
|
39
|
+
schemaObject: recordSchemaObject.value,
|
|
40
|
+
path: valuePath,
|
|
41
|
+
typeNamespace,
|
|
42
|
+
topRoot,
|
|
43
|
+
types,
|
|
44
|
+
originalJSON
|
|
45
|
+
});
|
|
46
|
+
return ['jsoe-search-record', {
|
|
47
|
+
dataset: {searchPath: path, searchKind: 'record'},
|
|
48
|
+
title: label,
|
|
49
|
+
$define: {
|
|
50
|
+
/** @this {HTMLElement} */
|
|
51
|
+
getQuery () {
|
|
52
|
+
const searchPath = this.dataset.searchPath ?? '';
|
|
53
|
+
const keyEl = findSearchElement(this, `${searchPath}/*key`);
|
|
54
|
+
const valueEl = findSearchElement(this, `${searchPath}/*value`);
|
|
55
|
+
const keyQuery = keyEl && hasGetQuery(keyEl)
|
|
56
|
+
? keyEl.getQuery()
|
|
57
|
+
: undefined;
|
|
58
|
+
const valueQuery = valueEl && hasGetQuery(valueEl)
|
|
59
|
+
? valueEl.getQuery()
|
|
60
|
+
: undefined;
|
|
61
|
+
if (!keyQuery && !valueQuery) {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
const joint = readCheckbox(this);
|
|
65
|
+
return makeMapRecordJointLeaf(searchPath, joint, keyQuery, valueQuery);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}, [
|
|
69
|
+
['span', {class: 'searchLabel'}, [label]],
|
|
70
|
+
['div', {class: 'searchRecordKey'}, [
|
|
71
|
+
['span', ['Key matches: ']],
|
|
72
|
+
keyArr
|
|
73
|
+
]],
|
|
74
|
+
['div', {class: 'searchRecordValue'}, [
|
|
75
|
+
['span', ['Value matches: ']],
|
|
76
|
+
valueArr
|
|
77
|
+
]],
|
|
78
|
+
buildCheckbox({name: `${name}-joint`, label: 'Require same entry'})
|
|
79
|
+
]];
|
|
80
|
+
},
|
|
81
|
+
getQuery: getQueryViaElement
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export default recordSearchType;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import {buildPathLabel, buildLengthSizeControls, readLengthSizeQuery} from '../searchUtils.js';
|
|
2
|
+
import {combineAnd} from '../queryTreeBuilders.js';
|
|
3
|
+
import {findSearchElement, getQueryViaElement, hasGetQuery} from '../searchElementUtils.js';
|
|
4
|
+
import {buildSearchWidget} from '../searchDispatch.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {import('../searchDispatch.js').SearchTypeObject} SearchTypeObject
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Each fixed position gets its own control from `.items[i]`, not one
|
|
12
|
+
* control repeated per element (search plan §1 - unlike the value-editing
|
|
13
|
+
* side, this gets a dedicated module rather than delegating to
|
|
14
|
+
* `arraySearchType.js`, since positions aren't interchangeable). A tuple
|
|
15
|
+
* with no `rest` has an inherently fixed length (`items.length`), so - as
|
|
16
|
+
* with a fixed-length array - no length control is shown for it; "with rest
|
|
17
|
+
* has size search as with arrays" (README) applies once `rest` is present:
|
|
18
|
+
* total length becomes a variable-length `lengthSize` control (`min:
|
|
19
|
+
* items.length`, no sparse toggle - not applicable to a tuple), and the
|
|
20
|
+
* `rest` element itself recurses into its own search widget under the same
|
|
21
|
+
* `*` path-segment convention `arraySearchType.js` uses for its element.
|
|
22
|
+
* @type {SearchTypeObject}
|
|
23
|
+
*/
|
|
24
|
+
const tupleSearchType = {
|
|
25
|
+
buildUI ({schemaObject, path, typeNamespace, topRoot, types, originalJSON}) {
|
|
26
|
+
const label = buildPathLabel(schemaObject, path);
|
|
27
|
+
const name = `${typeNamespace}-tuple`;
|
|
28
|
+
const tupleSchemaObject = /** @type {import('zodexy').SzTuple} */ (
|
|
29
|
+
schemaObject
|
|
30
|
+
);
|
|
31
|
+
const {items, rest} = tupleSchemaObject;
|
|
32
|
+
|
|
33
|
+
const itemArrs = items.map((itemSchema, idx) => buildSearchWidget({
|
|
34
|
+
schemaObject: itemSchema,
|
|
35
|
+
path: `${path}/${idx}`,
|
|
36
|
+
typeNamespace,
|
|
37
|
+
topRoot,
|
|
38
|
+
types,
|
|
39
|
+
originalJSON
|
|
40
|
+
}));
|
|
41
|
+
|
|
42
|
+
const restElementPath = `${path}/*`;
|
|
43
|
+
const restArr = rest
|
|
44
|
+
? buildSearchWidget({
|
|
45
|
+
schemaObject: rest,
|
|
46
|
+
path: restElementPath,
|
|
47
|
+
typeNamespace,
|
|
48
|
+
topRoot,
|
|
49
|
+
types,
|
|
50
|
+
originalJSON
|
|
51
|
+
})
|
|
52
|
+
: undefined;
|
|
53
|
+
|
|
54
|
+
/** @type {import('../../types.js').JamilihArray[]} */
|
|
55
|
+
const children = [['span', {class: 'searchLabel'}, [label]]];
|
|
56
|
+
itemArrs.forEach((itemArr, idx) => {
|
|
57
|
+
children.push(['div', {class: 'searchTupleItem'}, [
|
|
58
|
+
['span', [`Position ${idx}: `]],
|
|
59
|
+
itemArr
|
|
60
|
+
]]);
|
|
61
|
+
});
|
|
62
|
+
if (rest) {
|
|
63
|
+
children.push(
|
|
64
|
+
...buildLengthSizeControls({
|
|
65
|
+
name, min: items.length, max: undefined, includeSparse: false
|
|
66
|
+
}),
|
|
67
|
+
['div', {class: 'searchTupleRest'}, [
|
|
68
|
+
['span', ['Rest element matches: ']],
|
|
69
|
+
/** @type {import('../../types.js').JamilihArray} */ (restArr)
|
|
70
|
+
]]
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return ['jsoe-search-tuple', {
|
|
75
|
+
dataset: {
|
|
76
|
+
searchPath: path, searchKind: 'tuple',
|
|
77
|
+
itemCount: String(items.length), hasRest: rest ? 'true' : ''
|
|
78
|
+
},
|
|
79
|
+
title: label,
|
|
80
|
+
$define: {
|
|
81
|
+
// Reads `itemCount`/`hasRest` off `this.dataset` rather than
|
|
82
|
+
// closing over `items`/`rest`: `$define`'s mixin is installed
|
|
83
|
+
// once on the shared prototype the first time this tag is
|
|
84
|
+
// defined, so a second tuple widget on the same page would
|
|
85
|
+
// otherwise silently reuse the first tuple's item count/rest-ness.
|
|
86
|
+
/** @this {HTMLElement} */
|
|
87
|
+
getQuery () {
|
|
88
|
+
const searchPath = this.dataset.searchPath ?? '';
|
|
89
|
+
const itemCount = Number(this.dataset.itemCount ?? '0');
|
|
90
|
+
const hasRest = this.dataset.hasRest === 'true';
|
|
91
|
+
const itemLeaves = Array.from({length: itemCount}, (_, idx) => {
|
|
92
|
+
const itemEl = findSearchElement(this, `${searchPath}/${idx}`);
|
|
93
|
+
return itemEl && hasGetQuery(itemEl) ? itemEl.getQuery() : undefined;
|
|
94
|
+
});
|
|
95
|
+
if (!hasRest) {
|
|
96
|
+
return combineAnd(itemLeaves);
|
|
97
|
+
}
|
|
98
|
+
const lengthLeaf = readLengthSizeQuery(this, searchPath);
|
|
99
|
+
const restEl = findSearchElement(this, `${searchPath}/*`);
|
|
100
|
+
const restLeaf = restEl && hasGetQuery(restEl)
|
|
101
|
+
? restEl.getQuery()
|
|
102
|
+
: undefined;
|
|
103
|
+
return combineAnd([...itemLeaves, lengthLeaf, restLeaf]);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}, children];
|
|
107
|
+
},
|
|
108
|
+
getQuery: getQueryViaElement
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export default tupleSearchType;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {buildPathLabel, buildMultiSelect, readMultiSelect} from '../searchUtils.js';
|
|
2
|
+
import {makeMultiSelectLeaf} from '../queryTreeBuilders.js';
|
|
3
|
+
import {getQueryViaElement} from '../searchElementUtils.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {import('../searchDispatch.js').SearchTypeObject} SearchTypeObject
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Special number: multiple select of "Infinity", "-Infinity" (README;
|
|
11
|
+
* `NaN` is covered separately by `nanSearchType.js`'s presence-only
|
|
12
|
+
* control, since it's its own zodex schema type - `SpecialRealNumberType.js`
|
|
13
|
+
* itself covers exactly `Infinity`/`-Infinity`/`-0`, not `NaN`).
|
|
14
|
+
* @type {SearchTypeObject}
|
|
15
|
+
*/
|
|
16
|
+
const SpecialRealNumberSearchType = {
|
|
17
|
+
buildUI ({schemaObject, path, typeNamespace}) {
|
|
18
|
+
const label = buildPathLabel(schemaObject, path);
|
|
19
|
+
const name = `${typeNamespace}-SpecialRealNumber`;
|
|
20
|
+
return ['jsoe-search-special-real-number', {
|
|
21
|
+
dataset: {searchPath: path, searchKind: 'SpecialRealNumber'},
|
|
22
|
+
title: label,
|
|
23
|
+
$define: {
|
|
24
|
+
/** @this {HTMLElement} */
|
|
25
|
+
getQuery () {
|
|
26
|
+
const selected = readMultiSelect(this);
|
|
27
|
+
return selected.length
|
|
28
|
+
? makeMultiSelectLeaf(this.dataset.searchPath ?? '', {$in: selected})
|
|
29
|
+
: undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}, [
|
|
33
|
+
['span', {class: 'searchLabel'}, [label]],
|
|
34
|
+
buildMultiSelect({
|
|
35
|
+
name, options: ['Infinity', '-Infinity', '-0']
|
|
36
|
+
})
|
|
37
|
+
]];
|
|
38
|
+
},
|
|
39
|
+
getQuery: getQueryViaElement
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default SpecialRealNumberSearchType;
|