@es-joy/jsoe 0.29.0 → 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.
Files changed (85) hide show
  1. package/.claude/scheduled_tasks.lock +1 -0
  2. package/CHANGES.md +6 -0
  3. package/README.md +2 -0
  4. package/dist/fundamentalTypes/dateType.d.ts +8 -3
  5. package/dist/fundamentalTypes/dateType.d.ts.map +1 -1
  6. package/dist/index.js +2 -2
  7. package/dist/index.js.map +1 -1
  8. package/dist/search/fundamentalTypes/arraySearchType.d.ts +11 -4
  9. package/dist/search/fundamentalTypes/arraySearchType.d.ts.map +1 -1
  10. package/dist/search/fundamentalTypes/bigintSearchType.d.ts.map +1 -1
  11. package/dist/search/fundamentalTypes/blobSearchType.d.ts.map +1 -1
  12. package/dist/search/fundamentalTypes/dateSearchType.d.ts +8 -3
  13. package/dist/search/fundamentalTypes/dateSearchType.d.ts.map +1 -1
  14. package/dist/search/fundamentalTypes/domexceptionSearchType.d.ts +5 -5
  15. package/dist/search/fundamentalTypes/domexceptionSearchType.d.ts.map +1 -1
  16. package/dist/search/fundamentalTypes/enumSearchType.d.ts +4 -0
  17. package/dist/search/fundamentalTypes/enumSearchType.d.ts.map +1 -1
  18. package/dist/search/fundamentalTypes/fileSearchType.d.ts +19 -10
  19. package/dist/search/fundamentalTypes/fileSearchType.d.ts.map +1 -1
  20. package/dist/search/fundamentalTypes/filelistSearchType.d.ts +4 -12
  21. package/dist/search/fundamentalTypes/filelistSearchType.d.ts.map +1 -1
  22. package/dist/search/fundamentalTypes/functionSearchType.d.ts +4 -4
  23. package/dist/search/fundamentalTypes/functionSearchType.d.ts.map +1 -1
  24. package/dist/search/fundamentalTypes/mapSearchType.d.ts +8 -4
  25. package/dist/search/fundamentalTypes/mapSearchType.d.ts.map +1 -1
  26. package/dist/search/fundamentalTypes/numberSearchType.d.ts.map +1 -1
  27. package/dist/search/fundamentalTypes/objectSearchType.d.ts +10 -4
  28. package/dist/search/fundamentalTypes/objectSearchType.d.ts.map +1 -1
  29. package/dist/search/fundamentalTypes/regexpSearchType.d.ts +7 -1
  30. package/dist/search/fundamentalTypes/regexpSearchType.d.ts.map +1 -1
  31. package/dist/search/fundamentalTypes/setSearchType.d.ts +5 -4
  32. package/dist/search/fundamentalTypes/setSearchType.d.ts.map +1 -1
  33. package/dist/search/fundamentalTypes/stringSearchType.d.ts +9 -1
  34. package/dist/search/fundamentalTypes/stringSearchType.d.ts.map +1 -1
  35. package/dist/search/fundamentalTypes/symbolSearchType.d.ts.map +1 -1
  36. package/dist/search/index.d.ts +18 -8
  37. package/dist/search/index.d.ts.map +1 -1
  38. package/dist/search/queryTree.d.ts +12 -1
  39. package/dist/search/queryTree.d.ts.map +1 -1
  40. package/dist/search/queryTreeBuilders.d.ts +6 -0
  41. package/dist/search/queryTreeBuilders.d.ts.map +1 -1
  42. package/dist/search/searchElementUtils.d.ts +17 -8
  43. package/dist/search/searchElementUtils.d.ts.map +1 -1
  44. package/dist/search/searchUtils.d.ts +343 -18
  45. package/dist/search/searchUtils.d.ts.map +1 -1
  46. package/dist/search/subTypes/blobHTMLSearchType.d.ts +22 -2
  47. package/dist/search/subTypes/blobHTMLSearchType.d.ts.map +1 -1
  48. package/dist/search/subTypes/recordSearchType.d.ts +4 -4
  49. package/dist/search/subTypes/recordSearchType.d.ts.map +1 -1
  50. package/dist/search/subTypes/tupleSearchType.d.ts +3 -3
  51. package/dist/search/subTypes/tupleSearchType.d.ts.map +1 -1
  52. package/dist/search/superTypes/buffersourceSearchType.d.ts.map +1 -1
  53. package/dist/search/unions/unionFamilySearchType.d.ts.map +1 -1
  54. package/package.json +1 -1
  55. package/src/fundamentalTypes/dateType.js +9 -4
  56. package/src/fundamentalTypes/regexpType.js +1 -1
  57. package/src/jsoe.css +204 -0
  58. package/src/search/fundamentalTypes/arraySearchType.js +42 -7
  59. package/src/search/fundamentalTypes/bigintSearchType.js +7 -1
  60. package/src/search/fundamentalTypes/blobSearchType.js +2 -1
  61. package/src/search/fundamentalTypes/booleanSearchType.js +1 -1
  62. package/src/search/fundamentalTypes/dateSearchType.js +113 -20
  63. package/src/search/fundamentalTypes/domexceptionSearchType.js +39 -10
  64. package/src/search/fundamentalTypes/enumSearchType.js +5 -1
  65. package/src/search/fundamentalTypes/fileSearchType.js +64 -11
  66. package/src/search/fundamentalTypes/filelistSearchType.js +32 -7
  67. package/src/search/fundamentalTypes/functionSearchType.js +36 -12
  68. package/src/search/fundamentalTypes/mapSearchType.js +43 -13
  69. package/src/search/fundamentalTypes/numberSearchType.js +8 -1
  70. package/src/search/fundamentalTypes/objectSearchType.js +236 -17
  71. package/src/search/fundamentalTypes/regexpSearchType.js +29 -5
  72. package/src/search/fundamentalTypes/setSearchType.js +33 -7
  73. package/src/search/fundamentalTypes/stringSearchType.js +11 -2
  74. package/src/search/fundamentalTypes/symbolSearchType.js +2 -1
  75. package/src/search/index.js +26 -9
  76. package/src/search/queryTree.js +10 -1
  77. package/src/search/queryTreeBuilders.js +9 -0
  78. package/src/search/searchElementUtils.js +108 -24
  79. package/src/search/searchUtils.js +516 -24
  80. package/src/search/subTypes/blobHTMLSearchType.js +64 -7
  81. package/src/search/subTypes/recordSearchType.js +34 -13
  82. package/src/search/subTypes/tupleSearchType.js +51 -10
  83. package/src/search/superTypes/SpecialRealNumberSearchType.js +1 -1
  84. package/src/search/superTypes/buffersourceSearchType.js +7 -1
  85. package/src/search/unions/unionFamilySearchType.js +8 -0
@@ -1,10 +1,13 @@
1
1
  import {
2
2
  buildPathLabel, buildCheckbox, readCheckbox,
3
3
  buildLiteralRegexControls, readLiteralRegexQuery,
4
- buildRangeInputsPair, readRangeInputsPair,
5
- buildTriStateSelect, readTriStateSelect
4
+ buildRangeInputsPair, readRangeInputsPair, syncRangeValidity,
5
+ buildTriStateSelect, readTriStateSelect,
6
+ buildOptInFieldset, readOptInChecked, wireOptInFieldset,
7
+ buildAtLeastOneSentinel, syncAtLeastOneCheck
6
8
  } from './searchUtils.js';
7
9
  import {combineAnd, makeRangeLeaf, makeDomShapeLeaf} from './queryTreeBuilders.js';
10
+ import regexpType from '../fundamentalTypes/regexpType.js';
8
11
 
9
12
  /**
10
13
  * Locates a built search element by the JSON-Pointer path it was built for.
@@ -62,7 +65,12 @@ export function hasGetQuery (el) {
62
65
  * leaves (`undefined`/`void`, `null`, `NaN`): the only meaningful question
63
66
  * is whether the path is present at all, which only matters once the path
64
67
  * is optional or nested in a union - so all three share one tiny, single-
65
- * checkbox implementation, differing only in tag name/label.
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.
66
74
  * @param {{tagName: string}} cfg
67
75
  * @returns {import('./searchDispatch.js').SearchTypeObject}
68
76
  */
@@ -85,7 +93,9 @@ export function makePresenceOnlySearchType ({tagName}) {
85
93
  }
86
94
  }, [
87
95
  ['span', {class: 'searchLabel'}, [label]],
88
- buildCheckbox({name, label: `Require ${label} present`})
96
+ buildCheckbox({
97
+ name, label: `Require ${label} present`, checked: true, disabled: true
98
+ })
89
99
  ]];
90
100
  },
91
101
  getQuery: getQueryViaElement
@@ -113,30 +123,51 @@ function buildErrorFamilyChildren ({label, name}) {
113
123
  /** @type {import('./searchUtils.js').JamilihArray[]} */
114
124
  const children = [['span', {class: 'searchLabel'}, [label]]];
115
125
  errorStringProps.forEach((prop) => {
116
- children.push(['div', {class: `errorProp-${prop}`}, [
117
- ['span', [`${prop}: `]],
118
- buildLiteralRegexControls({name: `${name}-${prop}`, key: prop})
119
- ]]);
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
+ }));
120
132
  });
121
133
  errorNumberProps.forEach((prop) => {
122
- children.push(['div', {class: `errorProp-${prop}`}, [
123
- ['span', [`${prop}: `]],
124
- ...buildRangeInputsPair({name: `${name}-${prop}`, key: prop})
125
- ]]);
134
+ children.push(...buildOptInFieldset({
135
+ name: `${name}-${prop}`, key: prop, label: prop,
136
+ children: buildRangeInputsPair({name: `${name}-${prop}`, key: prop})
137
+ }));
126
138
  });
139
+ children.push(buildAtLeastOneSentinel());
127
140
  return children;
128
141
  }
129
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
+
130
157
  /**
131
158
  * Factory for `errorSearchType.js`/`errorsSpecialSearchType.js`, offering
132
159
  * literal/regex search of child string properties, numeric of number
133
- * children (README) - one `buildLiteralRegexControls`/`buildRangeInputsPair` pair
134
- * per known property (`key`-distinguished so they coexist in one widget;
135
- * see those helpers' docs), combined via `$and`. `.cause` (a recursive,
136
- * arbitrarily-typed property) and `errorsSpecial`'s `AggregateError.errors`
137
- * array are deliberately left out of this pass - the README's bullet asks
138
- * only for the flat string/number children, and open-ended recursion into
139
- * an arbitrary `cause` chain is a materially bigger feature than "the same
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
140
171
  * shape, twice more".
141
172
  * @param {{tagName: string}} cfg
142
173
  * @returns {import('./searchDispatch.js').SearchTypeObject}
@@ -150,13 +181,26 @@ export function makeErrorFamilySearchType ({tagName}) {
150
181
  dataset: {searchPath: path, searchKind: tagName},
151
182
  title: label,
152
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
+ },
153
192
  /** @this {HTMLElement} */
154
193
  getQuery () {
155
194
  const searchPath = this.dataset.searchPath ?? '';
156
195
  const stringLeaves = errorStringProps.map((prop) => (
157
- readLiteralRegexQuery(this, `${searchPath}/${prop}`, prop)
196
+ readOptInChecked(this, prop)
197
+ ? readLiteralRegexQuery(this, `${searchPath}/${prop}`, prop)
198
+ : undefined
158
199
  ));
159
200
  const numberLeaves = errorNumberProps.map((prop) => {
201
+ if (!readOptInChecked(this, prop)) {
202
+ return undefined;
203
+ }
160
204
  const {gte, lte} = readRangeInputsPair(this, prop);
161
205
  if (gte === '' && lte === '') {
162
206
  return undefined;
@@ -188,10 +232,10 @@ function buildDomShapeChildren ({
188
232
  /** @type {import('./searchUtils.js').JamilihArray[]} */
189
233
  const children = [['span', {class: 'searchLabel'}, [label]]];
190
234
  dimensionKeys.forEach((dim) => {
191
- children.push(['div', {class: `domShapeDimension-${dim}`}, [
192
- ['span', [`${dim}: `]],
193
- ...buildRangeInputsPair({name: `${name}-${dim}`, key: dim})
194
- ]]);
235
+ children.push(...buildOptInFieldset({
236
+ name: `${name}-${dim}`, key: dim, label: dim,
237
+ children: buildRangeInputsPair({name: `${name}-${dim}`, key: dim})
238
+ }));
195
239
  });
196
240
  if (includeReadonly) {
197
241
  children.push(['label', [
@@ -211,9 +255,25 @@ function buildDomShapeChildren ({
211
255
  })
212
256
  ]]);
213
257
  }
258
+ children.push(buildAtLeastOneSentinel());
214
259
  return children;
215
260
  }
216
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
+
217
277
  /**
218
278
  * Factory for `domrectSearchType.js`/`dompointSearchType.js`/
219
279
  * `dommatrixSearchType.js`: numeric search ranges for children; "Is/Is not
@@ -245,12 +305,36 @@ export function makeDomShapeSearchType ({
245
305
  dataset: {searchPath: path, searchKind: tagName},
246
306
  title: label,
247
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
+ },
248
329
  /** @this {HTMLElement} */
249
330
  getQuery () {
250
331
  const searchPath = this.dataset.searchPath ?? '';
251
332
  /** @type {{[dim: string]: import('./queryTree.js').QueryRangeLeaf}} */
252
333
  const dimensions = {};
253
334
  dimensionKeys.forEach((dim) => {
335
+ if (!readOptInChecked(this, dim)) {
336
+ return;
337
+ }
254
338
  const {gte, lte} = readRangeInputsPair(this, dim);
255
339
  if (gte === '' && lte === '') {
256
340
  return;