assign-gingerly 0.0.53 → 0.0.55

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 (114) hide show
  1. package/README.md +847 -5
  2. package/assignFrom.js +229 -9
  3. package/assignFrom.ts +338 -9
  4. package/assignGingerly.js +34 -1
  5. package/assignGingerly.ts +54 -1
  6. package/beVigilant.js +73 -0
  7. package/beVigilant.ts +85 -0
  8. package/enhanceAll.js +106 -0
  9. package/enhanceAll.ts +138 -0
  10. package/handlers/join.js +74 -0
  11. package/handlers/join.ts +80 -0
  12. package/handlers/lazyLoad.js +212 -0
  13. package/handlers/lazyLoad.ts +307 -0
  14. package/handlers/lazyLoadSwitch.js +58 -0
  15. package/handlers/lazyLoadSwitch.ts +63 -0
  16. package/handlers/microDataJoin.js +184 -0
  17. package/handlers/microDataJoin.ts +270 -0
  18. package/inferencer/.gitmodules +3 -0
  19. package/inferencer/.vscode/settings.json +2 -0
  20. package/inferencer/InferencedPropagator.js +230 -0
  21. package/inferencer/InferencedPropagator.ts +269 -0
  22. package/inferencer/LICENSE +21 -0
  23. package/inferencer/README.md +524 -0
  24. package/inferencer/Requirements/SupportForPropagator.md +368 -0
  25. package/inferencer/imports.html +7 -0
  26. package/inferencer/inferencer.js +254 -0
  27. package/inferencer/inferencer.ts +292 -0
  28. package/inferencer/package-lock.json +129 -0
  29. package/inferencer/package.json +60 -0
  30. package/inferencer/playwright-report/data/507ad515125e13390ea07de92f22331c913fa068.md +55 -0
  31. package/inferencer/playwright-report/index.html +90 -0
  32. package/inferencer/playwright.config.ts +54 -0
  33. package/inferencer/test-results/.last-run.json +6 -0
  34. package/inferencer/test-results/inferencer-Inferencer-Enha-535bc-inferencer-tests-in-browser-chromium/error-context.md +55 -0
  35. package/inferencer/tests/inferencedPropagator.html +428 -0
  36. package/inferencer/tests/inferencedPropagator.spec.ts +18 -0
  37. package/inferencer/tests/inferencer.html +355 -0
  38. package/inferencer/tests/inferencer.spec.ts +19 -0
  39. package/inferencer/tsconfig.json +19 -0
  40. package/inferencer/types/.kiro/specs/conversion-template/README.md +128 -0
  41. package/inferencer/types/.kiro/specs/conversion-template/design.md +360 -0
  42. package/inferencer/types/.kiro/specs/conversion-template/requirements.md +191 -0
  43. package/inferencer/types/.kiro/specs/conversion-template/tasks.md +174 -0
  44. package/inferencer/types/.kiro/steering/coding-standards.md +53 -0
  45. package/inferencer/types/.kiro/steering/conversion-guide.md +108 -0
  46. package/inferencer/types/.kiro/steering/declarative-configuration.md +108 -0
  47. package/inferencer/types/.kiro/steering/emc-json-serializability.md +306 -0
  48. package/inferencer/types/EnhancementConversionInstructions.md +1854 -0
  49. package/inferencer/types/LICENSE +21 -0
  50. package/inferencer/types/NewCustomElement.md +388 -0
  51. package/inferencer/types/NewCustomElementFeature.md +683 -0
  52. package/inferencer/types/NewEnhancementInstructions.md +705 -0
  53. package/inferencer/types/README.md +2 -0
  54. package/inferencer/types/agrace/types.d.ts +11 -0
  55. package/inferencer/types/assign-gingerly/types.d.ts +572 -0
  56. package/inferencer/types/be-a-beacon/types.d.ts +17 -0
  57. package/inferencer/types/be-bound/types.d.ts +66 -0
  58. package/inferencer/types/be-buttoned-up/types.d.ts +19 -0
  59. package/inferencer/types/be-calculating/types.d.ts +54 -0
  60. package/inferencer/types/be-clonable/types.d.ts +38 -0
  61. package/inferencer/types/be-committed/types.d.ts +22 -0
  62. package/inferencer/types/be-consoling/types.d.ts +24 -0
  63. package/inferencer/types/be-decked-with/types.d.ts +26 -0
  64. package/inferencer/types/be-delible/types.d.ts +27 -0
  65. package/inferencer/types/be-dispatching/types.d.ts +34 -0
  66. package/inferencer/types/be-evanescent/types.d.ts +20 -0
  67. package/inferencer/types/be-flashy/types.d.ts +21 -0
  68. package/inferencer/types/be-gone/types.d.ts +25 -0
  69. package/inferencer/types/be-observing/types.d.ts +55 -0
  70. package/inferencer/types/be-reflective/types.d.ts +78 -0
  71. package/inferencer/types/be-reformable/types.d.ts +49 -0
  72. package/inferencer/types/be-render-neutral/types.d.ts +32 -0
  73. package/inferencer/types/be-switched/types.d.ts +146 -0
  74. package/inferencer/types/be-typed/types.d.ts +32 -0
  75. package/inferencer/types/be-valued/types.d.ts +22 -0
  76. package/inferencer/types/data-props/types.d.ts +34 -0
  77. package/inferencer/types/do-inc/types.d.ts +56 -0
  78. package/inferencer/types/do-invoke/types.d.ts +38 -0
  79. package/inferencer/types/do-merge/types.d.ts +28 -0
  80. package/inferencer/types/do-toggle/types.d.ts +31 -0
  81. package/inferencer/types/face-up/types.d.ts +100 -0
  82. package/inferencer/types/fetch-for/types.d.ts +36 -0
  83. package/inferencer/types/folder-picker/types.d.ts +21 -0
  84. package/inferencer/types/global.d.ts +29 -0
  85. package/inferencer/types/id-generation/types.d.ts +26 -0
  86. package/inferencer/types/inferencer/types.d.ts +46 -0
  87. package/inferencer/types/mount-observer/types.d.ts +363 -0
  88. package/inferencer/types/nested-regex-groups/types.d.ts +107 -0
  89. package/inferencer/types/pipe-in/types.d.ts +52 -0
  90. package/inferencer/types/roundabout/types.d.ts +268 -0
  91. package/inferencer/types/soak-up/types.d.ts +40 -0
  92. package/inferencer/types/templ-maker/types.d.ts +43 -0
  93. package/inferencer/types/time-ticker/types.d.ts +62 -0
  94. package/inferencer/types/truth-sourcer/types.d.ts +44 -0
  95. package/inferencer/upSearch.js +27 -0
  96. package/inferencer/upSearch.ts +26 -0
  97. package/inferencer/withScopePerimeter.js +27 -0
  98. package/inferencer/withScopePerimeter.ts +33 -0
  99. package/inferredAssignments.js +38 -0
  100. package/inferredAssignments.ts +65 -0
  101. package/isAllowedImportPath.js +42 -0
  102. package/isAllowedImportPath.ts +53 -0
  103. package/package.json +57 -3
  104. package/paths.js +231 -0
  105. package/paths.ts +413 -0
  106. package/processHandlerCommands.js +188 -0
  107. package/processHandlerCommands.ts +217 -0
  108. package/resolveIdRef.js +144 -0
  109. package/resolveIdRef.ts +170 -0
  110. package/resolveValues.js +41 -2
  111. package/resolveValues.ts +41 -1
  112. package/transitionHelper.js +109 -0
  113. package/transitionHelper.ts +132 -0
  114. package/types/assign-gingerly/types.d.ts +89 -0
@@ -0,0 +1,524 @@
1
+ # inferencer
2
+
3
+ DOM Element Enhancement that makes commonly used inferences for value, display, and event type properties.
4
+
5
+ [![NPM version](https://badge.fury.io/js/inferencer.png)](http://badge.fury.io/js/inferencer)
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install inferencer assign-gingerly
11
+ ```
12
+
13
+ ## Overview
14
+
15
+ The `inferencer` enhancement provides an attribute-less [element enhancement](https://github.com/bahrus/assign-gingerly#object-and-element-enhancements-via-assign-gingerly) API for smart value and display property assignment. Instead of manually determining which property to set on different element types (e.g., `value` for inputs, `checked` for checkboxes, `textContent` for divs), *inferencer* automatically infers the correct property based on the element type.
16
+
17
+ ### Why inferencer?
18
+
19
+ Different HTML elements use different properties to represent their value:
20
+ - Input text fields use `value`
21
+ - Checkboxes and radio buttons use `checked`
22
+ - Time elements use `dateTime`
23
+ - Divs and spans use `textContent`
24
+ - Progress and meter elements use `value` but display with `ariaValueText`
25
+
26
+ The inferencer enhancement eliminates the need to remember these differences by providing symbols that automatically map to the correct property:
27
+
28
+ - `value` symbol - Sets the element's data value
29
+ - `display` symbol - Sets the element's display/presentation value
30
+ - `eventType` getter - Returns the most appropriate event type for the element
31
+
32
+ ## Basic Usage
33
+
34
+ ```TypeScript
35
+ import { value, display, registryItem } from 'inferencer/inferencer.js';
36
+ import 'assign-gingerly/object-extension.js';
37
+
38
+ // Use the value symbol - automatically sets the right property
39
+ const input = document.createElement('input');
40
+ input.type = 'text';
41
+ input.set[value] = 'hello';
42
+ console.log(input.value); // 'hello'
43
+
44
+ // alternatively:
45
+
46
+ const inputInference = input.enh.get(registryItem);
47
+ inputInference.value = 'goodbye';
48
+
49
+ console.log(input.value); // 'goodbye'
50
+
51
+ const checkbox = document.createElement('input');
52
+ checkbox.type = 'checkbox';
53
+ checkbox.set[value] = true;
54
+ console.log(checkbox.checked); // true
55
+
56
+ const div = document.createElement('div');
57
+ div.set[value] = 'content';
58
+ console.log(div.textContent); // 'content'
59
+
60
+ const time = document.createElement('time');
61
+ time.set[value] = '2024-01-01T00:00:00Z';
62
+ console.log(time.dateTime); // '2024-01-01T00:00:00Z'
63
+ ```
64
+
65
+ ## Value Property Inference
66
+
67
+ The `value` symbol automatically maps to the most appropriate property for each element type:
68
+
69
+ | Element Type | Property Set | Example |
70
+ |-------------|-------------|---------|
71
+ | `<input type="text">` | `value` | Text input value |
72
+ | `<input type="checkbox">` | `checked` | Checkbox state |
73
+ | `<input type="radio">` | `checked` | Radio button state |
74
+ | `<textarea>` | `value` | Textarea content |
75
+ | `<select>` | `value` | Selected option |
76
+ | `<time>` | `dateTime` | ISO datetime string |
77
+ | `<data>` | `value` | Machine-readable value |
78
+ | `<meter>` | `value` | Numeric value |
79
+ | `<progress>` | `value` | Progress value |
80
+ | `<output>` | `value` | Output value |
81
+ | Elements with `itemprop` | `itemprop` value | Custom property name |
82
+ | Other elements | `textContent` | Text content |
83
+
84
+ ## Display Property Inference
85
+
86
+ The `display` symbol sets the human-readable display value:
87
+
88
+ ```TypeScript
89
+ // Time element - display formatted time
90
+ const time = document.createElement('time');
91
+ time.set[value] = '2024-01-01T00:00:00Z'; // Machine-readable
92
+ time.set[display] = 'January 1, 2024'; // Human-readable
93
+ console.log(time.dateTime); // '2024-01-01T00:00:00Z'
94
+ console.log(time.textContent); // 'January 1, 2024'
95
+
96
+ // Meter element - display with ARIA
97
+ const meter = document.createElement('meter');
98
+ meter.min = 0;
99
+ meter.max = 100;
100
+ meter.set[value] = 75; // Numeric value
101
+ meter.set[display] = '75 percent'; // Screen reader text
102
+ console.log(meter.value); // 75
103
+ console.log(meter.ariaValueText); // '75 percent'
104
+ ```
105
+
106
+ | Element Type | Property Set | Example |
107
+ |-------------|-------------|---------|
108
+ | `<input>`, `<textarea>`, `<select>` | `value` | Form control value |
109
+ | `<time>` | `textContent` | Formatted time string |
110
+ | `<data>` | `textContent` | Human-readable content |
111
+ | `<meter>`, `<progress>` | `ariaValueText` | Screen reader text |
112
+ | Other elements | `textContent` | Text content |
113
+
114
+ ## Event Type Inference
115
+
116
+ The `inferEventType` function returns the most appropriate event type for different element types:
117
+
118
+ ```TypeScript
119
+ import { inferEventType } from 'inferencer';
120
+
121
+ const input = document.createElement('input');
122
+ console.log(inferEventType(input)); // 'input'
123
+
124
+ const form = document.createElement('form');
125
+ console.log(inferEventType(form)); // 'submit'
126
+
127
+ const button = document.createElement('button');
128
+ console.log(inferEventType(button)); // 'click'
129
+ ```
130
+
131
+ | Element Type | Event Type | Use Case |
132
+ |-------------|-----------|----------|
133
+ | `<input>`, `<textarea>`, `<select>` | `input` | Form control value changes |
134
+ | `<form>` | `submit` | Form submission |
135
+ | `<details>` | `toggle` | Details element open/close |
136
+ | `<dialog>` | `close` | Dialog dismissal |
137
+ | Other elements | `click` | Default interactive event |
138
+
139
+ **Accessing via Enhancement Instance:**
140
+
141
+ ```TypeScript
142
+ const input = document.createElement('input');
143
+ input.set[value] = 'test';
144
+
145
+ console.log(input.enh.infer.eventType); // 'input'
146
+
147
+ const form = document.createElement('form');
148
+ form.set[value] = 'test';
149
+
150
+ console.log(form.enh.infer.eventType); // 'submit'
151
+ ```
152
+
153
+ This is particularly useful when building enhancements that need to attach event listeners but don't know the element type in advance.
154
+
155
+ ## Propagator Support
156
+
157
+ The inferencer provides a `getPropagator()` method that returns an `EventTarget` which emits events when element properties change. This solves a common challenge: subscribing to property changes across different element types, whether the change is user-driven or programmatic.
158
+
159
+ ### Basic Usage
160
+
161
+ ```TypeScript
162
+ import { Infer } from 'inferencer/inferencer.js';
163
+
164
+ const input = document.createElement('input');
165
+ const infer = new Infer(input);
166
+ const propagator = await infer.getPropagator();
167
+
168
+ // Listen for value changes — works for both user input and programmatic sets
169
+ propagator.addEventListener('value', () => {
170
+ console.log('value changed to:', input.value);
171
+ });
172
+
173
+ input.value = 'programmatic change'; // fires the listener
174
+ ```
175
+
176
+ The event name matches the property name being observed. Observation is lazy — wiring only happens for properties you actually subscribe to.
177
+
178
+ ### How It Works
179
+
180
+ For **custom elements with a [roundabout](https://github.com/bahrus/roundabout) propagator**, `getPropagator()` returns the element's native propagator directly — no inference needed.
181
+
182
+ For all other elements, it creates an `InferencedPropagator` that uses the best available strategy to detect changes:
183
+
184
+ | Strategy | When Used | Mechanism |
185
+ |----------|-----------|-----------|
186
+ | Attribute observation | Properties that reflect to attributes (aria-*, href, src) | MutationObserver |
187
+ | Hybrid event + setter | Form controls (input, textarea, select) | Native event + setter interception |
188
+ | Setter interception | Custom elements with prototype setters | Instance property override |
189
+ | Polling | Everything else (last resort) | requestAnimationFrame dirty check |
190
+
191
+ ### Attribute-Reflected Properties
192
+
193
+ Properties like `ariaLabel`, `href`, and `src` that reflect to DOM attributes are observed via MutationObserver:
194
+
195
+ ```TypeScript
196
+ const anchor = document.createElement('a');
197
+ const infer = new Infer(anchor);
198
+ const propagator = await infer.getPropagator();
199
+
200
+ propagator.addEventListener('href', () => {
201
+ console.log('href changed to:', anchor.href);
202
+ });
203
+
204
+ anchor.href = 'https://example.com'; // fires the listener
205
+ ```
206
+
207
+ ### Form Controls (Hybrid Strategy)
208
+
209
+ For `<input>`, `<textarea>`, and `<select>`, changes can come from user interaction (which fires native events) or programmatic assignment (which doesn't). The propagator handles both:
210
+
211
+ ```TypeScript
212
+ const input = document.createElement('input');
213
+ const infer = new Infer(input);
214
+ const propagator = await infer.getPropagator();
215
+
216
+ propagator.addEventListener('value', () => {
217
+ console.log('value is now:', input.value);
218
+ });
219
+
220
+ // User types → native 'input' event → propagator fires
221
+ // Programmatic: input.value = 'hello' → setter intercept → propagator fires
222
+ ```
223
+
224
+ ### Custom Elements
225
+
226
+ For custom elements with standard getters/setters on the prototype, setter interception catches all programmatic changes:
227
+
228
+ ```TypeScript
229
+ class MyCounter extends HTMLElement {
230
+ #count = 0;
231
+ get count() { return this.#count; }
232
+ set count(v) { this.#count = v; }
233
+ }
234
+ customElements.define('my-counter', MyCounter);
235
+
236
+ const el = document.createElement('my-counter');
237
+ const infer = new Infer(el);
238
+ const propagator = await infer.getPropagator();
239
+
240
+ propagator.addEventListener('count', () => {
241
+ console.log('count changed to:', el.count);
242
+ });
243
+
244
+ el.count = 5; // fires the listener
245
+ ```
246
+
247
+ ### Roundabout Elements
248
+
249
+ Custom elements that implement a [roundabout property](https://github.com/bahrus/roundabout) already have a native propagator. `getPropagator()` detects this and returns it directly:
250
+
251
+ ```TypeScript
252
+ // Element with native propagator — no inference needed
253
+ const el = document.createElement('my-roundabout-element');
254
+ const infer = new Infer(el);
255
+ const propagator = await infer.getPropagator();
256
+
257
+ // This IS the element's own propagator, not an inferred one
258
+ propagator.addEventListener('someProperty', handler);
259
+ ```
260
+
261
+ ### Cleanup
262
+
263
+ Call `destroy()` to tear down all watchers when you're done:
264
+
265
+ ```TypeScript
266
+ const propagator = await infer.getPropagator();
267
+ propagator.addEventListener('value', handler);
268
+
269
+ // Later, when no longer needed:
270
+ propagator.destroy();
271
+ ```
272
+
273
+ ### Using InferencedPropagator Directly
274
+
275
+ You can also import and use `InferencedPropagator` directly if you already have an `Infer` instance:
276
+
277
+ ```TypeScript
278
+ import { InferencedPropagator } from 'inferencer/InferencedPropagator.js';
279
+ import { Infer } from 'inferencer/inferencer.js';
280
+
281
+ const element = document.createElement('input');
282
+ const infer = new Infer(element);
283
+ const propagator = new InferencedPropagator(infer);
284
+
285
+ propagator.addEventListener('value', () => {
286
+ console.log('changed:', element.value);
287
+ });
288
+ ```
289
+
290
+ ## Accessing the Enhancement Instance
291
+
292
+ The inferencer enhancement is accessible via `element.enh.infer`:
293
+
294
+ ```TypeScript
295
+ const input = document.createElement('input');
296
+ input.set[value] = 'test';
297
+
298
+ // Access the enhancement instance
299
+ console.log(input.enh.infer.value); // 'test' (cached value)
300
+
301
+ // The instance maintains references to both value and display
302
+ input.set[display] = 'Test Display';
303
+ console.log(input.enh.infer.value); // 'test'
304
+ console.log(input.enh.infer.display); // 'Test Display'
305
+ console.log(input.enh.infer.eventType); // 'input'
306
+ ```
307
+
308
+ ## Using with assignGingerly
309
+
310
+ The inferencer enhancement integrates seamlessly with `assignGingerly`:
311
+
312
+ ```TypeScript
313
+ import { value, display } from 'inferencer';
314
+ import 'assign-gingerly/object-extension.js';
315
+
316
+ const element = document.createElement('input');
317
+ element.type = 'text';
318
+
319
+ // Use symbols in assignGingerly
320
+ element.assignGingerly({
321
+ [value]: 'hello world',
322
+ style: {
323
+ color: 'blue'
324
+ }
325
+ });
326
+
327
+ console.log(element.value); // 'hello world'
328
+ console.log(element.style.color); // 'blue'
329
+ ```
330
+
331
+ ## Itemprop Support
332
+
333
+ Elements with an `itemprop` attribute use that attribute's value as the property name:
334
+
335
+ ```html
336
+ <span itemprop="title"></span>
337
+ ```
338
+
339
+ ```TypeScript
340
+ const span = document.querySelector('[itemprop="title"]');
341
+ span.set[value] = 'My Title';
342
+ console.log(span.title); // 'My Title'
343
+ ```
344
+
345
+ ## Helper Functions
346
+
347
+ The inferencer module exports helper functions for manual property and event type inference:
348
+
349
+ ```TypeScript
350
+ import { inferValueProperty, inferDisplayProperty, inferEventType } from 'inferencer';
351
+
352
+ const input = document.createElement('input');
353
+ input.type = 'checkbox';
354
+
355
+ const valueProp = inferValueProperty(input);
356
+ console.log(valueProp); // 'checked'
357
+
358
+ const displayProp = inferDisplayProperty(input);
359
+ console.log(displayProp); // 'value'
360
+
361
+ const eventType = inferEventType(input);
362
+ console.log(eventType); // 'input'
363
+ ```
364
+
365
+ These functions can be useful when you need to determine the property or event type name without actually setting a value or attaching a listener.
366
+
367
+ ## Implementation Details
368
+
369
+ The inferencer enhancement is implemented as a standard enhancement class:
370
+
371
+ ```TypeScript
372
+ class Infer<TValue = any, TDisplay = any> {
373
+ #weakRef: WeakRef<Element>;
374
+
375
+ constructor(enhancedElement?: Element) {
376
+ this.#weakRef = new WeakRef(enhancedElement!);
377
+ }
378
+
379
+ get value(): TValue | undefined { /* ... */ }
380
+ set value(nv: TValue) {
381
+ const element = this.#weakRef.deref()!;
382
+ element[inferValueProperty(element)] = nv;
383
+ }
384
+
385
+ get display(): TDisplay | undefined { /* ... */ }
386
+ set display(nv: TDisplay) {
387
+ const element = this.#weakRef.deref()!;
388
+ element[inferDisplayProperty(element)] = nv;
389
+ }
390
+
391
+ get eventType(): string {
392
+ return inferEventType(this.enhancedElement);
393
+ }
394
+ }
395
+ ```
396
+
397
+ **Registry Configuration:**
398
+
399
+ ```TypeScript
400
+ export const registryItem: EnhancementConfig = {
401
+ spawn: Infer,
402
+ enhKey: 'infer',
403
+ symlinks: {
404
+ [value]: 'value',
405
+ [display]: 'display'
406
+ }
407
+ };
408
+ ```
409
+
410
+ The `symlinks` mapping connects the symbols to the enhancement's properties, enabling the `element.set[symbol]` syntax.
411
+
412
+ ## Benefits
413
+
414
+ 1. **Type-agnostic code**: Write code that works with any element type without conditionals
415
+ 2. **Cleaner syntax**: No need to remember which property each element type uses
416
+ 3. **Accessibility**: Separate value and display properties support screen readers
417
+ 4. **Framework-friendly**: Symbols work well with reactive frameworks and data binding
418
+ 5. **Extensible**: Based on the enhancement registry system, can be customized or extended
419
+ 6. **Event inference**: Automatically determine the most appropriate event type for any element
420
+
421
+ ## Complete Example
422
+
423
+ ```html
424
+ <!DOCTYPE html>
425
+ <html>
426
+ <head>
427
+ <script type="module">
428
+ import { value, display, registryItem } from 'inferencer';
429
+ import 'assign-gingerly/object-extension.js';
430
+
431
+ // Register the enhancement
432
+ customElements.enhancementRegistry.push(registryItem);
433
+
434
+ // Create various elements
435
+ const input = document.createElement('input');
436
+ input.type = 'text';
437
+
438
+ const checkbox = document.createElement('input');
439
+ checkbox.type = 'checkbox';
440
+
441
+ const time = document.createElement('time');
442
+
443
+ const meter = document.createElement('meter');
444
+ meter.min = 0;
445
+ meter.max = 100;
446
+
447
+ // Set values using the same symbol - each element handles it correctly
448
+ input.set[value] = 'Hello World';
449
+ checkbox.set[value] = true;
450
+ time.set[value] = '2024-01-01T00:00:00Z';
451
+ time.set[display] = 'January 1, 2024';
452
+ meter.set[value] = 75;
453
+ meter.set[display] = '75 percent';
454
+
455
+ // Add to document
456
+ document.body.append(input, checkbox, time, meter);
457
+
458
+ console.log('Input value:', input.value); // 'Hello World'
459
+ console.log('Checkbox checked:', checkbox.checked); // true
460
+ console.log('Time dateTime:', time.dateTime); // '2024-01-01T00:00:00Z'
461
+ console.log('Time display:', time.textContent); // 'January 1, 2024'
462
+ console.log('Meter value:', meter.value); // 75
463
+ console.log('Meter display:', meter.ariaValueText); // '75 percent'
464
+
465
+ // Event type inference
466
+ console.log('Input event:', input.enh.infer.eventType); // 'input'
467
+ console.log('Meter event:', meter.enh.infer.eventType); // 'click'
468
+ </script>
469
+ </head>
470
+ <body>
471
+ <h1>Inferencer Enhancement Demo</h1>
472
+ </body>
473
+ </html>
474
+ ```
475
+
476
+ ## Browser Support
477
+
478
+ The inferencer enhancement requires:
479
+ - Chrome 146+ (for scoped custom element registries)
480
+ - Modern browsers with Symbol support
481
+ - WeakRef support (all modern browsers)
482
+
483
+ For browsers without scoped registry support, the enhancement falls back to the global `customElements.enhancementRegistry`.
484
+
485
+ ## API Reference
486
+
487
+ ### Exports
488
+
489
+ - `value: symbol` - Symbol for smart value assignment
490
+ - `display: symbol` - Symbol for smart display assignment
491
+ - `registryItem: EnhancementConfig` - Registry configuration for the enhancement
492
+ - `Infer: class` - The enhancement class
493
+ - `inferValueProperty(element: Element): string` - Helper function to infer value property name
494
+ - `inferDisplayProperty(element: Element): string` - Helper function to infer display property name
495
+ - `inferEventType(element: Element): string` - Helper function to infer event type name
496
+ - `InferencedPropagator: class` - (from `inferencer/InferencedPropagator.js`) EventTarget that infers property change detection
497
+
498
+ ## License
499
+
500
+ MIT
501
+
502
+ ## Related Packages
503
+
504
+ - [assign-gingerly](https://www.npmjs.com/package/assign-gingerly) - Required dependency for enhancement registry support
505
+
506
+ ## Viewing Locally
507
+
508
+ Any web server that serves static files with server-side includes will do but...
509
+
510
+ 1. Install git
511
+ 2. Fork/clone this repo
512
+ 3. Install node.js
513
+ 4. Open command window to folder where you cloned this repo
514
+ 5. > git submodule add https://github.com/bahrus/types.git types
515
+ 6. > git submodule update --init --recursive
516
+ 7. > npm install
517
+ 8. > npm run serve
518
+ 9. Open http://localhost:8000/demo/ in a modern browser
519
+
520
+ ## Running Tests
521
+
522
+ ```
523
+ > npm run test
524
+ ```