domma-js 0.56.0 → 0.58.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 (121) hide show
  1. package/README.md +2 -2
  2. package/assets/types/generated/public/assets/flags/africa.d.ts +6 -0
  3. package/assets/types/generated/public/assets/flags/americas.d.ts +6 -0
  4. package/assets/types/generated/public/assets/flags/asia.d.ts +6 -0
  5. package/assets/types/generated/public/assets/flags/europe.d.ts +9 -0
  6. package/assets/types/generated/public/assets/flags/index.d.ts +11 -0
  7. package/assets/types/generated/public/assets/flags/oceania.d.ts +2 -0
  8. package/assets/types/generated/public/assets/icons/buildings.d.ts +6 -0
  9. package/assets/types/generated/public/assets/icons/code.d.ts +2 -0
  10. package/assets/types/generated/public/assets/icons/commerce.d.ts +7 -0
  11. package/assets/types/generated/public/assets/icons/communication.d.ts +7 -0
  12. package/assets/types/generated/public/assets/icons/devices.d.ts +6 -0
  13. package/assets/types/generated/public/assets/icons/emojis.d.ts +6 -0
  14. package/assets/types/generated/public/assets/icons/files.d.ts +7 -0
  15. package/assets/types/generated/public/assets/icons/finance.d.ts +6 -0
  16. package/assets/types/generated/public/assets/icons/forms.d.ts +5 -0
  17. package/assets/types/generated/public/assets/icons/health.d.ts +6 -0
  18. package/assets/types/generated/public/assets/icons/index.d.ts +24 -0
  19. package/assets/types/generated/public/assets/icons/media.d.ts +7 -0
  20. package/assets/types/generated/public/assets/icons/navigation.d.ts +7 -0
  21. package/assets/types/generated/public/assets/icons/seasonal.d.ts +6 -0
  22. package/assets/types/generated/public/assets/icons/social.d.ts +7 -0
  23. package/assets/types/generated/public/assets/icons/sport.d.ts +6 -0
  24. package/assets/types/generated/public/assets/icons/status.d.ts +7 -0
  25. package/assets/types/generated/public/assets/icons/transport.d.ts +7 -0
  26. package/assets/types/generated/public/assets/icons/ui.d.ts +7 -0
  27. package/assets/types/generated/public/assets/icons/weather.d.ts +6 -0
  28. package/assets/types/generated/src/auth.d.ts +424 -0
  29. package/assets/types/generated/src/avatar.d.ts +270 -0
  30. package/assets/types/generated/src/binding-source.d.ts +58 -0
  31. package/assets/types/generated/src/butterfly-drawing.d.ts +2 -0
  32. package/assets/types/generated/src/component-factory.d.ts +150 -0
  33. package/assets/types/generated/src/component.d.ts +162 -0
  34. package/assets/types/generated/src/components/back-to-top.d.ts +150 -0
  35. package/assets/types/generated/src/components/badge.d.ts +208 -0
  36. package/assets/types/generated/src/components/card.d.ts +189 -0
  37. package/assets/types/generated/src/components/command-palette.d.ts +352 -0
  38. package/assets/types/generated/src/components/dropzone.d.ts +342 -0
  39. package/assets/types/generated/src/components/focus-trap.d.ts +238 -0
  40. package/assets/types/generated/src/components/loader.d.ts +133 -0
  41. package/assets/types/generated/src/components/modal.d.ts +339 -0
  42. package/assets/types/generated/src/components/range-slider.d.ts +267 -0
  43. package/assets/types/generated/src/components/shared.d.ts +91 -0
  44. package/assets/types/generated/src/components/split-pane.d.ts +239 -0
  45. package/assets/types/generated/src/components/toast.d.ts +284 -0
  46. package/assets/types/generated/src/components/tooltip.d.ts +200 -0
  47. package/assets/types/generated/src/components/virtual-list.d.ts +340 -0
  48. package/assets/types/generated/src/config.d.ts +193 -0
  49. package/assets/types/generated/src/context-cursor.d.ts +69 -0
  50. package/assets/types/generated/src/context-menu.d.ts +596 -0
  51. package/assets/types/generated/src/dates.d.ts +367 -0
  52. package/assets/types/generated/src/dom.d.ts +1221 -0
  53. package/assets/types/generated/src/effects.d.ts +1281 -0
  54. package/assets/types/generated/src/elements.d.ts +4994 -0
  55. package/assets/types/generated/src/escape.d.ts +5 -0
  56. package/assets/types/generated/src/flags-bundle.d.ts +4 -0
  57. package/assets/types/generated/src/flags.d.ts +338 -0
  58. package/assets/types/generated/src/forms.d.ts +1060 -0
  59. package/assets/types/generated/src/globals.d.ts +45 -0
  60. package/assets/types/generated/src/http.d.ts +131 -0
  61. package/assets/types/generated/src/i18n.d.ts +261 -0
  62. package/assets/types/generated/src/icons.d.ts +213 -0
  63. package/assets/types/generated/src/index.d.ts +249 -0
  64. package/assets/types/generated/src/input-group.d.ts +135 -0
  65. package/assets/types/generated/src/models.d.ts +968 -0
  66. package/assets/types/generated/src/popover.d.ts +413 -0
  67. package/assets/types/generated/src/router.d.ts +344 -0
  68. package/assets/types/generated/src/safe-url.d.ts +10 -0
  69. package/assets/types/generated/src/sanitize.d.ts +97 -0
  70. package/assets/types/generated/src/schema-builder.d.ts +420 -0
  71. package/assets/types/generated/src/skeleton.d.ts +135 -0
  72. package/assets/types/generated/src/smooth-caret.d.ts +61 -0
  73. package/assets/types/generated/src/sortable.d.ts +368 -0
  74. package/assets/types/generated/src/storage.d.ts +93 -0
  75. package/assets/types/generated/src/tables.d.ts +901 -0
  76. package/assets/types/generated/src/theme.d.ts +262 -0
  77. package/assets/types/generated/src/ticker-tape-drawing.d.ts +2 -0
  78. package/assets/types/generated/src/treeview.d.ts +504 -0
  79. package/assets/types/generated/src/utils.d.ts +1667 -0
  80. package/assets/types/generated/src/web-components/base/domma-element.d.ts +134 -0
  81. package/assets/types/generated/src/web-components/index.d.ts +14 -0
  82. package/assets/types/generated/vendor/domma-reactive.d.ts +587 -0
  83. package/assets/types/index.d.ts +104 -226
  84. package/package.json +5 -2
  85. package/public/dist/bundles/domma-complete.css +20 -14
  86. package/public/dist/bundles/domma-data-focused.css +20 -14
  87. package/public/dist/bundles/domma-essentials.css +20 -14
  88. package/public/dist/bundles/domma-full.css +20 -14
  89. package/public/dist/bundles/domma-minimal.css +8 -8
  90. package/public/dist/domma-flags.esm.js +3 -3
  91. package/public/dist/domma-flags.esm.js.map +1 -1
  92. package/public/dist/domma-flags.min.js +3 -3
  93. package/public/dist/domma-flags.min.js.map +1 -1
  94. package/public/dist/domma-syntax.min.js +3 -3
  95. package/public/dist/domma.css +3 -3
  96. package/public/dist/domma.esm.js +5 -5
  97. package/public/dist/domma.esm.js.map +1 -1
  98. package/public/dist/domma.min.js +5 -5
  99. package/public/dist/domma.min.js.map +1 -1
  100. package/public/dist/elements.css +9 -3
  101. package/public/dist/grid.css +3 -3
  102. package/public/dist/syntax.css +3 -3
  103. package/public/dist/themes/domma-themes.css +3 -3
  104. package/templates/kickstart/.claude/snippets.md +1 -1
  105. package/templates/kickstart/CLAUDE.md +1 -1
  106. package/templates/kickstart/frontend/types/domma.d.ts +7 -4
  107. package/templates/kickstart-spa/.claude/snippets.md +1 -1
  108. package/assets/types/config.d.ts +0 -136
  109. package/assets/types/dates.d.ts +0 -209
  110. package/assets/types/dom.d.ts +0 -448
  111. package/assets/types/elements.d.ts +0 -1168
  112. package/assets/types/flags.d.ts +0 -130
  113. package/assets/types/http.d.ts +0 -97
  114. package/assets/types/i18n.d.ts +0 -99
  115. package/assets/types/icons.d.ts +0 -147
  116. package/assets/types/models.d.ts +0 -260
  117. package/assets/types/smooth-caret.d.ts +0 -12
  118. package/assets/types/storage.d.ts +0 -93
  119. package/assets/types/tables.d.ts +0 -327
  120. package/assets/types/theme.d.ts +0 -137
  121. package/assets/types/utils.d.ts +0 -675
@@ -0,0 +1,968 @@
1
+ /**
2
+ * A type check for a field's value (`M.types.*`).
3
+ * @callback TypeValidator
4
+ * @param {any} value
5
+ * @returns {boolean}
6
+ */
7
+ /**
8
+ * One field of a blueprint. Forms (`F.create`) read further keys from the same object
9
+ * (`label`, `options`, `formConfig`, ...), so any other key is allowed.
10
+ * @typedef {object} FieldDefinition
11
+ * @property {'string'|'number'|'boolean'|'array'|'object'|'date'|'any'|(string & {})} [type] Checked with
12
+ * `M.types[type]` when the value is not empty; a type with no validator (e.g. a form's `email`) is not checked
13
+ * @property {any} [default] Initial value when the data gives none (otherwise `null`)
14
+ * @property {boolean} [required] `null`, `undefined` and `''` fail
15
+ * @property {number} [min] Minimum, for a number value
16
+ * @property {number} [max] Maximum, for a number value
17
+ * @property {number} [minLength] Minimum length, for a string value
18
+ * @property {number} [maxLength] Maximum length, for a string value
19
+ * @property {RegExp} [pattern] Pattern a string value must match
20
+ * @property {(value: any) => boolean|string|void} [validate] Custom check: `false` fails, a string fails with
21
+ * that message, anything else passes
22
+ */
23
+ /**
24
+ * A blueprint: field name -> definition.
25
+ * @typedef {{[field: string]: FieldDefinition & {[key: string]: any}}} Schema
26
+ */
27
+ /**
28
+ * @typedef {object} ValidationResult
29
+ * @property {boolean} valid
30
+ * @property {Array<{field: string, error: string}>} errors
31
+ */
32
+ /**
33
+ * @typedef {object} ModelOptions
34
+ * @property {string} [persist] localStorage key (stored as `model:<persist>`); loaded on creation and saved on change
35
+ * @property {boolean} [autoSave=true] Save on every change when `persist` is set
36
+ */
37
+ /**
38
+ * @typedef {object} ChangeEvent
39
+ * @property {string} field
40
+ * @property {any} newValue
41
+ * @property {any} oldValue
42
+ * @property {Model} model
43
+ */
44
+ /**
45
+ * @callback ChangeCallback
46
+ * @param {ChangeEvent} event
47
+ * @returns {void}
48
+ */
49
+ /**
50
+ * @callback FieldChangeCallback
51
+ * @param {any} newValue
52
+ * @param {any} oldValue
53
+ * @param {Model} model
54
+ * @returns {void}
55
+ */
56
+ /** @typedef {() => void} UnsubscribeFn */
57
+ /**
58
+ * Options for `M.bind()`.
59
+ * @typedef {object} BindingOptions
60
+ * @property {(value: any) => any} [format] Model value -> what the element shows
61
+ * @property {(value: any) => any} [parse] Element value -> what the model stores (two-way only)
62
+ * @property {boolean} [twoWay=false] Write the element's input back to the model
63
+ */
64
+ /**
65
+ * A single reactive value (`M.observable()`), from domma-reactive.
66
+ * @template [T=any]
67
+ * @typedef {import('../vendor/domma-reactive.js').Observable<T>} Observable
68
+ */
69
+ /**
70
+ * A reactive array (`M.observableArray()`), from domma-reactive.
71
+ * @template [T=any]
72
+ * @typedef {import('../vendor/domma-reactive.js').ObservableArray<T>} ObservableArray
73
+ */
74
+ /**
75
+ * @template [T=any]
76
+ * @typedef {import('../vendor/domma-reactive.js').ObservableOptions<T>} ObservableOptions
77
+ */
78
+ /**
79
+ * A lazily-evaluated, dependency-tracked derived value (`M.computed()`).
80
+ * @template [T=any]
81
+ * @typedef {object} ComputedRef
82
+ * @property {T} value The same read as `get()`, spelled as a property - the only one a template expression can
83
+ * use. Assigning hands the value to the derivation's `write` (warns and changes nothing without one).
84
+ * @property {() => T} get Current value, recomputing only if a dependency changed
85
+ * @property {(next: T) => void} set Imperative alias for assigning `.value`
86
+ * @property {() => T} peek Current value without registering a dependency on the caller
87
+ * @property {() => void} dispose Unlink from the dependency graph
88
+ */
89
+ /**
90
+ * @template [T=any]
91
+ * @typedef {object} ComputedOptions
92
+ * @property {string} [label] Debug label used in warnings
93
+ * @property {(value: T, computation: import('../vendor/domma-reactive.js').Computation<T>) => void} [onChange] Called with the
94
+ * new value whenever it changes
95
+ */
96
+ /**
97
+ * A writable computed: where a write should land.
98
+ * @template T
99
+ * @typedef {object} WritableComputedDefinition
100
+ * @property {() => T} read
101
+ * @property {(next: T) => void} write
102
+ */
103
+ /**
104
+ * @typedef {object} EffectOptions
105
+ * @property {string} [label] Debug label used in warnings
106
+ */
107
+ /**
108
+ * Options for `M.applyBindings()`.
109
+ * @typedef {object} ApplyBindingsOptions
110
+ * @property {Record<string, (...args: any[]) => any>} [methods] Handlers for `data-on-*`. Looked up only when the
111
+ * data has no such key.
112
+ * @property {import('../vendor/domma-reactive.js').RenderFn} [render] Template renderer for `data-each` item bodies.
113
+ * Defaults to `utils.render`.
114
+ * @property {string} [template] A name for this subtree, used in warnings
115
+ */
116
+ /**
117
+ * One activated binding record, from domma-reactive. `deps` are the names its expression reads.
118
+ * @typedef {import('../vendor/domma-reactive.js').Binding} ActiveBinding
119
+ */
120
+ /**
121
+ * What `M.applyBindings()` returns; call `dispose()` when the markup is done with.
122
+ * @typedef {import('../vendor/domma-reactive.js').BindingsHandle} BindingHandle
123
+ */
124
+ /**
125
+ * A binding kind for `M.registerBinding()`. Only `update` is required.
126
+ * @typedef {import('../vendor/domma-reactive.js').BindingHandler} BindingHandler
127
+ */
128
+ /**
129
+ * A named store (`M.store()`).
130
+ * @typedef {object} Store
131
+ * @property {Record<string, any>} state The current state (replaced, never mutated, by setState)
132
+ * @property {Set<(state: Record<string, any>, oldState: Record<string, any>) => void>} listeners
133
+ * @property {() => Record<string, any>} getState Get a copy of the current state
134
+ * @property {(updates: Record<string, any>) => void} setState Merge partial updates and notify
135
+ * @property {(listener: (state: Record<string, any>, oldState: Record<string, any>) => void) => () => boolean} subscribe
136
+ * Subscribe to state changes; returns the unsubscribe function
137
+ * @property {(newState?: Record<string, any>) => void} reset Reset to the initial state, or to `newState`
138
+ * (listeners receive `{}` as the old state)
139
+ */
140
+ /**
141
+ * @typedef {object} TypeValidators
142
+ * @property {TypeValidator} string
143
+ * @property {TypeValidator} number Not NaN
144
+ * @property {TypeValidator} boolean
145
+ * @property {TypeValidator} array
146
+ * @property {TypeValidator} object A non-null, non-array object
147
+ * @property {TypeValidator} date A valid `Date`, or ISO-8601 date / date-time text
148
+ * @property {TypeValidator} any
149
+ */
150
+ /**
151
+ * Reactive Model Class
152
+ */
153
+ export class Model {
154
+ /**
155
+ * @param {Schema} schema Field definitions
156
+ * @param {Record<string, any>} [data={}] Initial data values
157
+ * @param {ModelOptions} [options={}]
158
+ */
159
+ constructor(schema: Schema, data?: Record<string, any>, options?: ModelOptions);
160
+ /** @private */
161
+ private _schema;
162
+ /** @private */
163
+ private _initialData;
164
+ /** @private */
165
+ private _bindings;
166
+ /**
167
+ * @type {Set<ChangeCallback>}
168
+ * @private
169
+ */
170
+ private _changeCallbacks;
171
+ /**
172
+ * @type {Map<string, Set<FieldChangeCallback>>}
173
+ * @private
174
+ */
175
+ private _fieldCallbacks;
176
+ /**
177
+ * @type {Map<string, Observable<any>>}
178
+ * @private
179
+ */
180
+ private _fields;
181
+ /**
182
+ * @type {Record<string, any>|null}
183
+ * @private
184
+ */
185
+ private _trackedView;
186
+ /**
187
+ * @type {string|null}
188
+ * @private
189
+ */
190
+ private _persistKey;
191
+ /** @private */
192
+ private _autoSave;
193
+ /**
194
+ * Read a field, or the whole data object when called with no argument.
195
+ *
196
+ * Reads performed inside a computed or effect are tracked, so the caller is
197
+ * re-run when that field changes. Reading the whole object tracks every
198
+ * field currently present - the conservative choice, since the reader could
199
+ * touch any of them.
200
+ *
201
+ * @overload
202
+ * @returns {Record<string, any>} Every field
203
+ */
204
+ get(): Record<string, any>;
205
+ /**
206
+ * @overload
207
+ * @param {string} field
208
+ * @returns {any} The field's value (`undefined` for an unknown field)
209
+ */
210
+ get(field: string): any;
211
+ /**
212
+ * Get (creating if absent) the observable backing a field.
213
+ *
214
+ * Fields not declared in the schema are created on first write, matching
215
+ * the previous behaviour where _data accepted any key.
216
+ *
217
+ * @param {string} name
218
+ * @returns {Observable<any>}
219
+ * @private
220
+ */
221
+ private _field;
222
+ /**
223
+ * Plain-object view of every field, read WITHOUT tracking.
224
+ *
225
+ * Used by toJSON(), persistence and validation - render-time and
226
+ * serialisation reads must not register dependencies.
227
+ *
228
+ * @returns {Record<string, any>}
229
+ * @private
230
+ */
231
+ private _snapshot;
232
+ /**
233
+ * A read-tracked, write-through view of the model's data.
234
+ *
235
+ * Property reads register a dependency; property writes are routed through
236
+ * set(), so validation, change notification and persistence all still run.
237
+ *
238
+ * const state = model.tracked();
239
+ * M.effect(() => console.log(state.count)); // re-runs when count changes
240
+ * state.count = 5; // validated + notified
241
+ *
242
+ * @returns {Record<string, any>}
243
+ */
244
+ tracked(): Record<string, any>;
245
+ /**
246
+ * @overload
247
+ * @param {string} field
248
+ * @param {any} value
249
+ * @returns {this}
250
+ */
251
+ set(field: string, value: any): this;
252
+ /**
253
+ * @overload
254
+ * @param {Record<string, any>} data Several fields at once
255
+ * @returns {this}
256
+ */
257
+ set(data: Record<string, any>): this;
258
+ /**
259
+ * @param {string} field
260
+ * @param {any} value
261
+ * @private
262
+ */
263
+ private _setField;
264
+ /**
265
+ * @param {string} field
266
+ * @param {any} value
267
+ * @returns {{valid: boolean, error?: string}}
268
+ * @private
269
+ */
270
+ private _validateField;
271
+ /**
272
+ * Validate all fields
273
+ * @returns {ValidationResult}
274
+ */
275
+ validate(): ValidationResult;
276
+ /**
277
+ * Get model data as a plain object (untracked)
278
+ * @returns {Record<string, any>}
279
+ */
280
+ toJSON(): Record<string, any>;
281
+ /**
282
+ * Subscribe to changes.
283
+ *
284
+ * onChange(cb) - every field; cb receives {field, newValue, oldValue, model}
285
+ * onChange(field, cb) - one field only; cb receives the same change object
286
+ *
287
+ * For positional arguments (newValue, oldValue, model), use onFieldChange().
288
+ *
289
+ * @overload
290
+ * @param {ChangeCallback} callback
291
+ * @returns {UnsubscribeFn}
292
+ */
293
+ onChange(callback: ChangeCallback): UnsubscribeFn;
294
+ /**
295
+ * @overload
296
+ * @param {string} field
297
+ * @param {ChangeCallback} callback
298
+ * @returns {UnsubscribeFn}
299
+ */
300
+ onChange(field: string, callback: ChangeCallback): UnsubscribeFn;
301
+ /**
302
+ * Subscribe to one field's changes, with positional arguments (newValue, oldValue, model)
303
+ * @param {string} field
304
+ * @param {FieldChangeCallback} callback
305
+ * @returns {UnsubscribeFn} Unsubscribe function
306
+ */
307
+ onFieldChange(field: string, callback: FieldChangeCallback): UnsubscribeFn;
308
+ /**
309
+ * @private
310
+ */
311
+ private _notifyChange;
312
+ /**
313
+ * @private
314
+ */
315
+ private _updateBindings;
316
+ /**
317
+ * @param {string} field
318
+ * @param {Binding} binding
319
+ * @private
320
+ */
321
+ private _addBinding;
322
+ /**
323
+ * @param {string} field
324
+ * @param {Binding} binding
325
+ * @private
326
+ */
327
+ private _removeBinding;
328
+ /**
329
+ * Reset every field to its initial value
330
+ * @param {boolean} [clearStorage=false] Also clear the persisted copy
331
+ * @returns {this}
332
+ */
333
+ reset(clearStorage?: boolean): this;
334
+ /**
335
+ * Destroy model and clean up: drops every listener, binding and observable
336
+ * @param {boolean} [clearStorage=false] Also clear the persisted copy
337
+ * @returns {void}
338
+ */
339
+ destroy(clearStorage?: boolean): void;
340
+ /**
341
+ * Manually save model to localStorage
342
+ * @returns {boolean} - True if successful
343
+ */
344
+ save(): boolean;
345
+ /**
346
+ * Manually load model from localStorage
347
+ * @returns {boolean} - True if data was loaded
348
+ */
349
+ load(): boolean;
350
+ /**
351
+ * Clear persisted data from localStorage
352
+ * @returns {boolean} - True if successful
353
+ */
354
+ clearStorage(): boolean;
355
+ /**
356
+ * Get the persistence key
357
+ * @returns {string|null}
358
+ */
359
+ getPersistKey(): string | null;
360
+ /**
361
+ * Check if model is persisted
362
+ * @returns {boolean}
363
+ */
364
+ isPersisted(): boolean;
365
+ /**
366
+ * Save model data to localStorage
367
+ * @returns {boolean}
368
+ * @private
369
+ */
370
+ private _saveToStorage;
371
+ /**
372
+ * Load model data from localStorage
373
+ * @returns {boolean} - True if data was loaded
374
+ * @private
375
+ */
376
+ private _loadFromStorage;
377
+ }
378
+ export namespace models {
379
+ export let _events: Map<string, Set<(data: any) => void>>;
380
+ /**
381
+ * Subscribe to an event
382
+ * @param {string} event
383
+ * @param {(data: any) => void} callback
384
+ * @returns {UnsubscribeFn}
385
+ */
386
+ export function subscribe(event: string, callback: (data: any) => void): UnsubscribeFn;
387
+ /**
388
+ * Alias for subscribe
389
+ * @param {string} event
390
+ * @param {(data: any) => void} callback
391
+ * @returns {UnsubscribeFn}
392
+ */
393
+ export function on(event: string, callback: (data: any) => void): UnsubscribeFn;
394
+ /**
395
+ * Unsubscribe from an event
396
+ * @param {string} event
397
+ * @param {(data: any) => void} callback
398
+ * @returns {void}
399
+ */
400
+ export function unsubscribe(event: string, callback: (data: any) => void): void;
401
+ /**
402
+ * Alias for unsubscribe
403
+ * @param {string} event
404
+ * @param {(data: any) => void} callback
405
+ * @returns {void}
406
+ */
407
+ export function off(event: string, callback: (data: any) => void): void;
408
+ /**
409
+ * Publish an event
410
+ * @param {string} event
411
+ * @param {any} [data]
412
+ * @returns {void}
413
+ */
414
+ export function publish(event: string, data?: any): void;
415
+ /**
416
+ * Alias for publish
417
+ * @param {string} event
418
+ * @param {any} [data]
419
+ * @returns {void}
420
+ */
421
+ export function emit(event: string, data?: any): void;
422
+ /**
423
+ * Subscribe to an event once
424
+ * @param {string} event
425
+ * @param {(data: any) => void} callback
426
+ * @returns {UnsubscribeFn}
427
+ */
428
+ export function once(event: string, callback: (data: any) => void): UnsubscribeFn;
429
+ /**
430
+ * Clear one event's listeners, or every event's
431
+ * @param {string} [event]
432
+ * @returns {void}
433
+ */
434
+ export function clear(event?: string): void;
435
+ /**
436
+ * Create a new reactive model
437
+ * @param {Schema} schema - Field definitions
438
+ * @param {Record<string, any>} [initialData={}] - Initial data values
439
+ * @param {ModelOptions} [options={}] - Options (persist, autoSave)
440
+ * @returns {Model}
441
+ */
442
+ export function create(schema: Schema, initialData?: Record<string, any>, options?: ModelOptions): Model;
443
+ /**
444
+ * Extend a blueprint with additional fields
445
+ * @param {...Schema} blueprints - Blueprints to merge (left-to-right)
446
+ * @returns {Schema} - A new merged blueprint
447
+ */
448
+ export function extend(...blueprints: Schema[]): Schema;
449
+ /**
450
+ * Pick specific fields from a blueprint
451
+ * @template {Schema} S
452
+ * @template {keyof S & string} K
453
+ * @param {S} blueprint - Source blueprint
454
+ * @param {K[]} fields - Array of field names to pick
455
+ * @returns {Pick<S, K>} - New blueprint with only specified fields
456
+ */
457
+ export function pick<S extends Schema, K extends keyof S & string>(blueprint: S, fields: K[]): Pick<S, K>;
458
+ /**
459
+ * Omit specific fields from a blueprint
460
+ * @template {Schema} S
461
+ * @template {keyof S & string} K
462
+ * @param {S} blueprint - Source blueprint
463
+ * @param {K[]} fields - Array of field names to omit
464
+ * @returns {Omit<S, K>} - New blueprint without specified fields
465
+ */
466
+ export function omit<S extends Schema, K extends keyof S & string>(blueprint: S, fields: K[]): Omit<S, K>;
467
+ export { observable };
468
+ export { observableArray };
469
+ /**
470
+ * Create a lazily-evaluated derived value that tracks whatever it reads.
471
+ *
472
+ * The body is not run until `.get()` is called, and afterwards the cached
473
+ * value is reused until one of the fields it read actually changes.
474
+ *
475
+ * const model = M.create(blueprint, {price: 10, qty: 3});
476
+ * const total = M.computed(() => model.get('price') * model.get('qty'));
477
+ * total.get(); // 30 - evaluated now
478
+ * total.get(); // 30 - cached, body not re-run
479
+ * model.set('qty', 4);
480
+ * total.get(); // 40 - re-evaluated on demand
481
+ *
482
+ * The body must be synchronous: tracking stops at the first `await`.
483
+ *
484
+ * A computed is read-only unless you say where a write should land:
485
+ *
486
+ * const celsius = M.observable(100);
487
+ * const fahrenheit = M.computed({
488
+ * read: () => celsius.value * 9 / 5 + 32,
489
+ * write: (f) => { celsius.value = (f - 32) * 5 / 9; }
490
+ * });
491
+ * fahrenheit.value = 32; // celsius.value === 0
492
+ *
493
+ * That is what lets `data-model` bind a derived value. Assigning to one
494
+ * with no `write` warns and changes nothing, rather than storing into the
495
+ * read cache where the next recompute would silently drop it.
496
+ *
497
+ * @template [T=any]
498
+ * @overload
499
+ * @param {() => T} fn Derivation (read-only).
500
+ * @param {ComputedOptions<T>} [options]
501
+ * @returns {ComputedRef<T>}
502
+ */
503
+ export function computed<T = any>(fn: () => T, options?: ComputedOptions<T>): ComputedRef<T>;
504
+ /**
505
+ * @template [T=any]
506
+ * @overload
507
+ * @param {WritableComputedDefinition<T>} fn {read, write}: a writable computed.
508
+ * @param {ComputedOptions<T>} [options]
509
+ * @returns {ComputedRef<T>}
510
+ */
511
+ export function computed<T = any>(fn: WritableComputedDefinition<T>, options?: ComputedOptions<T>): ComputedRef<T>;
512
+ /**
513
+ * Run a function now, and again whenever any field it read changes.
514
+ *
515
+ * Dependencies are re-collected on every run, so an effect whose branches
516
+ * change stops listening to the branch it no longer takes.
517
+ *
518
+ * const stop = M.effect(() => {
519
+ * $('#total').text(model.get('price') * model.get('qty'));
520
+ * });
521
+ * stop(); // unsubscribe
522
+ *
523
+ * Re-runs are batched: a burst of writes in the same tick produces a single
524
+ * run on the next microtask, not one per write.
525
+ *
526
+ * @param {() => unknown} fn Synchronous body.
527
+ * @param {EffectOptions} [options]
528
+ * @returns {UnsubscribeFn} Call to stop the effect.
529
+ */
530
+ export function effect(fn: () => unknown, options?: EffectOptions): UnsubscribeFn;
531
+ /**
532
+ * Read values without registering them as dependencies of the enclosing
533
+ * computed or effect.
534
+ *
535
+ * @template T
536
+ * @param {() => T} fn
537
+ * @returns {T}
538
+ */
539
+ export function untracked<T>(fn: () => T): T;
540
+ /**
541
+ * Settle all pending reactive work immediately rather than waiting for the
542
+ * microtask flush. Mainly useful in tests and when code must observe a
543
+ * derived value synchronously after a write.
544
+ * @returns {void}
545
+ */
546
+ export function flush(): void;
547
+ export let types: TypeValidators;
548
+ /**
549
+ * Bind a model field to DOM element(s): the element shows the field, and with `twoWay` writes back to it
550
+ * @param {Model} model
551
+ * @param {string} field
552
+ * @param {string|HTMLElement} selector Selector (every match is bound) or element
553
+ * @param {BindingOptions} [options]
554
+ * @returns {UnsubscribeFn} Unbind function
555
+ */
556
+ export function bind(model: Model, field: string, selector: string | HTMLElement, options?: BindingOptions): UnsubscribeFn;
557
+ /**
558
+ * Bring markup that already exists to life.
559
+ *
560
+ * `M.bind()` wires ONE field to ONE element. This activates every binding
561
+ * attribute under a root at once, and is the counterpart to the template
562
+ * bindings a `Domma.component()` already gets: a component owns its markup
563
+ * and renders it, a server-rendered page owns its markup and wants
564
+ * behaviour added to it.
565
+ *
566
+ * <div id="app">
567
+ * <h1 data-bind-text="title">Rendered by the server</h1>
568
+ * <input data-model="query">
569
+ * <p data-if="showHelp">Help text.</p>
570
+ * <button data-on-click="save">Save</button>
571
+ * <ul data-each="rows key=id">
572
+ * <li data-bind-text="name">template row</li>
573
+ * </ul>
574
+ * </div>
575
+ *
576
+ * const model = M.create(blueprint, {title: 'Live', query: '', rows: []});
577
+ * const handle = M.applyBindings(model, '#app', {
578
+ * methods: { save() { H.post('/api/save', model.toJSON()); } }
579
+ * });
580
+ *
581
+ * Pass a Model and every binding reads and writes through it - `data-model`
582
+ * lands in the model, with validation and change notification, and any
583
+ * other binding on that field updates. A plain object works too, but only
584
+ * the parts of it that are observable will be reactive.
585
+ *
586
+ * `{{ }}` is deliberately NOT interpolated in markup that already exists;
587
+ * `data-bind-text` is the supported spelling. The one exception is the
588
+ * contents of a `data-each`, which are a template rather than rendered
589
+ * output. See docs/Bindings.md.
590
+ *
591
+ * Applying twice over the same region is safe: elements already bound are
592
+ * skipped, with one warning naming the root.
593
+ *
594
+ * @param {Model|Record<string, any>} data A Model, or a plain object.
595
+ * @param {string|Element|import('./dom.js').DommaCollection|ArrayLike<Element>} root Selector, element or
596
+ * collection (its first element).
597
+ * @param {ApplyBindingsOptions} [options] `methods` (handlers for `data-on-*`),
598
+ * `render` (template renderer for list
599
+ * items - defaults to `utils.render`, so
600
+ * `{{ }}` inside a `data-each` behaves as
601
+ * it does everywhere else in Domma) and
602
+ * `template` (a name used in warnings).
603
+ * @returns {BindingHandle}
604
+ * @throws {TypeError} When no element is found for `root`.
605
+ */
606
+ export function applyBindings(data: Model | Record<string, any>, root: string | Element | import("./dom.js").DommaCollection | ArrayLike<Element>, options?: ApplyBindingsOptions): BindingHandle;
607
+ /**
608
+ * Add a binding kind, usable as `data-<name>` wherever bindings are.
609
+ *
610
+ * Not a side door: every built-in - text, attr, raw, if, event, bind,
611
+ * model - is registered through this same function, so a custom binding can
612
+ * do anything a built-in can.
613
+ *
614
+ * M.registerBinding('uppercase', {
615
+ * attribute: 'data-uppercase',
616
+ * expression: true, // parse the attribute value
617
+ * tracks: true, // re-run when what it reads changes
618
+ * primes: true, // run once after the first paint
619
+ * update({binding, nodes, context}) {
620
+ * const value = binding.evaluate(context);
621
+ * for (const el of nodes) el.textContent = String(value).toUpperCase();
622
+ * return true;
623
+ * }
624
+ * });
625
+ * // <p data-uppercase="name"></p>
626
+ *
627
+ * `update` receives every node the binding owns at once, not one per call,
628
+ * so a handler that re-renders a region does so once however many regions
629
+ * it owns.
630
+ *
631
+ * @template {BindingHandler} H
632
+ * @param {string} name The binding kind, which becomes `binding.kind`.
633
+ * @param {H} handler `{attribute|attributePrefix, expression, tracks,
634
+ * region, capturesBody, primes, update, attach,
635
+ * detach}` - see docs/Bindings.md.
636
+ * @returns {H} The handler
637
+ */
638
+ export function registerBinding<H extends BindingHandler>(name: string, handler: H): H;
639
+ /**
640
+ * Remove a binding kind added with registerBinding().
641
+ *
642
+ * @param {string} name
643
+ * @returns {boolean} whether anything was removed
644
+ */
645
+ export function unregisterBinding(name: string): boolean;
646
+ /**
647
+ * Add an extender, callable as `M.observable(x).extend({name: value})`.
648
+ *
649
+ * `rateLimit`, `throttle` and `notify` are registered through this same
650
+ * function, so an extender you add is not a second-class citizen - the
651
+ * built-ins have no privileged path.
652
+ *
653
+ * M.registerExtender('trace', (control, label) => {
654
+ * control.intercept((next) => (value) => {
655
+ * console.log(label, value);
656
+ * next(value);
657
+ * });
658
+ * });
659
+ *
660
+ * const count = M.observable(0).extend({trace: 'count'});
661
+ *
662
+ * The control surface an extender is handed has exactly two powers:
663
+ * `setEquals(fn)` replaces the change gate, and `intercept(wrap)` wraps the
664
+ * announcement. Neither can touch the stored value, which is what keeps the
665
+ * guarantee that a write always lands immediately - even under a rate
666
+ * limit, where only the notification waits.
667
+ *
668
+ * @template {import('../vendor/domma-reactive.js').Extender} F
669
+ * @param {string} name
670
+ * @param {F} fn `(control, value) => void`
671
+ * @returns {F} The extender
672
+ */
673
+ export function registerExtender<F extends import("../vendor/domma-reactive.js").Extender>(name: string, fn: F): F;
674
+ /**
675
+ * Remove an extender added with registerExtender().
676
+ * The built-ins are refused.
677
+ *
678
+ * @param {string} name
679
+ * @returns {boolean} whether anything was removed
680
+ */
681
+ export function unregisterExtender(name: string): boolean;
682
+ /**
683
+ * Add a function callable from a binding expression.
684
+ *
685
+ * Expressions cannot call methods on your data - `{{total.get()}}` will not
686
+ * parse - because arbitrary calls are how an expression language turns into
687
+ * an execution surface. A registered helper is the supported way to shape a
688
+ * value in the markup:
689
+ *
690
+ * M.registerHelper('upper', (s) => String(s).toUpperCase());
691
+ * // <p data-bind-text="upper(name)"></p>
692
+ *
693
+ * Helpers are shared by every binding and every component template.
694
+ *
695
+ * @template {(...args: any[]) => unknown} F
696
+ * @param {string} name
697
+ * @param {F} fn Pure, synchronous.
698
+ * @returns {F} The helper
699
+ */
700
+ export function registerHelper<F extends (...args: any[]) => unknown>(name: string, fn: F): F;
701
+ /**
702
+ * Remove a helper added with registerHelper().
703
+ *
704
+ * @param {string} name
705
+ * @returns {boolean} whether anything was removed
706
+ */
707
+ export function unregisterHelper(name: string): boolean;
708
+ export let _stores: Map<string, Store>;
709
+ /**
710
+ * Get or create a named store (`initialState` is used only when it is created)
711
+ * @param {string} name
712
+ * @param {Record<string, any>} [initialState={}]
713
+ * @returns {Store}
714
+ */
715
+ export function store(name: string, initialState?: Record<string, any>): Store;
716
+ /**
717
+ * Get an existing store
718
+ * @param {string} name
719
+ * @returns {Store|undefined}
720
+ */
721
+ export function getStore(name: string): Store | undefined;
722
+ /**
723
+ * Remove a store
724
+ * @param {string} name
725
+ * @returns {void}
726
+ */
727
+ export function removeStore(name: string): void;
728
+ }
729
+ /**
730
+ * A type check for a field's value (`M.types.*`).
731
+ */
732
+ export type TypeValidator = (value: any) => boolean;
733
+ /**
734
+ * One field of a blueprint. Forms (`F.create`) read further keys from the same object
735
+ * (`label`, `options`, `formConfig`, ...), so any other key is allowed.
736
+ */
737
+ export type FieldDefinition = {
738
+ /**
739
+ * Checked with
740
+ * `M.types[type]` when the value is not empty; a type with no validator (e.g. a form's `email`) is not checked
741
+ */
742
+ type?: "string" | "number" | "boolean" | "array" | "object" | "date" | "any" | (string & {});
743
+ /**
744
+ * Initial value when the data gives none (otherwise `null`)
745
+ */
746
+ default?: any;
747
+ /**
748
+ * `null`, `undefined` and `''` fail
749
+ */
750
+ required?: boolean;
751
+ /**
752
+ * Minimum, for a number value
753
+ */
754
+ min?: number;
755
+ /**
756
+ * Maximum, for a number value
757
+ */
758
+ max?: number;
759
+ /**
760
+ * Minimum length, for a string value
761
+ */
762
+ minLength?: number;
763
+ /**
764
+ * Maximum length, for a string value
765
+ */
766
+ maxLength?: number;
767
+ /**
768
+ * Pattern a string value must match
769
+ */
770
+ pattern?: RegExp;
771
+ /**
772
+ * Custom check: `false` fails, a string fails with
773
+ * that message, anything else passes
774
+ */
775
+ validate?: (value: any) => boolean | string | void;
776
+ };
777
+ /**
778
+ * A blueprint: field name -> definition.
779
+ */
780
+ export type Schema = {
781
+ [field: string]: FieldDefinition & {
782
+ [key: string]: any;
783
+ };
784
+ };
785
+ export type ValidationResult = {
786
+ valid: boolean;
787
+ errors: Array<{
788
+ field: string;
789
+ error: string;
790
+ }>;
791
+ };
792
+ export type ModelOptions = {
793
+ /**
794
+ * localStorage key (stored as `model:<persist>`); loaded on creation and saved on change
795
+ */
796
+ persist?: string;
797
+ /**
798
+ * Save on every change when `persist` is set
799
+ */
800
+ autoSave?: boolean;
801
+ };
802
+ export type ChangeEvent = {
803
+ field: string;
804
+ newValue: any;
805
+ oldValue: any;
806
+ model: Model;
807
+ };
808
+ export type ChangeCallback = (event: ChangeEvent) => void;
809
+ export type FieldChangeCallback = (newValue: any, oldValue: any, model: Model) => void;
810
+ export type UnsubscribeFn = () => void;
811
+ /**
812
+ * Options for `M.bind()`.
813
+ */
814
+ export type BindingOptions = {
815
+ /**
816
+ * Model value -> what the element shows
817
+ */
818
+ format?: (value: any) => any;
819
+ /**
820
+ * Element value -> what the model stores (two-way only)
821
+ */
822
+ parse?: (value: any) => any;
823
+ /**
824
+ * Write the element's input back to the model
825
+ */
826
+ twoWay?: boolean;
827
+ };
828
+ /**
829
+ * A single reactive value (`M.observable()`), from domma-reactive.
830
+ */
831
+ export type Observable<T = any> = import("../vendor/domma-reactive.js").Observable<T>;
832
+ /**
833
+ * A reactive array (`M.observableArray()`), from domma-reactive.
834
+ */
835
+ export type ObservableArray<T = any> = import("../vendor/domma-reactive.js").ObservableArray<T>;
836
+ export type ObservableOptions<T = any> = import("../vendor/domma-reactive.js").ObservableOptions<T>;
837
+ /**
838
+ * A lazily-evaluated, dependency-tracked derived value (`M.computed()`).
839
+ */
840
+ export type ComputedRef<T = any> = {
841
+ /**
842
+ * The same read as `get()`, spelled as a property - the only one a template expression can
843
+ * use. Assigning hands the value to the derivation's `write` (warns and changes nothing without one).
844
+ */
845
+ value: T;
846
+ /**
847
+ * Current value, recomputing only if a dependency changed
848
+ */
849
+ get: () => T;
850
+ /**
851
+ * Imperative alias for assigning `.value`
852
+ */
853
+ set: (next: T) => void;
854
+ /**
855
+ * Current value without registering a dependency on the caller
856
+ */
857
+ peek: () => T;
858
+ /**
859
+ * Unlink from the dependency graph
860
+ */
861
+ dispose: () => void;
862
+ };
863
+ export type ComputedOptions<T = any> = {
864
+ /**
865
+ * Debug label used in warnings
866
+ */
867
+ label?: string;
868
+ /**
869
+ * Called with the
870
+ * new value whenever it changes
871
+ */
872
+ onChange?: (value: T, computation: import("../vendor/domma-reactive.js").Computation<T>) => void;
873
+ };
874
+ /**
875
+ * A writable computed: where a write should land.
876
+ */
877
+ export type WritableComputedDefinition<T> = {
878
+ read: () => T;
879
+ write: (next: T) => void;
880
+ };
881
+ export type EffectOptions = {
882
+ /**
883
+ * Debug label used in warnings
884
+ */
885
+ label?: string;
886
+ };
887
+ /**
888
+ * Options for `M.applyBindings()`.
889
+ */
890
+ export type ApplyBindingsOptions = {
891
+ /**
892
+ * Handlers for `data-on-*`. Looked up only when the
893
+ * data has no such key.
894
+ */
895
+ methods?: Record<string, (...args: any[]) => any>;
896
+ /**
897
+ * Template renderer for `data-each` item bodies.
898
+ * Defaults to `utils.render`.
899
+ */
900
+ render?: import("../vendor/domma-reactive.js").RenderFn;
901
+ /**
902
+ * A name for this subtree, used in warnings
903
+ */
904
+ template?: string;
905
+ };
906
+ /**
907
+ * One activated binding record, from domma-reactive. `deps` are the names its expression reads.
908
+ */
909
+ export type ActiveBinding = import("../vendor/domma-reactive.js").Binding;
910
+ /**
911
+ * What `M.applyBindings()` returns; call `dispose()` when the markup is done with.
912
+ */
913
+ export type BindingHandle = import("../vendor/domma-reactive.js").BindingsHandle;
914
+ /**
915
+ * A binding kind for `M.registerBinding()`. Only `update` is required.
916
+ */
917
+ export type BindingHandler = import("../vendor/domma-reactive.js").BindingHandler;
918
+ /**
919
+ * A named store (`M.store()`).
920
+ */
921
+ export type Store = {
922
+ /**
923
+ * The current state (replaced, never mutated, by setState)
924
+ */
925
+ state: Record<string, any>;
926
+ listeners: Set<(state: Record<string, any>, oldState: Record<string, any>) => void>;
927
+ /**
928
+ * Get a copy of the current state
929
+ */
930
+ getState: () => Record<string, any>;
931
+ /**
932
+ * Merge partial updates and notify
933
+ */
934
+ setState: (updates: Record<string, any>) => void;
935
+ /**
936
+ * Subscribe to state changes; returns the unsubscribe function
937
+ */
938
+ subscribe: (listener: (state: Record<string, any>, oldState: Record<string, any>) => void) => () => boolean;
939
+ /**
940
+ * Reset to the initial state, or to `newState`
941
+ * (listeners receive `{}` as the old state)
942
+ */
943
+ reset: (newState?: Record<string, any>) => void;
944
+ };
945
+ export type TypeValidators = {
946
+ string: TypeValidator;
947
+ /**
948
+ * Not NaN
949
+ */
950
+ number: TypeValidator;
951
+ boolean: TypeValidator;
952
+ array: TypeValidator;
953
+ /**
954
+ * A non-null, non-array object
955
+ */
956
+ object: TypeValidator;
957
+ /**
958
+ * A valid `Date`, or ISO-8601 date / date-time text
959
+ */
960
+ date: TypeValidator;
961
+ any: TypeValidator;
962
+ };
963
+ /**
964
+ * The models module (`M`): pub/sub, reactive models, dependency-tracked reactivity, DOM bindings and stores.
965
+ */
966
+ export type Models = typeof models;
967
+ import { observable } from '../vendor/domma-reactive.js';
968
+ import { observableArray } from '../vendor/domma-reactive.js';