@es-joy/jsoe 0.28.2 → 0.30.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/.claude/scheduled_tasks.lock +1 -0
- package/CHANGES.md +25 -0
- package/README.md +4 -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 +26 -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 +22 -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 +15 -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 +26 -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 +28 -0
- package/dist/search/fundamentalTypes/fileSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/filelistSearchType.d.ts +24 -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 +22 -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 +21 -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 +20 -0
- package/dist/search/fundamentalTypes/regexpSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/setSearchType.d.ts +15 -0
- package/dist/search/fundamentalTypes/setSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/stringSearchType.d.ts +21 -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 +70 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/queryTree.d.ts +12 -1
- package/dist/search/queryTree.d.ts.map +1 -1
- package/dist/search/queryTreeBuilders.d.ts +18 -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 +106 -0
- package/dist/search/searchElementUtils.d.ts.map +1 -0
- package/dist/search/searchUtils.d.ts +550 -0
- package/dist/search/searchUtils.d.ts.map +1 -0
- package/dist/search/subTypes/blobHTMLSearchType.d.ts +36 -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 +40 -14
- package/src/fundamentalTypes/domexceptionType.js +41 -33
- package/src/fundamentalTypes/regexpType.js +1 -1
- package/src/index.js +6 -0
- package/src/jsoe.css +204 -0
- package/src/jtltExtensions.js +103 -0
- package/src/search/fundamentalTypes/arraySearchType.js +101 -0
- package/src/search/fundamentalTypes/bigintSearchType.js +68 -0
- package/src/search/fundamentalTypes/blobSearchType.js +42 -0
- package/src/search/fundamentalTypes/booleanSearchType.js +40 -0
- package/src/search/fundamentalTypes/catchSearchType.js +59 -0
- package/src/search/fundamentalTypes/dateSearchType.js +166 -0
- package/src/search/fundamentalTypes/domexceptionSearchType.js +84 -0
- package/src/search/fundamentalTypes/enumSearchType.js +62 -0
- package/src/search/fundamentalTypes/errorSearchType.js +11 -0
- package/src/search/fundamentalTypes/fileSearchType.js +94 -0
- package/src/search/fundamentalTypes/filelistSearchType.js +103 -0
- package/src/search/fundamentalTypes/functionSearchType.js +102 -0
- package/src/search/fundamentalTypes/mapSearchType.js +117 -0
- package/src/search/fundamentalTypes/nanSearchType.js +11 -0
- package/src/search/fundamentalTypes/nullSearchType.js +11 -0
- package/src/search/fundamentalTypes/numberSearchType.js +59 -0
- package/src/search/fundamentalTypes/objectSearchType.js +367 -0
- package/src/search/fundamentalTypes/promiseSearchType.js +61 -0
- package/src/search/fundamentalTypes/regexpSearchType.js +72 -0
- package/src/search/fundamentalTypes/setSearchType.js +91 -0
- package/src/search/fundamentalTypes/stringSearchType.js +44 -0
- package/src/search/fundamentalTypes/symbolSearchType.js +39 -0
- package/src/search/fundamentalTypes/undefinedSearchType.js +11 -0
- package/src/search/index.js +96 -0
- package/src/search/queryTree.js +244 -0
- package/src/search/queryTreeBuilders.js +233 -0
- package/src/search/searchDispatch.js +291 -0
- package/src/search/searchElementUtils.js +373 -0
- package/src/search/searchUtils.js +847 -0
- package/src/search/subTypes/blobHTMLSearchType.js +122 -0
- package/src/search/subTypes/recordSearchType.js +105 -0
- package/src/search/subTypes/tupleSearchType.js +152 -0
- package/src/search/superTypes/SpecialRealNumberSearchType.js +42 -0
- package/src/search/superTypes/buffersourceSearchType.js +53 -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 +168 -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,373 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildPathLabel, buildCheckbox, readCheckbox,
|
|
3
|
+
buildLiteralRegexControls, readLiteralRegexQuery,
|
|
4
|
+
buildRangeInputsPair, readRangeInputsPair, syncRangeValidity,
|
|
5
|
+
buildTriStateSelect, readTriStateSelect,
|
|
6
|
+
buildOptInFieldset, readOptInChecked, wireOptInFieldset,
|
|
7
|
+
buildAtLeastOneSentinel, syncAtLeastOneCheck
|
|
8
|
+
} from './searchUtils.js';
|
|
9
|
+
import {combineAnd, makeRangeLeaf, makeDomShapeLeaf} from './queryTreeBuilders.js';
|
|
10
|
+
import regexpType from '../fundamentalTypes/regexpType.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Locates a built search element by the JSON-Pointer path it was built for.
|
|
14
|
+
* Compares `dataset.searchPath` in JS rather than interpolating `path` into
|
|
15
|
+
* a `querySelector` attribute-value string, since a schema path can embed
|
|
16
|
+
* arbitrary property-name characters (only `~`/`/` are escaped by
|
|
17
|
+
* `makeJSONPointer`) that would otherwise need CSS-selector escaping.
|
|
18
|
+
* @param {ParentNode} root
|
|
19
|
+
* @param {string} path
|
|
20
|
+
* @returns {HTMLElement|undefined}
|
|
21
|
+
*/
|
|
22
|
+
export function findSearchElement (root, path) {
|
|
23
|
+
return /** @type {HTMLElement[]} */ (
|
|
24
|
+
[...root.querySelectorAll('[data-search-path]')]
|
|
25
|
+
).find((el) => el.dataset.searchPath === path);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @typedef {HTMLElement & {
|
|
30
|
+
* getQuery: () => import('./queryTree.js').QueryNode|undefined
|
|
31
|
+
* }} SearchElement
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The `SearchTypeObject.getQuery` every leaf module implements identically:
|
|
36
|
+
* locate the element it built under `root` and delegate to its own
|
|
37
|
+
* (per-element, `dataset`-driven) `getQuery()` method.
|
|
38
|
+
* @param {{root: HTMLElement, path: string}} cfg
|
|
39
|
+
* @returns {import('./queryTree.js').QueryNode|undefined}
|
|
40
|
+
*/
|
|
41
|
+
export function getQueryViaElement ({root, path}) {
|
|
42
|
+
const el = /** @type {SearchElement|undefined} */ (
|
|
43
|
+
findSearchElement(root, path)
|
|
44
|
+
);
|
|
45
|
+
return el?.getQuery();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Type-predicate guard distinguishing a built search element (leaf or
|
|
50
|
+
* container, either answers to `.getQuery()`) from a plain DOM node - used
|
|
51
|
+
* by container elements (e.g. `objectSearchType.js`'s `<jsoe-search-object>`)
|
|
52
|
+
* that walk `this.children` polymorphically (search plan §8) without
|
|
53
|
+
* knowing which children are search elements and which are plain layout
|
|
54
|
+
* (a controls `<div>`, etc.).
|
|
55
|
+
* @param {Element} el
|
|
56
|
+
* @returns {el is SearchElement}
|
|
57
|
+
*/
|
|
58
|
+
export function hasGetQuery (el) {
|
|
59
|
+
return typeof (/** @type {{getQuery?: unknown}} */ (el)).getQuery ===
|
|
60
|
+
'function';
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Factory for the README's "no variants to allow for distinct search"
|
|
65
|
+
* leaves (`undefined`/`void`, `null`, `NaN`): the only meaningful question
|
|
66
|
+
* is whether the path is present at all, which only matters once the path
|
|
67
|
+
* is optional or nested in a union - so all three share one tiny, single-
|
|
68
|
+
* checkbox implementation, differing only in tag name/label. Unlike every
|
|
69
|
+
* other leaf, this one is never left for the user to configure at all: its
|
|
70
|
+
* checkbox is pre-checked and `disabled` (`buildCheckbox`'s doc), since a
|
|
71
|
+
* type with only one possible value has nothing else worth offering a
|
|
72
|
+
* choice between - it's simply valid, unconditionally, the moment it
|
|
73
|
+
* exists, rather than needing a `required`-style rule of its own.
|
|
74
|
+
* @param {{tagName: string}} cfg
|
|
75
|
+
* @returns {import('./searchDispatch.js').SearchTypeObject}
|
|
76
|
+
*/
|
|
77
|
+
export function makePresenceOnlySearchType ({tagName}) {
|
|
78
|
+
return {
|
|
79
|
+
buildUI ({schemaObject, path, typeNamespace}) {
|
|
80
|
+
const label = buildPathLabel(schemaObject, path);
|
|
81
|
+
const name = `${typeNamespace}-${tagName}`;
|
|
82
|
+
return [tagName, {
|
|
83
|
+
dataset: {searchPath: path, searchKind: tagName},
|
|
84
|
+
title: label,
|
|
85
|
+
$define: {
|
|
86
|
+
/** @this {HTMLElement} */
|
|
87
|
+
getQuery () {
|
|
88
|
+
const checked = readCheckbox(this);
|
|
89
|
+
return checked
|
|
90
|
+
? {kind: 'presence', path: this.dataset.searchPath ?? '', $exists: true}
|
|
91
|
+
: undefined;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}, [
|
|
95
|
+
['span', {class: 'searchLabel'}, [label]],
|
|
96
|
+
buildCheckbox({
|
|
97
|
+
name, label: `Require ${label} present`, checked: true, disabled: true
|
|
98
|
+
})
|
|
99
|
+
]];
|
|
100
|
+
},
|
|
101
|
+
getQuery: getQueryViaElement
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* The Error family's fixed known properties (`errorType.js`'s own
|
|
107
|
+
* `setValue`/`getValue` hard-code this same set - `message`/`name`/
|
|
108
|
+
* `fileName`/`stack` as strings, `lineNumber`/`columnNumber` as numbers -
|
|
109
|
+
* since a `checked`-type schema like `error`/`errors` carries no structural
|
|
110
|
+
* detail of its own to derive property names/types from, unlike `object`).
|
|
111
|
+
* @type {string[]}
|
|
112
|
+
*/
|
|
113
|
+
const errorStringProps = ['message', 'name', 'fileName', 'stack'];
|
|
114
|
+
|
|
115
|
+
/** @type {string[]} */
|
|
116
|
+
const errorNumberProps = ['lineNumber', 'columnNumber'];
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @param {{label: string, name: string}} cfg
|
|
120
|
+
* @returns {import('./searchUtils.js').JamilihArray[]}
|
|
121
|
+
*/
|
|
122
|
+
function buildErrorFamilyChildren ({label, name}) {
|
|
123
|
+
/** @type {import('./searchUtils.js').JamilihArray[]} */
|
|
124
|
+
const children = [['span', {class: 'searchLabel'}, [label]]];
|
|
125
|
+
errorStringProps.forEach((prop) => {
|
|
126
|
+
children.push(...buildOptInFieldset({
|
|
127
|
+
name: `${name}-${prop}`, key: prop, label: prop,
|
|
128
|
+
children: [buildLiteralRegexControls({
|
|
129
|
+
name: `${name}-${prop}`, key: prop, flagOptions: regexpType.allowedFlags
|
|
130
|
+
})]
|
|
131
|
+
}));
|
|
132
|
+
});
|
|
133
|
+
errorNumberProps.forEach((prop) => {
|
|
134
|
+
children.push(...buildOptInFieldset({
|
|
135
|
+
name: `${name}-${prop}`, key: prop, label: prop,
|
|
136
|
+
children: buildRangeInputsPair({name: `${name}-${prop}`, key: prop})
|
|
137
|
+
}));
|
|
138
|
+
});
|
|
139
|
+
children.push(buildAtLeastOneSentinel());
|
|
140
|
+
return children;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* @param {Element} root - a `jsoe-search-error`/`jsoe-search-errors-special`
|
|
145
|
+
* element
|
|
146
|
+
* @returns {void}
|
|
147
|
+
*/
|
|
148
|
+
function syncErrorFamilyValidity (root) {
|
|
149
|
+
syncAtLeastOneCheck(
|
|
150
|
+
root,
|
|
151
|
+
() => [...errorStringProps, ...errorNumberProps].some(
|
|
152
|
+
(prop) => readOptInChecked(root, prop)
|
|
153
|
+
)
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Factory for `errorSearchType.js`/`errorsSpecialSearchType.js`, offering
|
|
159
|
+
* literal/regex search of child string properties, numeric of number
|
|
160
|
+
* children (README) - one `buildLiteralRegexControls`/`buildRangeInputsPair`
|
|
161
|
+
* pair per known property (`key`-distinguished so they coexist in one
|
|
162
|
+
* widget; see those helpers' docs), each wrapped in its own
|
|
163
|
+
* `buildOptInFieldset` (so picking, say, just `message` doesn't also force
|
|
164
|
+
* `name`/`fileName`/`stack`/`lineNumber`/`columnNumber` to be filled in),
|
|
165
|
+
* combined via `$and`, with `buildAtLeastOneSentinel` requiring at least one
|
|
166
|
+
* of the six to actually be opted into. `.cause` (a recursive, arbitrarily-
|
|
167
|
+
* typed property) and `errorsSpecial`'s `AggregateError.errors` array are
|
|
168
|
+
* deliberately left out of this pass - the README's bullet asks only for
|
|
169
|
+
* the flat string/number children, and open-ended recursion into an
|
|
170
|
+
* arbitrary `cause` chain is a materially bigger feature than "the same
|
|
171
|
+
* shape, twice more".
|
|
172
|
+
* @param {{tagName: string}} cfg
|
|
173
|
+
* @returns {import('./searchDispatch.js').SearchTypeObject}
|
|
174
|
+
*/
|
|
175
|
+
export function makeErrorFamilySearchType ({tagName}) {
|
|
176
|
+
return {
|
|
177
|
+
buildUI ({schemaObject, path, typeNamespace}) {
|
|
178
|
+
const label = buildPathLabel(schemaObject, path);
|
|
179
|
+
const name = `${typeNamespace}-${tagName}`;
|
|
180
|
+
return [tagName, {
|
|
181
|
+
dataset: {searchPath: path, searchKind: tagName},
|
|
182
|
+
title: label,
|
|
183
|
+
$define: {
|
|
184
|
+
/** @this {HTMLElement} */
|
|
185
|
+
connectedCallback () {
|
|
186
|
+
errorNumberProps.forEach((prop) => syncRangeValidity(this, prop));
|
|
187
|
+
[...errorStringProps, ...errorNumberProps].forEach((prop) => (
|
|
188
|
+
wireOptInFieldset(this, prop, () => syncErrorFamilyValidity(this))
|
|
189
|
+
));
|
|
190
|
+
syncErrorFamilyValidity(this);
|
|
191
|
+
},
|
|
192
|
+
/** @this {HTMLElement} */
|
|
193
|
+
getQuery () {
|
|
194
|
+
const searchPath = this.dataset.searchPath ?? '';
|
|
195
|
+
const stringLeaves = errorStringProps.map((prop) => (
|
|
196
|
+
readOptInChecked(this, prop)
|
|
197
|
+
? readLiteralRegexQuery(this, `${searchPath}/${prop}`, prop)
|
|
198
|
+
: undefined
|
|
199
|
+
));
|
|
200
|
+
const numberLeaves = errorNumberProps.map((prop) => {
|
|
201
|
+
if (!readOptInChecked(this, prop)) {
|
|
202
|
+
return undefined;
|
|
203
|
+
}
|
|
204
|
+
const {gte, lte} = readRangeInputsPair(this, prop);
|
|
205
|
+
if (gte === '' && lte === '') {
|
|
206
|
+
return undefined;
|
|
207
|
+
}
|
|
208
|
+
return makeRangeLeaf(`${searchPath}/${prop}`, 'number', {
|
|
209
|
+
...(gte === '' ? {} : {$gte: Number(gte)}),
|
|
210
|
+
...(lte === '' ? {} : {$lte: Number(lte)})
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
return combineAnd([...stringLeaves, ...numberLeaves]);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}, buildErrorFamilyChildren({label, name})];
|
|
217
|
+
},
|
|
218
|
+
getQuery: getQueryViaElement
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* @param {{
|
|
224
|
+
* label: string, name: string, dimensionKeys: string[],
|
|
225
|
+
* includeReadonly: boolean, includeDimensionCheck: boolean
|
|
226
|
+
* }} cfg
|
|
227
|
+
* @returns {import('./searchUtils.js').JamilihArray[]}
|
|
228
|
+
*/
|
|
229
|
+
function buildDomShapeChildren ({
|
|
230
|
+
label, name, dimensionKeys, includeReadonly, includeDimensionCheck
|
|
231
|
+
}) {
|
|
232
|
+
/** @type {import('./searchUtils.js').JamilihArray[]} */
|
|
233
|
+
const children = [['span', {class: 'searchLabel'}, [label]]];
|
|
234
|
+
dimensionKeys.forEach((dim) => {
|
|
235
|
+
children.push(...buildOptInFieldset({
|
|
236
|
+
name: `${name}-${dim}`, key: dim, label: dim,
|
|
237
|
+
children: buildRangeInputsPair({name: `${name}-${dim}`, key: dim})
|
|
238
|
+
}));
|
|
239
|
+
});
|
|
240
|
+
if (includeReadonly) {
|
|
241
|
+
children.push(['label', [
|
|
242
|
+
'Readonly: ',
|
|
243
|
+
buildTriStateSelect({
|
|
244
|
+
name: `${name}-readonly`, key: 'readonly',
|
|
245
|
+
trueLabel: 'Readonly', falseLabel: 'Not readonly'
|
|
246
|
+
})
|
|
247
|
+
]]);
|
|
248
|
+
}
|
|
249
|
+
if (includeDimensionCheck) {
|
|
250
|
+
children.push(['label', [
|
|
251
|
+
'3d: ',
|
|
252
|
+
buildTriStateSelect({
|
|
253
|
+
name: `${name}-dimension`, key: 'dimension',
|
|
254
|
+
trueLabel: '3d', falseLabel: 'Not 3d'
|
|
255
|
+
})
|
|
256
|
+
]]);
|
|
257
|
+
}
|
|
258
|
+
children.push(buildAtLeastOneSentinel());
|
|
259
|
+
return children;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* @param {{
|
|
264
|
+
* root: Element, dimensionKeys: string[], includeReadonly: boolean,
|
|
265
|
+
* includeDimensionCheck: boolean
|
|
266
|
+
* }} cfg
|
|
267
|
+
* @returns {void}
|
|
268
|
+
*/
|
|
269
|
+
function syncDomShapeValidity ({root, dimensionKeys, includeReadonly, includeDimensionCheck}) {
|
|
270
|
+
syncAtLeastOneCheck(root, () => (
|
|
271
|
+
dimensionKeys.some((dim) => readOptInChecked(root, dim)) ||
|
|
272
|
+
(includeReadonly && readTriStateSelect(root, 'readonly') !== undefined) ||
|
|
273
|
+
(includeDimensionCheck && readTriStateSelect(root, 'dimension') !== undefined)
|
|
274
|
+
));
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Factory for `domrectSearchType.js`/`dompointSearchType.js`/
|
|
279
|
+
* `dommatrixSearchType.js`: numeric search ranges for children; "Is/Is not
|
|
280
|
+
* Readonly"; DOMMatrix: "Is/Is not 3d" (README) - one `buildRangeInputsPair`
|
|
281
|
+
* per known dimension (`key`-distinguished so they coexist in one widget;
|
|
282
|
+
* `dimensionKeys` covers DOMMatrix's 2D (`a`-`f`) *and* 3D (`m11`-`m44`)
|
|
283
|
+
* shapes at once rather than switching the control set on an "Is/Is not 3d"
|
|
284
|
+
* answer that's itself just another optional search constraint, not a
|
|
285
|
+
* schema fact - `domrect`/`dompoint`/`dommatrix` are all "checked" types
|
|
286
|
+
* with no structural schema to derive dimension names from in the first
|
|
287
|
+
* place, same reasoning as `makeErrorFamilySearchType`), combined into one
|
|
288
|
+
* `domShape` leaf (`queryTree.js`) rather than separate leaves via `$and`.
|
|
289
|
+
* @param {{
|
|
290
|
+
* tagName: string,
|
|
291
|
+
* dimensionKeys: string[],
|
|
292
|
+
* includeReadonly?: boolean,
|
|
293
|
+
* includeDimensionCheck?: boolean
|
|
294
|
+
* }} cfg
|
|
295
|
+
* @returns {import('./searchDispatch.js').SearchTypeObject}
|
|
296
|
+
*/
|
|
297
|
+
export function makeDomShapeSearchType ({
|
|
298
|
+
tagName, dimensionKeys, includeReadonly = false, includeDimensionCheck = false
|
|
299
|
+
}) {
|
|
300
|
+
return {
|
|
301
|
+
buildUI ({schemaObject, path, typeNamespace}) {
|
|
302
|
+
const label = buildPathLabel(schemaObject, path);
|
|
303
|
+
const name = `${typeNamespace}-${tagName}`;
|
|
304
|
+
return [tagName, {
|
|
305
|
+
dataset: {searchPath: path, searchKind: tagName},
|
|
306
|
+
title: label,
|
|
307
|
+
$define: {
|
|
308
|
+
/** @this {HTMLElement} */
|
|
309
|
+
connectedCallback () {
|
|
310
|
+
const syncValidity = () => syncDomShapeValidity({
|
|
311
|
+
root: this, dimensionKeys, includeReadonly, includeDimensionCheck
|
|
312
|
+
});
|
|
313
|
+
dimensionKeys.forEach((dim) => {
|
|
314
|
+
syncRangeValidity(this, dim);
|
|
315
|
+
wireOptInFieldset(this, dim, syncValidity);
|
|
316
|
+
});
|
|
317
|
+
if (includeReadonly) {
|
|
318
|
+
this.querySelector('select.jsoeSearchTriState--readonly')?.addEventListener(
|
|
319
|
+
'change', syncValidity
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
if (includeDimensionCheck) {
|
|
323
|
+
this.querySelector('select.jsoeSearchTriState--dimension')?.addEventListener(
|
|
324
|
+
'change', syncValidity
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
syncValidity();
|
|
328
|
+
},
|
|
329
|
+
/** @this {HTMLElement} */
|
|
330
|
+
getQuery () {
|
|
331
|
+
const searchPath = this.dataset.searchPath ?? '';
|
|
332
|
+
/** @type {{[dim: string]: import('./queryTree.js').QueryRangeLeaf}} */
|
|
333
|
+
const dimensions = {};
|
|
334
|
+
dimensionKeys.forEach((dim) => {
|
|
335
|
+
if (!readOptInChecked(this, dim)) {
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
const {gte, lte} = readRangeInputsPair(this, dim);
|
|
339
|
+
if (gte === '' && lte === '') {
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
dimensions[dim] = makeRangeLeaf(`${searchPath}/${dim}`, 'number', {
|
|
343
|
+
...(gte === '' ? {} : {$gte: Number(gte)}),
|
|
344
|
+
...(lte === '' ? {} : {$lte: Number(lte)})
|
|
345
|
+
});
|
|
346
|
+
});
|
|
347
|
+
const readonlyCheck = includeReadonly
|
|
348
|
+
? readTriStateSelect(this, 'readonly')
|
|
349
|
+
: undefined;
|
|
350
|
+
const dimensionCheck = includeDimensionCheck
|
|
351
|
+
? readTriStateSelect(this, 'dimension')
|
|
352
|
+
: undefined;
|
|
353
|
+
if (
|
|
354
|
+
readonlyCheck === undefined && dimensionCheck === undefined &&
|
|
355
|
+
Object.keys(dimensions).length === 0
|
|
356
|
+
) {
|
|
357
|
+
return undefined;
|
|
358
|
+
}
|
|
359
|
+
return makeDomShapeLeaf(searchPath, dimensions, {
|
|
360
|
+
...(readonlyCheck === undefined ? {} : {readonlyCheck}),
|
|
361
|
+
...(dimensionCheck === undefined
|
|
362
|
+
? {}
|
|
363
|
+
: {dimensionCheck: dimensionCheck ? 3 : 2})
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}, buildDomShapeChildren({
|
|
368
|
+
label, name, dimensionKeys, includeReadonly, includeDimensionCheck
|
|
369
|
+
})];
|
|
370
|
+
},
|
|
371
|
+
getQuery: getQueryViaElement
|
|
372
|
+
};
|
|
373
|
+
}
|