@rusticarcade/palette 0.1.0 → 0.3.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.
@@ -0,0 +1,803 @@
1
+ /**
2
+ * Initialize the global test DOM environment (using HappyDOM)
3
+ */
4
+ declare function prepareGlobalTestDOM(): Promise<void>;
5
+ /**
6
+ * Cleanup the global test DOM environment (using HappyDOM)
7
+ */
8
+ declare function cleanupGlobalTestDOM(): Promise<void>;
9
+ type StateListener<Shape> = (state: Shape) => void;
10
+ /**
11
+ * Powerful and flexible state management with deep reactivity, transaction, and
12
+ * locking support.
13
+ *
14
+ * The State class wraps stateful data and provides an API for mutating the data
15
+ * while listeners subscribe to meaningful updates.
16
+ *
17
+ * Modify state with setters, mutators, transactions, or proxied updates with
18
+ * deep reactivity and array mutation support built in.
19
+ *
20
+ * @example
21
+ *
22
+ * ```typescript
23
+ * const state = new State({count: 1});
24
+ * state.addListener(data => console.log(data))
25
+ *
26
+ * state.set("count", 2); // Prints "2"
27
+ * state.set("count", 2); // Nothing happens, no change
28
+ * state.live.count = 3; // Prints "3"
29
+ * ```
30
+ */
31
+ declare class State<Shape extends object> {
32
+ private _data;
33
+ private _listeners;
34
+ private _proxy?;
35
+ private _proxyCache;
36
+ private _reverseProxyCache;
37
+ private _isLocked;
38
+ private _hasWarned;
39
+ constructor(initialData: Shape, onChange?: StateListener<Shape>);
40
+ /**
41
+ * Lazily create and cache proxies into the state for reactive updates on
42
+ * nested values.
43
+ */
44
+ private _createProxy;
45
+ private _unwrapProxy;
46
+ /**
47
+ * Handle setting nested values and emitting updated data if the value changed
48
+ */
49
+ private _setNested;
50
+ /**
51
+ * Process an incoming partial state and emit updates to listeners if there
52
+ * are any changes detected.
53
+ *
54
+ * @remarks
55
+ * Object.is() to check for differences. Does not attempt deep diffing.
56
+ */
57
+ private _processIncomingState;
58
+ /**
59
+ * Emit the current state to all listeners
60
+ */
61
+ private _emit;
62
+ /**
63
+ * The current state
64
+ *
65
+ * @remarks
66
+ * This is a direct reference to the internal state. It is marked as Readonly
67
+ * to help prevent accidental changes. Never edit this value directly.
68
+ */
69
+ get current(): Readonly<Shape>;
70
+ /**
71
+ * Proxied access to state properties with automatic reconciliation.
72
+ *
73
+ * Allows direct property access for both reading and writing state values.
74
+ *
75
+ * @example
76
+ *
77
+ * Deep reactivity with the `.live` accessor
78
+ *
79
+ * ```typescript
80
+ * const state = new State({
81
+ * nested: {
82
+ * values: [1, 2, 3],
83
+ * }
84
+ * });
85
+ *
86
+ * // Deep value assignment triggers state updates
87
+ * state.live.nested.values[1] = 5;
88
+ *
89
+ * // Array mutators are automatically reactive as well
90
+ * state.live.nested.values.push(4);
91
+ * state.live.nested.values.reverse();
92
+ * ```
93
+ */
94
+ get live(): Shape;
95
+ /**
96
+ * Indicates if this state is currently locked (true) or not (false)
97
+ */
98
+ get isLocked(): boolean;
99
+ /**
100
+ * Add a handler function for when this state changes.
101
+ *
102
+ * Listeners are invoked in the order they are registered and are passed a
103
+ * reference to the internally managed state object as a readonly object.
104
+ *
105
+ * **Do not modify state values directly**. Instead, use {@link set} or
106
+ * {@link patch} to make immutable updates.
107
+ */
108
+ addListener: (listener: StateListener<Shape>) => void;
109
+ /**
110
+ * Remove a previously registered state handler
111
+ */
112
+ removeListener: (listener: StateListener<Shape>) => void;
113
+ /**
114
+ * Get a single value from the state object
115
+ *
116
+ * The value is returned as Readonly to prevent accidental state mutations.
117
+ * To mutate stateful properties, use {@link set} or {@link patch} instead.
118
+ *
119
+ * @example
120
+ *
121
+ * ```typescript
122
+ * const state = new State({ count: 1 });
123
+ * console.log(state.get("count")); // 1
124
+ * ```
125
+ *
126
+ */
127
+ get: <K extends keyof Shape>(key: K) => Readonly<Shape[K]>;
128
+ /**
129
+ * Returns a deep clone of the current state data using `structuredClone()` to
130
+ * make the copy.
131
+ *
132
+ * The object returned from this function can be edited without modifying the
133
+ * actual internal state.
134
+ *
135
+ * @example
136
+ *
137
+ * ```typescript
138
+ * const snap = state.snapshot();
139
+ * snap.count += 1;
140
+ * state.patch(snap);
141
+ * ```
142
+ */
143
+ snapshot: () => Shape;
144
+ /**
145
+ * Set a single stateful property while leaving other properties unchanged.
146
+ *
147
+ * Triggers an update to all listeners if the value is different from before
148
+ * when compared using shallow equality.
149
+ *
150
+ * @example
151
+ *
152
+ * ```typescript
153
+ * const state = new State({ count: 1, color: "red" });
154
+ * state.set("count", 2); // State is now { count: 2, color: "red" }
155
+ * ```
156
+ */
157
+ set: <K extends keyof Shape>(key: K, value: Shape[K]) => void;
158
+ /**
159
+ * Set multiple stateful properties at once, leaving omitted properties
160
+ * unchanged.
161
+ *
162
+ * @example
163
+ *
164
+ * Patch a partial state, updating all listed properties at once
165
+ *
166
+ * ```typescript
167
+ * const state = new State({
168
+ * weather: "sunny",
169
+ * temperature: 30,
170
+ * humidity: 70,
171
+ * });
172
+ *
173
+ * // Leaves `temperature` unchanged
174
+ * state.patch({
175
+ * weather: "cloudy",
176
+ * humidity: 50,
177
+ * });
178
+ * ```
179
+ */
180
+ patch: (patch: Partial<Shape>) => State<Shape>;
181
+ /**
182
+ * Fully replace the current state data and force listeners to receive the
183
+ * updated data immediately.
184
+ */
185
+ replace: (state: Shape) => State<Shape>;
186
+ /**
187
+ * Lock this State instance, preventing further external changes
188
+ */
189
+ lock: () => State<Shape>;
190
+ /**
191
+ * Unlock this State instance, allowing further external changes
192
+ */
193
+ unlock: () => State<Shape>;
194
+ /**
195
+ * Apply complex updates to the state using a mutator function.
196
+ *
197
+ * The mutator function takes one parameter which is a structuredClone copy of
198
+ * the current state object. Whatever is returned by the mutator is then
199
+ * patched in to the state.
200
+ */
201
+ mutate: (mutator: (current: Shape) => Shape) => State<Shape>;
202
+ /**
203
+ * Perform an async mutation of the state, optionally locking the state during
204
+ * the process.
205
+ * @param mutator A function to mutate and return the new state
206
+ * @param lock If `true`, lock the state until the mutator completes
207
+ */
208
+ mutateAsync: (mutator: (current: Shape) => Promise<Shape>, lock?: boolean) => Promise<State<Shape>>;
209
+ /**
210
+ * Perform a transaction-style set of actions defined within a function.
211
+ *
212
+ * The provided function can do anything, beyond just setting state. Any
213
+ * uncaught errors thrown from within the function will cause the transaction
214
+ * to fail and the state to automatically roll back to the last valid state.
215
+ *
216
+ * During a transaction, this state instance will be locked, preventing other
217
+ * changes.
218
+ *
219
+ * Transactions will always result in a state update when successful.
220
+ *
221
+ * @example
222
+ *
223
+ * Transactions with locking and rollback support
224
+ *
225
+ * ```typescript
226
+ * const state = new State({count: 1});
227
+ *
228
+ * state.transaction(async (s) => {
229
+ * // `s` is a full State object you can safely manipulate
230
+ * s.set("count", 10);
231
+ * });
232
+ * state.get("count"); // => 10;
233
+ *
234
+ * // Errors inside the transaction roll back the state
235
+ * state.transaction(async (s) => {
236
+ * s.set("count", 100);
237
+ * throw new Error();
238
+ * });
239
+ * state.get("count"); // => 10;
240
+ */
241
+ transaction: (fn: (state: State<Shape>) => void) => boolean;
242
+ /**
243
+ * Perform a transaction-style set of actions defined within an async function
244
+ *
245
+ * The provided function can do anything, beyond just setting state. Any
246
+ * uncaught errors thrown from within the function will cause the transaction
247
+ * to fail and the state to automatically roll back to the last valid state.
248
+ *
249
+ * During a transaction, this state instance will be locked, preventing other
250
+ * changes.
251
+ *
252
+ * Transactions will always result in a state update when successful.
253
+ *
254
+ * @example
255
+ *
256
+ * Transactions with locking and rollback support
257
+ *
258
+ * ```typescript
259
+ * const state = new State({count: 1});
260
+ *
261
+ * // Awaiting the result of a transaction
262
+ * await state.transactionAsync(async (s) => {
263
+ * // `s` is a full State object you can safely manipulate
264
+ * s.set("count", 10);
265
+ * });
266
+ * state.get("count"); // => 10;
267
+ *
268
+ * // Errors inside the transaction roll back the state
269
+ * await state.transactionAsync(async (s) => {
270
+ * s.set("count", 100);
271
+ * throw new Error();
272
+ * });
273
+ * state.get("count"); // => 10;
274
+ *
275
+ * // If you forget to await the transaction, its still locked
276
+ * state.transactionAsync(async (s) => {
277
+ * await waitSeconds(1);
278
+ * });
279
+ * state.set("count", 1); // Error: State is locked!
280
+ * ```
281
+ */
282
+ transactionAsync: (fn: (state: State<Shape>) => Promise<void>) => Promise<boolean>;
283
+ }
284
+ type TemplateRoot = HTMLElement | ShadowRoot;
285
+ type TemplateContext = {
286
+ attr?: Record<string, string | null>;
287
+ state?: Record<string, unknown>;
288
+ data?: Record<string, unknown>;
289
+ item?: Record<string, unknown>;
290
+ index?: number;
291
+ };
292
+ /**
293
+ * A renderable template from an HTMLTemplateElement
294
+ *
295
+ * Leverages a simple syntax to provide accessors to template data from one of
296
+ * four categories, based on use case:
297
+ *
298
+ * ```
299
+ * `@` -> The `attr` namespace (the host element's attributes)
300
+ * `$` -> The `state` namespace (the host element's reactive state)
301
+ * `*` -> The `data` namespace (the host element's computed data)
302
+ * `#` -> The `item` namespace (list item access with ::each)
303
+ * ```
304
+ *
305
+ * Bind attributes to a value using the `:attribute` syntax:
306
+ *
307
+ * ```html
308
+ * <div :id="$id" :class="@classname"></div>
309
+ * ```
310
+ */
311
+ declare class Template {
312
+ /**
313
+ * Properties related to the global Template build cache.
314
+ *
315
+ * This is not something typically needed for general app development, but
316
+ * allows for advanced configuration to tune the caching system if need be.
317
+ *
318
+ * Cache sizes default to 500 HTML Template Fragments and compiled Palette
319
+ * templates (includes nested templates like lists) to cover most application
320
+ * needs without using much memory.
321
+ */
322
+ static cache: {
323
+ /**
324
+ * Wipe all cached templates and HTML fragments
325
+ */
326
+ clear: () => void;
327
+ /**
328
+ * the default cache capacity of 500 items per cache
329
+ *
330
+ * General caching guidance:
331
+ * - 95% of the time, 500 works fine
332
+ * - For very large applications, up to 1000 is reasonable
333
+ * - For smaller apps, dropping down to 100 - 250 may save memory
334
+ *
335
+ * Ultimately the impact will be minimal unless your app has very specific
336
+ * rendering needs.
337
+ */
338
+ setCapacity: (maxSize: number) => void;
339
+ };
340
+ private _compiled;
341
+ /**
342
+ * The original {@link HTMLTemplateElement} used to create this Template.
343
+ *
344
+ * @remarks
345
+ * Make sure to never operate directly on this element. Always clone.
346
+ */
347
+ private _templateElement?;
348
+ /** The current known root element that this Template is rendered into */
349
+ private _mountedRoot?;
350
+ /** The most recent set value for each notation that has rendered */
351
+ private _latestRenderedValues;
352
+ /** The active HTMLElement which the template is updating on renders */
353
+ private _fragment;
354
+ /** Value Notations -> Set<Render Plans> */
355
+ private _plansByNotation;
356
+ /** Value Notations -> Accessor functions */
357
+ private _notationAccessors;
358
+ constructor(template: HTMLTemplateElement);
359
+ /**
360
+ * Create a full copy of this template for use in rendering to another root
361
+ */
362
+ clone: () => Template;
363
+ /**
364
+ * @returns An {@link HTMLTemplateElement} representing this template
365
+ */
366
+ element: () => HTMLTemplateElement;
367
+ private _collectUpdatedValues;
368
+ private _update;
369
+ /**
370
+ * Render this template into a target host element.
371
+ */
372
+ render: (root: TemplateRoot, context: TemplateContext) => void;
373
+ }
374
+ type EventName = keyof GlobalEventHandlersEventMap;
375
+ type EventHandler<K extends EventName = EventName> = (event: GlobalEventHandlersEventMap[K]) => void;
376
+ interface LiveAttributes<State extends object = {}> {
377
+ [name: string]: {
378
+ onChange?: (this: Component<State>, current: string | null, previous: string | null) => void;
379
+ reflect?: (this: Component<State>) => unknown;
380
+ };
381
+ }
382
+ type ComputedProperties<StateShape extends object = {}> = Record<string, unknown> | ((this: Component<StateShape>) => Record<string, unknown>);
383
+ type ComponentStyles = CSSStyleSheet | CSSStyleSheet[] | string;
384
+ type AttributeMap = Map<string, string | null>;
385
+ type StateInitializer<Shape extends object = {}> = Shape | State<Shape> | ((this: Component<Shape>) => Shape | State<Shape>);
386
+ /**
387
+ * The **Component** class extends the base HTMLElement class to provide an
388
+ * ergonomic way to design and develop Web Components with reactive state,
389
+ * managed attributes, and dynamic templating.
390
+ */
391
+ declare abstract class Component<StateShape extends object = {}> extends HTMLElement {
392
+ /**
393
+ * Register a Component with the browser. Optionally provide an overriding
394
+ * tag name.
395
+ */
396
+ static register(component: CustomElementConstructor | typeof Component, tagName?: string): void;
397
+ /**
398
+ * The HTML tag name to use for this Component
399
+ */
400
+ static tagName: string;
401
+ /**
402
+ * An HTML Template element for this element to use.
403
+ */
404
+ static template: HTMLTemplateElement | Template;
405
+ /**
406
+ * A {@link CSSStyleSheet} array or string to adopt as the component's scoped styles
407
+ */
408
+ static styles: ComponentStyles;
409
+ /**
410
+ * An array of html attribute names to observe to trigger updates.
411
+ *
412
+ * @remarks
413
+ * If you use the {@link define} factory helper, this value will be
414
+ * automatically merged with a list of any defined {@link liveAttributes}.
415
+ */
416
+ static observedAttributes: string[];
417
+ /**
418
+ * The mode for this Component's ShadowRoot.
419
+ *
420
+ * - `"open"` allows JS access to the children of this component
421
+ * - `"closed"` (default) disallows internal JS access
422
+ */
423
+ static shadowRootMode: "closed" | "open";
424
+ /**
425
+ * Called immediately before each template update
426
+ */
427
+ protected beforeUpdate?(): void;
428
+ /**
429
+ * Called immediately after each template update
430
+ */
431
+ protected afterUpdate?(previousAttributes: AttributeMap): void;
432
+ /**
433
+ * Called as the final lifecycle method at the end of the unmounting process.
434
+ *
435
+ * Content has been removed from the DOM and the component is no longer
436
+ * considered mounted when this function runs.
437
+ *
438
+ * Use this for final cleanup tasks and freeing resources.
439
+ */
440
+ protected finalize?(): void;
441
+ /**
442
+ * If defined, receives errors caught during the lifecycle methods of this
443
+ * component and it's children. If not defined, this component will instead
444
+ * throw errors as they are found.
445
+ *
446
+ * If the error cannot be handled, `onError()` should re-throw it for a higher
447
+ * up component to evaluate.
448
+ *
449
+ * To display an error message while removing an erroring component from the
450
+ * DOM, use `this.replaceWith()` and a newly constructed placeholder element.
451
+ *
452
+ * @example
453
+ *
454
+ * Recovering from errors or displaying a fallback
455
+ *
456
+ * ```typescript
457
+ * onError(error) {
458
+ * // Handle known errors
459
+ * if (error.message = "Invalid Input") {
460
+ * this.state.input = "";
461
+ * return;
462
+ * }
463
+ *
464
+ * // Display a fallback banner
465
+ * const banner = document.createElement("div");
466
+ * banner.textContent = "An unexpected error done did";
467
+ * this.replaceWith(banner);
468
+ * }
469
+ * ```
470
+ */
471
+ protected onError?(error: unknown): void;
472
+ /**
473
+ * The initial value for this Component's reactive internal state, if any.
474
+ *
475
+ * If `initialState` is defined as a function, the function is evaluated at
476
+ * mounting time and the return value is used as the initial state.
477
+ */
478
+ protected initialState?: StateInitializer<StateShape>;
479
+ /**
480
+ * An object or function returning an object which populates the `data` values
481
+ * in the templating engine. Such values are accessed using the `*` notation.
482
+ *
483
+ * When a hosted value is accessed, it's value is coerced based on the way it
484
+ * is being used. For attributes, values are serialized to a string or null,
485
+ * which will set the attribute (string) or remove it (null).
486
+ *
487
+ * For content swaps, strings, numbers and booleans are rendered as strings
488
+ * and set as textContent. null and undefined values render nothing (with a
489
+ * comment placeholder), an HTMLElement will be swapped in as a cloned node.
490
+ *
491
+ * Functions are evaluated at render/update time, and their return value is
492
+ * used instead. Functions are passed the current target node accessing the
493
+ * property as its first and only argument.
494
+ *
495
+ * Other types are unsupported.
496
+ *
497
+ * @example
498
+ *
499
+ * ```typescript
500
+ * host = {
501
+ * avatarUrl: "http://...",
502
+ * renderTime: () => new Date().toISOString(),
503
+ * }
504
+ * ```
505
+ *
506
+ * ```html
507
+ * <img :src="*avatarUrl" />
508
+ * <span>Rendered at ${"*renderTime"}</span>
509
+ * ```
510
+ */
511
+ protected computedProperties?: ComputedProperties<StateShape>;
512
+ /**
513
+ * Declaration of attribute behaviors during updates.
514
+ *
515
+ * Each key is the name of an attribute. Values are an object with two
516
+ * optional function definitions:
517
+ *
518
+ * `onChange(newValue, oldValue): void`, a handler function for when the value
519
+ * of this attribute has changed. Runs once per update cycle, *before* the
520
+ * update occurs.
521
+ *
522
+ * `reflect(): unknown`, a function which returns a value to serialize and set
523
+ * as this attribute *after* an update completes.
524
+ *
525
+ * @example
526
+ *
527
+ * ```typescript
528
+ * liveAttributes = {
529
+ * done: {
530
+ * onChange(newValue) {
531
+ * this.state.set("done", !!newValue);
532
+ * },
533
+ * reflect() { return this.state.current.done }
534
+ * }
535
+ * };
536
+ * ```
537
+ *
538
+ * @remarks
539
+ *
540
+ * If using the {@link define} helper, the keys of this property are
541
+ * automatically merged with any defined {@link observedAttributes}.
542
+ *
543
+ * If you are directly extending the class, `observedAttributes` must be
544
+ * explicitly defined with any attributes that should be monitored, regardless
545
+ * of if they're defined here.
546
+ */
547
+ protected liveAttributes?: LiveAttributes<StateShape>;
548
+ private _isComponentMounted;
549
+ private _template;
550
+ private _root;
551
+ private _state?;
552
+ private _delegator?;
553
+ private _ownListeners;
554
+ private _liveAttributeConfigs;
555
+ private _cleanupFn?;
556
+ private _renderInternals;
557
+ constructor();
558
+ /** Produce the data object to pass to the template's render function */
559
+ private _getRenderContext;
560
+ private _escalateError;
561
+ private _reportError;
562
+ private _executeAttributeChangeHandlers;
563
+ private _reflectLiveAttributes;
564
+ /** The actual update behavior */
565
+ private _performUpdate;
566
+ /** Safely request for an update to run on the next frame */
567
+ private _scheduleUpdate;
568
+ private _adoptState;
569
+ /**
570
+ * @deprecated Use {@link script} instead
571
+ */
572
+ protected connectedCallback(): void;
573
+ /**
574
+ * @deprecated use {@link finalize}
575
+ */
576
+ protected disconnectedCallback(): void;
577
+ /**
578
+ * @deprecated Use {@link liveAttributes} instead
579
+ */
580
+ protected attributeChangedCallback(name: string, _: string | null, newValue: string | null): void;
581
+ /**
582
+ * The ShadowRoot node of this element
583
+ */
584
+ get root(): ShadowRoot;
585
+ /**
586
+ * Directly access and manipulate this Component's reactive state with deep
587
+ * reactivity enabled.
588
+ *
589
+ * @example
590
+ *
591
+ * ```typescript
592
+ * initialState = { values: { count: 1, time: 0 } };
593
+ *
594
+ * increment() {
595
+ * this.state.values.count = 2;
596
+ * }
597
+ * ```
598
+ *
599
+ * @remarks
600
+ * This is a shorthand getter for `this.getState().live`
601
+ */
602
+ get state(): StateShape;
603
+ /**
604
+ * Replace the current state with a new value or adopt a whole different State
605
+ * instance
606
+ *
607
+ * @example
608
+ *
609
+ * State replacement
610
+ *
611
+ * ```typescript
612
+ * // Always triggers a render
613
+ * this.state = { some: "newState" }
614
+ *
615
+ * // Adopt a new state instance altogether
616
+ * const otherState = new State({some: "newState"});
617
+ * this.state = otherState;
618
+ *
619
+ * // Causes a render
620
+ * otherState.set("some", "value");
621
+ * ```
622
+ */
623
+ set state(newState: StateShape | State<StateShape>);
624
+ /**
625
+ * Access the full {@link State} instance for this Component.
626
+ *
627
+ * Using this method on a component which is not using reactive state
628
+ * will result in an error being thrown.
629
+ *
630
+ * @example
631
+ *
632
+ * Retrieve stateful value
633
+ *
634
+ * ```typescript
635
+ * class Example extends Component {
636
+ * initialState = { count: 1 };
637
+ *
638
+ * script() {
639
+ * const state = this.getState();
640
+ * console.log(`The count is ${state.get("count")}`);
641
+ * }
642
+ *
643
+ * }
644
+ * ```
645
+ *
646
+ * @example
647
+ *
648
+ * Set a stateful value
649
+ *
650
+ * ```typescript
651
+ * class Example extends Component {
652
+ * initialState = { count: 1 };
653
+ *
654
+ * increment() {
655
+ * const state = this.getState();
656
+ * const current = state.get("count");
657
+ * state.set("count", current + 1);
658
+ * }
659
+ * }
660
+ * ```
661
+ */
662
+ getState(): State<StateShape>;
663
+ /**
664
+ * Manually schedule a render to occur
665
+ *
666
+ * @remarks
667
+ * Calling {@link requestRender} multiple times in the same event loop won't
668
+ * schedule multiple renders. Renders are scheduled to occur on the next
669
+ * animation frame.
670
+ */
671
+ requestRender(callback?: VoidFunction): void;
672
+ /**
673
+ * Create a managed event listener on this Component with an optional query
674
+ * filter string to specify which elements to listen to events from.
675
+ *
676
+ * Event handlers set up with `listen()` are automatically cleaned up when
677
+ * the component is unmounted.
678
+ *
679
+ * Handlers are delegated to a single listener per event on the root of the
680
+ * Component, which is the closed ShadowRoot by default.
681
+ *
682
+ * @example
683
+ *
684
+ * Set up an event listener for a click event from a button with ID "submit"
685
+ *
686
+ * ```typescript
687
+ * this.listen("#submit", "click", this.handleClick);
688
+ * ```
689
+ *
690
+ * @example
691
+ *
692
+ * Set up an event listener on the host element itself (`this`).
693
+ *
694
+ * ```typescript
695
+ * // Use ":host" or ":HOST" as the query selector to targe the host element
696
+ * this.listen(":host", "animationend", this.handler);
697
+ * ```
698
+ */
699
+ listen<E extends EventName>(targetDescriptor: string | typeof Component<any> | HTMLElement, eventName: E, eventHandler: EventHandler<E>): void;
700
+ stopListening<E extends EventName>(targetDescriptor: string | typeof Component<any> | HTMLElement, eventName: E, eventHandler: EventHandler<E>): void;
701
+ dispatchEvent(event: Event): boolean;
702
+ /**
703
+ * Dispatch a {@link CustomEvent} with the specified name and detail
704
+ *
705
+ * @example Defining custom events
706
+ *
707
+ * ```typescript
708
+ * // Define types. This can happen in the same file or elsewhere for common
709
+ * // and shared events.
710
+ * type MyEvent = CustomEvent<T> // Set `T` to the event detail type
711
+ *
712
+ * declare global {
713
+ * interface GlobalEventHandlersEventMap {
714
+ * "my-event-name": MyEvent
715
+ * }
716
+ * }
717
+ *
718
+ * // Dispatch a custom event
719
+ * this.dispatchEvent("my-event-name", T);
720
+ *
721
+ * // Listen to a custom event
722
+ * $el.addEventListener("my-event-name", ...);
723
+ * ```
724
+ */
725
+ dispatchEvent<T>(event: string, detail?: T, options?: {
726
+ bubbles: boolean;
727
+ cancelable: boolean;
728
+ composed: boolean;
729
+ }): boolean;
730
+ querySelector<E extends HTMLElement>(query: string): E | null;
731
+ querySelectorAll<E extends HTMLElement>(query: string): NodeListOf<E>;
732
+ getElementById<E extends HTMLElement>(id: string): E | null;
733
+ requireElementById<E extends HTMLElement>(id: string): E;
734
+ setAttribute(name: string, value: string): void;
735
+ /**
736
+ * Set a value as an attribute, serializing to a string or `null`.
737
+ *
738
+ * null values cause the attribute to be removed from this element
739
+ */
740
+ setAttribute(name: string, value: unknown): void;
741
+ getAttribute(name: string): string | null;
742
+ /**
743
+ * Get an attribute as a number, falling back to a specified default.
744
+ *
745
+ *
746
+ * `null` attributes are returned as `null`, while string attributes are
747
+ * parsed using the `Number()` constructor.
748
+ *
749
+ * Values which evaluate to NaN are returned as `null`.
750
+ */
751
+ getAttribute(name: string, defaultValue: number): number;
752
+ /**
753
+ * Get an attribute as a string, falling back to a specified default
754
+ */
755
+ getAttribute(name: string, defaultValue: string): string;
756
+ /**
757
+ * Set the value of an attribute on this element if the provided value
758
+ * differs from the attribute when serialized
759
+ */
760
+ reflectAttribute(name: string, value: unknown): void;
761
+ /**
762
+ * Serialize this element to a string
763
+ */
764
+ toString(full?: boolean): string;
765
+ }
766
+ /**
767
+ * Render a Palette Component class as a test element
768
+ *
769
+ * If the class is not yet registered, it is auto-registered before creation.
770
+ *
771
+ * @example
772
+ *
773
+ * ```typescript
774
+ * test("component does something", async () => {
775
+ * let somethingMock = mock();
776
+ *
777
+ * class MyTestComponent extends Component {
778
+ * script() {
779
+ * somethingMock();
780
+ * }
781
+ * }
782
+ *
783
+ * await renderTestComponent(MyTestComponent);
784
+ * expect(somethingMock).toHaveBeenCalled();
785
+ * });
786
+ * ```
787
+ *
788
+ * @param component The component class to register and create
789
+ * @param attributes A record of attributes to apply
790
+ * @returns A reference to the rendered Component
791
+ */
792
+ declare function renderTestComponent<E extends typeof Component<any>>(component: E, attributes?: Record<string, unknown>): Promise<InstanceType<E>>;
793
+ /**
794
+ * Force a render on the target element
795
+ *
796
+ * Returns a promise which resolves when the render has completed
797
+ */
798
+ declare function rerenderTestComponent(element: Component): Promise<void>;
799
+ /**
800
+ * Returns a random tag name for use in a test element
801
+ */
802
+ declare const randomTagName: () => string;
803
+ export { rerenderTestComponent, renderTestComponent, randomTagName, prepareGlobalTestDOM, cleanupGlobalTestDOM };