element-vir 23.4.2 → 25.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -31
- package/dist/declarative-element/declarative-element-init.d.ts +17 -15
- package/dist/declarative-element/declarative-element.d.ts +18 -21
- package/dist/declarative-element/declarative-element.js +3 -4
- package/dist/declarative-element/define-element-no-inputs.d.ts +1 -8
- package/dist/declarative-element/define-element-no-inputs.js +22 -17
- package/dist/declarative-element/define-element.d.ts +12 -6
- package/dist/declarative-element/define-element.js +8 -2
- package/dist/declarative-element/directives/assign.directive.d.ts +3 -3
- package/dist/declarative-element/directives/async-prop.d.ts +59 -12
- package/dist/declarative-element/directives/async-prop.js +71 -11
- package/dist/declarative-element/is-declarative-element-definition.js +3 -4
- package/dist/declarative-element/properties/element-properties.d.ts +0 -17
- package/dist/declarative-element/properties/host-classes.d.ts +2 -3
- package/dist/declarative-element/properties/property-proxy.js +1 -5
- package/dist/declarative-element/properties/styles.d.ts +3 -4
- package/dist/declarative-element/render-callback.d.ts +10 -11
- package/dist/declarative-element/wrap-define-element.d.ts +7 -8
- package/dist/declarative-element/wrap-define-element.js +2 -2
- package/dist/index.d.ts +0 -3
- package/dist/index.js +0 -3
- package/dist/readme-examples/my-custom-define.d.ts +3 -3
- package/dist/readme-examples/my-with-async-prop.element.d.ts +3 -2
- package/dist/readme-examples/my-with-async-prop.element.js +9 -6
- package/dist/readme-examples/my-with-cleanup-callback.element.d.ts +1 -1
- package/dist/readme-examples/my-with-cleanup-callback.element.js +4 -10
- package/dist/readme-examples/my-with-event-listening.element.js +4 -2
- package/dist/readme-examples/my-with-host-class-definition.element.js +4 -2
- package/dist/readme-examples/my-with-update-state.element.js +9 -7
- package/package.json +11 -11
- package/dist/declarative-element/directives/is-resolved.directive.d.ts +0 -110
- package/dist/declarative-element/directives/is-resolved.directive.js +0 -127
- package/dist/declarative-element/properties/element-vir-state-setup.d.ts +0 -54
- package/dist/declarative-element/properties/element-vir-state-setup.js +0 -22
- package/dist/declarative-element/properties/per-instance.d.ts +0 -26
- package/dist/declarative-element/properties/per-instance.js +0 -32
package/README.md
CHANGED
|
@@ -169,13 +169,15 @@ import {defineElementNoInputs, html, listen} from 'element-vir';
|
|
|
169
169
|
|
|
170
170
|
export const MyWithUpdateState = defineElementNoInputs({
|
|
171
171
|
tagName: 'my-with-update-state',
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
172
|
+
state() {
|
|
173
|
+
return {
|
|
174
|
+
username: 'dev',
|
|
175
|
+
/**
|
|
176
|
+
* Use "as" to create state properties that can be types other than the initial value's
|
|
177
|
+
* type. This is particularly useful when, as below, the initial value is undefined.
|
|
178
|
+
*/
|
|
179
|
+
email: undefined as string | undefined,
|
|
180
|
+
};
|
|
179
181
|
},
|
|
180
182
|
render({state, updateState}) {
|
|
181
183
|
return html`
|
|
@@ -219,8 +221,8 @@ export const MyWithAssignment = defineElementNoInputs({
|
|
|
219
221
|
|
|
220
222
|
There are two other callbacks you can define that are sort of similar to lifecycle callbacks. They are much simpler than lifecycle callbacks however.
|
|
221
223
|
|
|
222
|
-
-
|
|
223
|
-
-
|
|
224
|
+
- `init`: called right before the first render and has all state and inputs setup. (This is similar to `connectedCallback` in standard HTMLElement classes but is fired much later, after inputs are assigned, to avoid race conditions.)
|
|
225
|
+
- `cleanup`: called when an element is removed from the DOM. (This is the same as the `disconnectedCallback` in standard HTMLElement classes.)
|
|
224
226
|
|
|
225
227
|
<!-- example-link: src/readme-examples/my-with-cleanup-callback.element.ts -->
|
|
226
228
|
|
|
@@ -229,24 +231,18 @@ import {defineElementNoInputs, html} from 'element-vir';
|
|
|
229
231
|
|
|
230
232
|
export const MyWithAssignmentCleanupCallback = defineElementNoInputs({
|
|
231
233
|
tagName: 'my-with-cleanup-callback',
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
},
|
|
235
|
-
init: ({updateState}) => {
|
|
236
|
-
updateState({
|
|
234
|
+
state() {
|
|
235
|
+
return {
|
|
237
236
|
intervalId: window.setInterval(() => console.info('hi'), 1000),
|
|
238
|
-
}
|
|
237
|
+
};
|
|
239
238
|
},
|
|
240
239
|
render() {
|
|
241
240
|
return html`
|
|
242
241
|
<h1>My App</h1>
|
|
243
242
|
`;
|
|
244
243
|
},
|
|
245
|
-
cleanup
|
|
244
|
+
cleanup({state}) {
|
|
246
245
|
window.clearInterval(state.intervalId);
|
|
247
|
-
updateState({
|
|
248
|
-
intervalId: undefined,
|
|
249
|
-
});
|
|
250
246
|
},
|
|
251
247
|
});
|
|
252
248
|
```
|
|
@@ -296,8 +292,10 @@ import {MyWithEvents} from './my-with-events.element.js';
|
|
|
296
292
|
|
|
297
293
|
export const MyWithEventListening = defineElementNoInputs({
|
|
298
294
|
tagName: 'my-with-event-listening',
|
|
299
|
-
|
|
300
|
-
|
|
295
|
+
state() {
|
|
296
|
+
return {
|
|
297
|
+
myNumber: -1,
|
|
298
|
+
};
|
|
301
299
|
},
|
|
302
300
|
render({state, updateState}) {
|
|
303
301
|
return html`
|
|
@@ -369,8 +367,8 @@ Host classes can be defined and used with type safety. Host classes are used to
|
|
|
369
367
|
|
|
370
368
|
Host classes are defined by passing an object to `hostClasses` at element definition time. Each property name in the `hostClasses` object creates a host class name (note that host class names must start with the element's tag name). Each value in the `hostClasses` object defines behavior for the host class:
|
|
371
369
|
|
|
372
|
-
-
|
|
373
|
-
-
|
|
370
|
+
- if the value is a callback, that host class will automatically be applied if the callback returns true after a render is executed.
|
|
371
|
+
- if the value is `false`, the host class is never automatically applied, it must be manually applied by consumers.
|
|
374
372
|
|
|
375
373
|
Apply host classes in the element's stylesheet by using a callback for the styles property:
|
|
376
374
|
|
|
@@ -381,8 +379,10 @@ import {css, defineElementNoInputs, html} from 'element-vir';
|
|
|
381
379
|
|
|
382
380
|
export const MyWithHostClassDefinition = defineElementNoInputs({
|
|
383
381
|
tagName: 'my-with-host-class-definition',
|
|
384
|
-
|
|
385
|
-
|
|
382
|
+
state() {
|
|
383
|
+
return {
|
|
384
|
+
myProp: 'hello there',
|
|
385
|
+
};
|
|
386
386
|
},
|
|
387
387
|
hostClasses: {
|
|
388
388
|
/**
|
|
@@ -629,12 +629,15 @@ async function loadSomething(endpoint: string): Promise<EndpointData> {
|
|
|
629
629
|
|
|
630
630
|
export const MyWithAsyncProp = defineElement<{endpoint: string}>()({
|
|
631
631
|
tagName: 'my-with-async-prop',
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
632
|
+
state() {
|
|
633
|
+
return {
|
|
634
|
+
data: asyncProp({
|
|
635
|
+
async updateCallback({endpoint}: {endpoint: string}) {
|
|
636
|
+
return loadSomething(endpoint);
|
|
637
|
+
},
|
|
638
|
+
}),
|
|
639
|
+
hi: '',
|
|
640
|
+
};
|
|
638
641
|
},
|
|
639
642
|
render({inputs, state}) {
|
|
640
643
|
/**
|
|
@@ -7,36 +7,30 @@ import { type EventsInitMap } from './properties/element-events.js';
|
|
|
7
7
|
import { type PropertyInitMapBase } from './properties/element-properties.js';
|
|
8
8
|
import { type HostClassesInitMap } from './properties/host-classes.js';
|
|
9
9
|
import { type StylesCallback } from './properties/styles.js';
|
|
10
|
-
import { type InitCallback, type RenderCallback } from './render-callback.js';
|
|
10
|
+
import { type InitCallback, type RenderCallback, type RenderParams } from './render-callback.js';
|
|
11
11
|
/**
|
|
12
12
|
* Initialization for an element-vir declarative element. This defines all the pieces required for
|
|
13
13
|
* rendering the element.
|
|
14
14
|
*
|
|
15
15
|
* @category Internal
|
|
16
16
|
*/
|
|
17
|
-
export type DeclarativeElementInit<TagName extends CustomElementTagName, Inputs extends PropertyInitMapBase,
|
|
17
|
+
export type DeclarativeElementInit<TagName extends CustomElementTagName, Inputs extends PropertyInitMapBase, State extends PropertyInitMapBase, EventsInit extends EventsInitMap, HostClassKeys extends BaseCssPropertyName<TagName>, CssVarKeys extends BaseCssPropertyName<TagName>, SlotNames extends ReadonlyArray<string>> = {
|
|
18
18
|
/**
|
|
19
19
|
* HTML tag name. This should not be used directly, as interpolating it with the html tagged
|
|
20
20
|
* template from this package is preferred.
|
|
21
21
|
*/
|
|
22
22
|
tagName: TagName;
|
|
23
23
|
/** Static styles. These should not and cannot change. */
|
|
24
|
-
styles?: CSSResult | StylesCallback<TagName, HostClassKeys, CssVarKeys
|
|
25
|
-
/**
|
|
26
|
-
* The definition of and initial values for the element's internal state. Note that this is
|
|
27
|
-
* defined statically: the init value will be the same for all instances of this element because
|
|
28
|
-
* it is only defined once.
|
|
29
|
-
*/
|
|
30
|
-
stateInitStatic?: StateInit;
|
|
24
|
+
styles?: CSSResult | StylesCallback<TagName, HostClassKeys, CssVarKeys> | undefined;
|
|
31
25
|
/** Events that the element can dispatch. (These can be thought of as "outputs".) */
|
|
32
|
-
events?: EventsInit;
|
|
33
|
-
slotNames?: SlotNames;
|
|
26
|
+
events?: EventsInit | undefined;
|
|
27
|
+
slotNames?: SlotNames | undefined;
|
|
34
28
|
/**
|
|
35
29
|
* HTML host classes. Values can be callbacks to determine when a host class should be defined,
|
|
36
30
|
* based on current instance state or inputs, or just false to indicate that the host class will
|
|
37
31
|
* only be manually set.
|
|
38
32
|
*/
|
|
39
|
-
hostClasses?: HostClassesInitMap<TagName, HostClassKeys, Inputs,
|
|
33
|
+
hostClasses?: HostClassesInitMap<TagName, HostClassKeys, Inputs, State> | undefined;
|
|
40
34
|
/**
|
|
41
35
|
* CSS Vars for the component. Keys of this object should be kebab-case and start with the
|
|
42
36
|
* element's tag name.
|
|
@@ -45,9 +39,17 @@ export type DeclarativeElementInit<TagName extends CustomElementTagName, Inputs
|
|
|
45
39
|
* then passed to the styles property, which must be a callback to take advantage of these.
|
|
46
40
|
*/
|
|
47
41
|
cssVars?: CssVarsInitMap<TagName, CssVarKeys>;
|
|
42
|
+
/**
|
|
43
|
+
* Make sure to define this at the top of your element init object or TypeScript will fail to
|
|
44
|
+
* infer the element's state type.
|
|
45
|
+
*
|
|
46
|
+
* Setup the element's initial state. This is only called once per element instance, before the
|
|
47
|
+
* first render. The return type of this method becomes the element's state type.
|
|
48
|
+
*/
|
|
49
|
+
state?: (params: Omit<RenderParams<TagName, Inputs, any, EventsInit, HostClassKeys, CssVarKeys, SlotNames>, 'state' | 'updateState'>) => Extract<keyof State, keyof HTMLElement> extends never ? Extract<keyof State, keyof Inputs> extends never ? State : `ERROR: Cannot define an element state property that clashes with input properties: ${Extract<keyof State, keyof Inputs> extends string | number | bigint | boolean | null | undefined ? Extract<keyof State, keyof Inputs> : ''}` : `ERROR: Cannot define an element state property that clashes with native HTMLElement properties: ${Extract<keyof State, keyof HTMLElement>}`;
|
|
48
50
|
/** Called as part of the first render call, before the first render call. */
|
|
49
|
-
init?: InitCallback<TagName, Inputs,
|
|
50
|
-
render: RenderCallback<TagName, Inputs,
|
|
51
|
-
cleanup?: InitCallback<TagName, Inputs,
|
|
51
|
+
init?: InitCallback<TagName, Inputs, State, EventsInit, HostClassKeys, CssVarKeys, SlotNames> | undefined;
|
|
52
|
+
render: RenderCallback<TagName, Inputs, State, EventsInit, HostClassKeys, CssVarKeys, SlotNames>;
|
|
53
|
+
cleanup?: InitCallback<TagName, Inputs, State, EventsInit, HostClassKeys, CssVarKeys, SlotNames> | undefined;
|
|
52
54
|
options?: Partial<DeclarativeElementDefinitionOptions> | undefined;
|
|
53
55
|
};
|
|
@@ -8,8 +8,7 @@ import { type DeclarativeElementDefinitionOptions } from './definition-options.j
|
|
|
8
8
|
import { type BaseCssPropertyName } from './properties/css-properties.js';
|
|
9
9
|
import { type CssVars } from './properties/css-vars.js';
|
|
10
10
|
import { type EventDescriptorMap, type EventsInitMap } from './properties/element-events.js';
|
|
11
|
-
import { type
|
|
12
|
-
import { type FlattenElementVirStateSetup } from './properties/element-vir-state-setup.js';
|
|
11
|
+
import { type PropertyInitMapBase } from './properties/element-properties.js';
|
|
13
12
|
import { type HostClassNamesMap } from './properties/host-classes.js';
|
|
14
13
|
import { type ObservableListenerMap } from './properties/property-proxy.js';
|
|
15
14
|
import { type RenderCallback, type RenderParams, type UpdateStateCallback } from './render-callback.js';
|
|
@@ -20,21 +19,21 @@ import { type SlotNameMap } from './slot-names.js';
|
|
|
20
19
|
*
|
|
21
20
|
* @category Internal
|
|
22
21
|
*/
|
|
23
|
-
export type DeclarativeElementHost<TagName extends CustomElementTagName = any, Inputs extends PropertyInitMapBase = any,
|
|
22
|
+
export type DeclarativeElementHost<TagName extends CustomElementTagName = any, Inputs extends PropertyInitMapBase = any, State extends PropertyInitMapBase = any, EventsInit extends EventsInitMap = any, HostClassKeys extends BaseCssPropertyName<TagName> = any, CssVarKeys extends BaseCssPropertyName<TagName> = any, SlotNames extends ReadonlyArray<string> = any> = SetRequiredAndNotNull<Omit<DeclarativeElement<TagName, Inputs, State, EventsInit, HostClassKeys, CssVarKeys, SlotNames>, Exclude<keyof StaticDeclarativeElementProperties<any, any, any, any, any, any, any>, keyof HTMLElement>>, 'shadowRoot'>;
|
|
24
23
|
/**
|
|
25
24
|
* The full definition for a declarative element.
|
|
26
25
|
*
|
|
27
26
|
* @category Internal
|
|
28
27
|
*/
|
|
29
|
-
export type DeclarativeElementDefinition<TagName extends CustomElementTagName = any, Inputs extends PropertyInitMapBase = any,
|
|
30
|
-
|
|
28
|
+
export type DeclarativeElementDefinition<TagName extends CustomElementTagName = any, Inputs extends PropertyInitMapBase = any, State extends PropertyInitMapBase = any, EventsInit extends EventsInitMap = any, HostClassKeys extends BaseCssPropertyName<TagName> = any, CssVarKeys extends BaseCssPropertyName<TagName> = any, SlotNames extends ReadonlyArray<string> = any> = (new () => DeclarativeElementHost<TagName, Inputs, State, EventsInit, HostClassKeys, CssVarKeys, SlotNames>) & StaticDeclarativeElementProperties<TagName, Inputs, State, EventsInit, HostClassKeys, CssVarKeys, SlotNames> & {
|
|
29
|
+
InstanceType: DeclarativeElementHost<TagName, Inputs, State, EventsInit, HostClassKeys, CssVarKeys, SlotNames>;
|
|
31
30
|
};
|
|
32
31
|
/**
|
|
33
32
|
* Abstract class base for all declarative elements.
|
|
34
33
|
*
|
|
35
34
|
* @category Internal
|
|
36
35
|
*/
|
|
37
|
-
export declare abstract class DeclarativeElement<TagName extends CustomElementTagName = any, Inputs extends PropertyInitMapBase = any,
|
|
36
|
+
export declare abstract class DeclarativeElement<TagName extends CustomElementTagName = any, Inputs extends PropertyInitMapBase = any, State extends PropertyInitMapBase = any, EventsInit extends EventsInitMap = any, HostClassKeys extends BaseCssPropertyName<TagName> = any, CssVarKeys extends BaseCssPropertyName<TagName> = any, SlotNames extends ReadonlyArray<string> = any> extends LitElement {
|
|
38
37
|
/**
|
|
39
38
|
* Assign inputs to an element instantiation. Use only on the opening tag.
|
|
40
39
|
*
|
|
@@ -53,11 +52,10 @@ export declare abstract class DeclarativeElement<TagName extends CustomElementTa
|
|
|
53
52
|
static readonly tagName: StaticDeclarativeElementProperties<CustomElementTagName, PropertyInitMapBase, PropertyInitMapBase, EventsInitMap, BaseCssPropertyName<CustomElementTagName>, BaseCssPropertyName<CustomElementTagName>, ReadonlyArray<string>>['tagName'];
|
|
54
53
|
static readonly styles: StaticDeclarativeElementProperties<CustomElementTagName, PropertyInitMapBase, PropertyInitMapBase, EventsInitMap, BaseCssPropertyName<CustomElementTagName>, BaseCssPropertyName<CustomElementTagName>, ReadonlyArray<string>>['styles'];
|
|
55
54
|
static readonly render: StaticDeclarativeElementProperties<CustomElementTagName, PropertyInitMapBase, PropertyInitMapBase, EventsInitMap, BaseCssPropertyName<CustomElementTagName>, BaseCssPropertyName<CustomElementTagName>, ReadonlyArray<string>>['render'];
|
|
56
|
-
static readonly
|
|
57
|
-
static readonly
|
|
58
|
-
static readonly
|
|
55
|
+
static readonly InputsType: StaticDeclarativeElementProperties<CustomElementTagName, PropertyInitMapBase, PropertyInitMapBase, EventsInitMap, BaseCssPropertyName<CustomElementTagName>, BaseCssPropertyName<CustomElementTagName>, ReadonlyArray<string>>['InputsType'];
|
|
56
|
+
static readonly StateType: StaticDeclarativeElementProperties<CustomElementTagName, PropertyInitMapBase, PropertyInitMapBase, EventsInitMap, BaseCssPropertyName<CustomElementTagName>, BaseCssPropertyName<CustomElementTagName>, ReadonlyArray<string>>['StateType'];
|
|
57
|
+
static readonly UpdateStateType: StaticDeclarativeElementProperties<CustomElementTagName, PropertyInitMapBase, PropertyInitMapBase, EventsInitMap, BaseCssPropertyName<CustomElementTagName>, BaseCssPropertyName<CustomElementTagName>, ReadonlyArray<string>>['UpdateStateType'];
|
|
59
58
|
static readonly events: StaticDeclarativeElementProperties<CustomElementTagName, PropertyInitMapBase, PropertyInitMapBase, EventsInitMap, BaseCssPropertyName<CustomElementTagName>, BaseCssPropertyName<CustomElementTagName>, ReadonlyArray<string>>['events'];
|
|
60
|
-
static readonly stateInitStatic: StaticDeclarativeElementProperties<CustomElementTagName, PropertyInitMapBase, PropertyInitMapBase, EventsInitMap, BaseCssPropertyName<CustomElementTagName>, BaseCssPropertyName<CustomElementTagName>, ReadonlyArray<string>>['stateInitStatic'];
|
|
61
59
|
static readonly init: StaticDeclarativeElementProperties<CustomElementTagName, PropertyInitMapBase, PropertyInitMapBase, EventsInitMap, BaseCssPropertyName<CustomElementTagName>, BaseCssPropertyName<CustomElementTagName>, ReadonlyArray<string>>['init'];
|
|
62
60
|
static readonly elementOptions: StaticDeclarativeElementProperties<CustomElementTagName, PropertyInitMapBase, PropertyInitMapBase, EventsInitMap, BaseCssPropertyName<CustomElementTagName>, BaseCssPropertyName<CustomElementTagName>, ReadonlyArray<string>>['elementOptions'];
|
|
63
61
|
static readonly hostClasses: StaticDeclarativeElementProperties<CustomElementTagName, PropertyInitMapBase, PropertyInitMapBase, EventsInitMap, BaseCssPropertyName<CustomElementTagName>, BaseCssPropertyName<CustomElementTagName>, ReadonlyArray<string>>['hostClasses'];
|
|
@@ -65,15 +63,15 @@ export declare abstract class DeclarativeElement<TagName extends CustomElementTa
|
|
|
65
63
|
static readonly slotNames: StaticDeclarativeElementProperties<CustomElementTagName, PropertyInitMapBase, PropertyInitMapBase, EventsInitMap, BaseCssPropertyName<CustomElementTagName>, BaseCssPropertyName<CustomElementTagName>, ReadonlyArray<string>>['slotNames'];
|
|
66
64
|
abstract _lastRenderError: Error | undefined;
|
|
67
65
|
abstract _internalRenderCount: number;
|
|
68
|
-
abstract _lastRenderedProps: Readonly<Pick<RenderParams<any, Inputs,
|
|
66
|
+
abstract _lastRenderedProps: Readonly<Pick<RenderParams<any, Inputs, State, any, any, any, any>, 'inputs' | 'state'>>;
|
|
69
67
|
/**
|
|
70
68
|
* Calls all destroy methods on all state properties, if they exist. This is automatically
|
|
71
69
|
* called whenever the element is detached.
|
|
72
70
|
*/
|
|
73
71
|
abstract destroy(): void;
|
|
74
72
|
abstract render(): unknown;
|
|
75
|
-
abstract readonly instanceState:
|
|
76
|
-
abstract readonly observablePropertyListenerMap: ObservableListenerMap<
|
|
73
|
+
abstract readonly instanceState: State;
|
|
74
|
+
abstract readonly observablePropertyListenerMap: ObservableListenerMap<State & Inputs>;
|
|
77
75
|
abstract readonly instanceInputs: Inputs;
|
|
78
76
|
/**
|
|
79
77
|
* Used to assign inputs to the given element. This can be externally called as an API for
|
|
@@ -83,7 +81,7 @@ export declare abstract class DeclarativeElement<TagName extends CustomElementTa
|
|
|
83
81
|
abstract assignInputs(inputs: EmptyObject extends Required<Inputs> ? never : Partial<Inputs>): void;
|
|
84
82
|
abstract _haveInputsBeenSet: boolean;
|
|
85
83
|
/** The element definition for this element instance. */
|
|
86
|
-
abstract readonly definition: DeclarativeElementDefinition<TagName, Inputs,
|
|
84
|
+
abstract readonly definition: DeclarativeElementDefinition<TagName, Inputs, State, EventsInit, HostClassKeys, CssVarKeys, SlotNames>;
|
|
87
85
|
}
|
|
88
86
|
/**
|
|
89
87
|
* The assign inputs method of a declarative element.
|
|
@@ -96,20 +94,19 @@ export type AssignMethod<Inputs extends PropertyInitMapBase> = IsAny<Inputs> ext
|
|
|
96
94
|
*
|
|
97
95
|
* @category Internal
|
|
98
96
|
*/
|
|
99
|
-
export type StaticDeclarativeElementProperties<TagName extends CustomElementTagName, Inputs extends PropertyInitMapBase,
|
|
97
|
+
export type StaticDeclarativeElementProperties<TagName extends CustomElementTagName, Inputs extends PropertyInitMapBase, State extends PropertyInitMapBase, EventsInit extends EventsInitMap, HostClassKeys extends BaseCssPropertyName<TagName>, CssVarKeys extends BaseCssPropertyName<TagName>, SlotNames extends ReadonlyArray<string>> = {
|
|
100
98
|
/** Assign inputs to an element directly on its interpolated tag. */
|
|
101
99
|
readonly assign: AssignMethod<Inputs>;
|
|
102
100
|
assignedInputs: Inputs | undefined;
|
|
103
101
|
/** Pass through the render callback for direct unit testability */
|
|
104
|
-
readonly render: RenderCallback<TagName, Inputs,
|
|
102
|
+
readonly render: RenderCallback<TagName, Inputs, State, EventsInit, HostClassKeys, CssVarKeys, SlotNames>;
|
|
105
103
|
readonly events: EventDescriptorMap<TagName, EventsInit>;
|
|
106
|
-
readonly stateInitStatic: ElementPropertyDescriptorMap<StateInit>;
|
|
107
104
|
readonly slotNames: SlotNameMap<SlotNames>;
|
|
108
|
-
readonly init: DeclarativeElementInit<TagName, Inputs,
|
|
105
|
+
readonly init: DeclarativeElementInit<TagName, Inputs, State, EventsInit, HostClassKeys, CssVarKeys, SlotNames>;
|
|
109
106
|
readonly elementOptions: DeclarativeElementDefinitionOptions;
|
|
110
|
-
readonly
|
|
111
|
-
readonly
|
|
112
|
-
readonly
|
|
107
|
+
readonly InputsType: Inputs;
|
|
108
|
+
readonly StateType: Readonly<State>;
|
|
109
|
+
readonly UpdateStateType: UpdateStateCallback<State>;
|
|
113
110
|
readonly hostClasses: HostClassNamesMap<string, HostClassKeys>;
|
|
114
111
|
readonly cssVars: CssVars<TagName, CssVarKeys>;
|
|
115
112
|
readonly tagName: string;
|
|
@@ -23,11 +23,10 @@ export class DeclarativeElement extends LitElement {
|
|
|
23
23
|
static tagName;
|
|
24
24
|
static styles;
|
|
25
25
|
static render;
|
|
26
|
-
static
|
|
27
|
-
static
|
|
28
|
-
static
|
|
26
|
+
static InputsType;
|
|
27
|
+
static StateType;
|
|
28
|
+
static UpdateStateType;
|
|
29
29
|
static events;
|
|
30
|
-
static stateInitStatic;
|
|
31
30
|
static init;
|
|
32
31
|
static elementOptions;
|
|
33
32
|
static hostClasses;
|
|
@@ -4,13 +4,6 @@ import { DeclarativeElementDefinition } from './declarative-element.js';
|
|
|
4
4
|
import { BaseCssPropertyName } from './properties/css-properties.js';
|
|
5
5
|
import { EventsInitMap } from './properties/element-events.js';
|
|
6
6
|
import { PropertyInitMapBase } from './properties/element-properties.js';
|
|
7
|
-
/**
|
|
8
|
-
* Verifies that the given {@link DeclarativeElementInit} for an element definition without inputs
|
|
9
|
-
* does not have any state properties that clash with built-in HTML element properties.
|
|
10
|
-
*
|
|
11
|
-
* @category Internal
|
|
12
|
-
*/
|
|
13
|
-
export type VerifiedElementNoInputsInit<TagName extends CustomElementTagName, Inputs extends PropertyInitMapBase, StateInit extends PropertyInitMapBase, EventsInit extends EventsInitMap, HostClassKeys extends BaseCssPropertyName<TagName>, CssVarKeys extends BaseCssPropertyName<TagName>, SlotNames extends ReadonlyArray<string>> = Extract<keyof StateInit, keyof HTMLElement> extends never ? DeclarativeElementInit<TagName, Inputs, StateInit, EventsInit, HostClassKeys, CssVarKeys, SlotNames> : 'ERROR: Cannot define an element state property that clashes with native HTMLElement properties.';
|
|
14
7
|
/**
|
|
15
8
|
* Defines an element without any inputs.
|
|
16
9
|
*
|
|
@@ -30,4 +23,4 @@ export type VerifiedElementNoInputsInit<TagName extends CustomElementTagName, In
|
|
|
30
23
|
* });
|
|
31
24
|
* ```
|
|
32
25
|
*/
|
|
33
|
-
export declare function defineElementNoInputs<const TagName extends CustomElementTagName = '-', Inputs extends PropertyInitMapBase = {},
|
|
26
|
+
export declare function defineElementNoInputs<const TagName extends CustomElementTagName = '-', Inputs extends PropertyInitMapBase = {}, State extends PropertyInitMapBase = {}, EventsInit extends EventsInitMap = {}, const HostClassKeys extends BaseCssPropertyName<TagName> = `${TagName}-`, const CssVarKeys extends BaseCssPropertyName<TagName> = `${TagName}-`, const SlotNames extends ReadonlyArray<string> = Readonly<[]>>(init: DeclarativeElementInit<TagName, Inputs, State, EventsInit, HostClassKeys, CssVarKeys, SlotNames>): DeclarativeElementDefinition<TagName, Inputs, State, EventsInit, HostClassKeys, CssVarKeys, SlotNames>;
|
|
@@ -33,9 +33,7 @@ import { createSlotNamesMap } from './slot-names.js';
|
|
|
33
33
|
* });
|
|
34
34
|
* ```
|
|
35
35
|
*/
|
|
36
|
-
export function defineElementNoInputs(
|
|
37
|
-
/** This as cast is safe only because of the following run-time type check. */
|
|
38
|
-
const init = initInput;
|
|
36
|
+
export function defineElementNoInputs(init) {
|
|
39
37
|
if (!check.isObject(init)) {
|
|
40
38
|
throw new TypeError('Cannot define element with non-object init: ${init}');
|
|
41
39
|
}
|
|
@@ -94,17 +92,20 @@ export function defineElementNoInputs(initInput) {
|
|
|
94
92
|
static cssVars = cssVars;
|
|
95
93
|
static init = init;
|
|
96
94
|
static slotNames = slotNamesMap;
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
throw new Error(`"instanceType" was called on ${init.tagName} as a value but it is only for types.`);
|
|
95
|
+
get InstanceType() {
|
|
96
|
+
throw new Error(`'InstanceType' was called on ${init.tagName} as a value but it is only a type.`);
|
|
100
97
|
}
|
|
101
|
-
static get
|
|
102
|
-
throw new Error(`
|
|
98
|
+
static get InputsType() {
|
|
99
|
+
throw new Error(`'InputsType' was called on ${init.tagName} as a value but it is only a type.`);
|
|
103
100
|
}
|
|
104
|
-
static get
|
|
105
|
-
throw new Error(`
|
|
101
|
+
static get StateType() {
|
|
102
|
+
throw new Error(`'StateType' was called on ${init.tagName} as a value but it is only a type.`);
|
|
103
|
+
}
|
|
104
|
+
static get UpdateStateType() {
|
|
105
|
+
throw new Error(`'UpdateStateType' was called on ${init.tagName} as a value but it is only a type.`);
|
|
106
106
|
}
|
|
107
107
|
_initCalled = false;
|
|
108
|
+
_stateCalled = false;
|
|
108
109
|
_hasRendered = false;
|
|
109
110
|
_lastRenderedProps = undefined;
|
|
110
111
|
_haveInputsBeenSet = false;
|
|
@@ -121,6 +122,17 @@ export function defineElementNoInputs(initInput) {
|
|
|
121
122
|
}
|
|
122
123
|
this._hasRendered = true;
|
|
123
124
|
const renderParams = this.createRenderParams();
|
|
125
|
+
if (!this._stateCalled && init.state) {
|
|
126
|
+
this._stateCalled = true;
|
|
127
|
+
const stateInit = init.state(renderParams);
|
|
128
|
+
if (stateInit instanceof Promise) {
|
|
129
|
+
throw new TypeError('init cannot be asynchronous');
|
|
130
|
+
}
|
|
131
|
+
getObjectTypedKeys(stateInit).forEach((stateKey) => {
|
|
132
|
+
bindReactiveProperty(this, stateKey);
|
|
133
|
+
this.instanceState[stateKey] = stateInit[stateKey];
|
|
134
|
+
});
|
|
135
|
+
}
|
|
124
136
|
if (!this._initCalled && init.init) {
|
|
125
137
|
this._initCalled = true;
|
|
126
138
|
if (init.init(renderParams) instanceof Promise) {
|
|
@@ -189,13 +201,6 @@ export function defineElementNoInputs(initInput) {
|
|
|
189
201
|
instanceState = createElementPropertyProxy(this, !elementOptions.allowPolymorphicState);
|
|
190
202
|
constructor() {
|
|
191
203
|
super();
|
|
192
|
-
const stateInitStatic =
|
|
193
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
194
|
-
init.stateInitStatic || {};
|
|
195
|
-
getObjectTypedKeys(stateInitStatic).forEach((stateKey) => {
|
|
196
|
-
bindReactiveProperty(this, stateKey);
|
|
197
|
-
this.instanceState[stateKey] = stateInitStatic[stateKey];
|
|
198
|
-
});
|
|
199
204
|
this.definition = anonymousClass;
|
|
200
205
|
}
|
|
201
206
|
};
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { CustomElementTagName } from './custom-tag-name.js';
|
|
2
|
+
import { DeclarativeElementInit } from './declarative-element-init.js';
|
|
2
3
|
import { DeclarativeElementDefinition } from './declarative-element.js';
|
|
3
|
-
import { VerifiedElementNoInputsInit } from './define-element-no-inputs.js';
|
|
4
4
|
import { BaseCssPropertyName } from './properties/css-properties.js';
|
|
5
5
|
import { EventsInitMap } from './properties/element-events.js';
|
|
6
6
|
import { PropertyInitMapBase } from './properties/element-properties.js';
|
|
7
7
|
/**
|
|
8
|
-
* Verifies that the given
|
|
9
|
-
*
|
|
10
|
-
* / input properties that clash with each other.
|
|
8
|
+
* Verifies that the given `Inputs` type does not clash with built-in HTMLElement properties. This
|
|
9
|
+
* is used within {@link defineElement}.
|
|
11
10
|
*
|
|
12
11
|
* @category Internal
|
|
13
12
|
*/
|
|
14
|
-
export type
|
|
13
|
+
export type DeclarativeElementInputErrorParams<Inputs extends PropertyInitMapBase> = Extract<keyof Inputs, keyof HTMLElement> extends never ? [] : [
|
|
14
|
+
'ERROR: Cannot define an element input property that clashes with native HTMLElement properties.'
|
|
15
|
+
];
|
|
15
16
|
/**
|
|
16
17
|
* Defines an element with inputs. If the element actually has no inputs, use
|
|
17
18
|
* {@link defineElementNoInputs} instead. Note that this function must be called twice, due to
|
|
@@ -33,4 +34,9 @@ export type VerifiedElementInit<TagName extends CustomElementTagName, Inputs ext
|
|
|
33
34
|
* });
|
|
34
35
|
* ```
|
|
35
36
|
*/
|
|
36
|
-
export declare function defineElement<Inputs extends PropertyInitMapBase = {}>(
|
|
37
|
+
export declare function defineElement<Inputs extends PropertyInitMapBase = {}>(
|
|
38
|
+
/**
|
|
39
|
+
* These `errorParams` is present when there are problems with the `Inputs` type. If it is
|
|
40
|
+
* present, the error should be fixed. This should always be empty.
|
|
41
|
+
*/
|
|
42
|
+
...errorParams: DeclarativeElementInputErrorParams<Inputs>): <const TagName extends CustomElementTagName, State extends PropertyInitMapBase = {}, EventsInit extends EventsInitMap = {}, const HostClassKeys extends BaseCssPropertyName<TagName> = `${TagName}-`, const CssVarKeys extends BaseCssPropertyName<TagName> = `${TagName}-`, const SlotNames extends ReadonlyArray<string> = Readonly<[]>>(initInput: DeclarativeElementInit<TagName, Inputs, State, EventsInit, HostClassKeys, CssVarKeys, SlotNames>) => DeclarativeElementDefinition<TagName, Inputs, State, EventsInit, HostClassKeys, CssVarKeys, SlotNames>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-empty-object-type */
|
|
2
|
-
import { check } from '@augment-vir/assert';
|
|
2
|
+
import { assert, check } from '@augment-vir/assert';
|
|
3
3
|
import { defineElementNoInputs } from './define-element-no-inputs.js';
|
|
4
4
|
/**
|
|
5
5
|
* Defines an element with inputs. If the element actually has no inputs, use
|
|
@@ -22,7 +22,13 @@ import { defineElementNoInputs } from './define-element-no-inputs.js';
|
|
|
22
22
|
* });
|
|
23
23
|
* ```
|
|
24
24
|
*/
|
|
25
|
-
export function defineElement(
|
|
25
|
+
export function defineElement(
|
|
26
|
+
/**
|
|
27
|
+
* These `errorParams` is present when there are problems with the `Inputs` type. If it is
|
|
28
|
+
* present, the error should be fixed. This should always be empty.
|
|
29
|
+
*/
|
|
30
|
+
...errorParams) {
|
|
31
|
+
assert.isEmpty(errorParams);
|
|
26
32
|
return (initInput) => {
|
|
27
33
|
const init = initInput;
|
|
28
34
|
if (!check.isObject(init)) {
|
|
@@ -2,7 +2,7 @@ import type { EmptyObject } from 'type-fest';
|
|
|
2
2
|
import { DirectiveResult } from '../../lit-exports/all-lit-exports.js';
|
|
3
3
|
import { PropertyInitMapBase } from '../properties/element-properties.js';
|
|
4
4
|
export type ElementDefinitionWithInputsType<InputsType extends PropertyInitMapBase = PropertyInitMapBase> = {
|
|
5
|
-
|
|
5
|
+
InputsType: InputsType;
|
|
6
6
|
};
|
|
7
7
|
/**
|
|
8
8
|
* Assign an object matching an element's inputs to its inputs.
|
|
@@ -12,7 +12,7 @@ export type ElementDefinitionWithInputsType<InputsType extends PropertyInitMapBa
|
|
|
12
12
|
* @example Html`<${MyElement} ${assign(MyElement, {value: 1})}>...` should be
|
|
13
13
|
* html`<${MyElement.assign({value: 1})}>...`
|
|
14
14
|
*/
|
|
15
|
-
export declare function assign<const SpecificDeclarativeElement extends ElementDefinitionWithInputsType>(declarativeElement: SpecificDeclarativeElement, inputsObject: EmptyObject extends Required<SpecificDeclarativeElement['
|
|
15
|
+
export declare function assign<const SpecificDeclarativeElement extends ElementDefinitionWithInputsType>(declarativeElement: SpecificDeclarativeElement, inputsObject: EmptyObject extends Required<SpecificDeclarativeElement['InputsType']> ? never : SpecificDeclarativeElement['InputsType']): DirectiveResult;
|
|
16
16
|
/**
|
|
17
17
|
* Assign an object matching an element's inputs to its inputs.
|
|
18
18
|
*
|
|
@@ -21,4 +21,4 @@ export declare function assign<const SpecificDeclarativeElement extends ElementD
|
|
|
21
21
|
* @example Html`<${MyElement} ${assign(MyElement, {value: 1})}>...` should be
|
|
22
22
|
* html`<${MyElement.assign({value: 1})}>...`
|
|
23
23
|
*/
|
|
24
|
-
export declare function assign<const SpecificDeclarativeElement extends ElementDefinitionWithInputsType, const SpecificInput extends SpecificDeclarativeElement['
|
|
24
|
+
export declare function assign<const SpecificDeclarativeElement extends ElementDefinitionWithInputsType, const SpecificInput extends SpecificDeclarativeElement['InputsType']>(inputsObject: SpecificInput extends typeof HTMLElement ? never : SpecificInput): DirectiveResult;
|
|
@@ -1,27 +1,74 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { ElementVirStateSetup } from '../properties/element-vir-state-setup.js';
|
|
1
|
+
import type { Overwrite } from '@augment-vir/common';
|
|
2
|
+
import { CallbackObservable, CallbackObservableInit, type AsyncValue } from 'observavir';
|
|
4
3
|
export type { AsyncValue } from 'observavir';
|
|
5
|
-
/**
|
|
6
|
-
|
|
4
|
+
/**
|
|
5
|
+
* The current state of an {@link AsyncProp}'s value.
|
|
6
|
+
*
|
|
7
|
+
* @category Internal
|
|
8
|
+
*/
|
|
9
|
+
export declare enum AsyncValueState {
|
|
10
|
+
/** The `.value` Promise has been rejected. */
|
|
11
|
+
Rejected = "rejected",
|
|
12
|
+
/** The `.value` Promise has not settled yet. */
|
|
13
|
+
Waiting = "waiting",
|
|
14
|
+
/** The `.value` Promise has been resolved into an awaited value. */
|
|
15
|
+
Resolved = "resolved"
|
|
7
16
|
}
|
|
8
17
|
/**
|
|
9
|
-
*
|
|
18
|
+
* Class for constructing async props. Do not use this directly as its internal types won't be
|
|
19
|
+
* inferred correctly. Instead use {@link asyncProp} an async prop or {@link AsyncProp} for types.
|
|
10
20
|
*
|
|
11
21
|
* @category Internal
|
|
12
22
|
*/
|
|
13
|
-
export
|
|
14
|
-
/**
|
|
15
|
-
|
|
23
|
+
export declare class InternalAsyncPropClass<Value, Params> extends CallbackObservable<Value, Params> {
|
|
24
|
+
/**
|
|
25
|
+
* The current `.value` if it has settled (into either a resolved value or an Error), or
|
|
26
|
+
* `undefined` if it has not.
|
|
27
|
+
*/
|
|
28
|
+
get resolvedValue(): Exclude<typeof this.value, Promise<any>> | undefined;
|
|
29
|
+
/** The state of the current `.value`. */
|
|
30
|
+
get state(): AsyncValueState;
|
|
31
|
+
/**
|
|
32
|
+
* Checks if the current `.value` has resolved (meaning the Promise has settled and it was not
|
|
33
|
+
* rejected). This type guards the current instance's `.value` property.
|
|
34
|
+
*/
|
|
35
|
+
isResolved(): this is Overwrite<this, {
|
|
36
|
+
value: Exclude<AsyncValue<Value>, Promise<any> | Error>;
|
|
37
|
+
}>;
|
|
38
|
+
/**
|
|
39
|
+
* Checks if the current `.value` has settled (meaning it is either a rejection error or a
|
|
40
|
+
* resolved value). This type guards the current instance's `.value` property.
|
|
41
|
+
*/
|
|
42
|
+
isSettled(): this is Overwrite<this, {
|
|
43
|
+
value: Exclude<AsyncValue<Value>, Promise<any>>;
|
|
44
|
+
}>;
|
|
45
|
+
/**
|
|
46
|
+
* Checks if the current `.value` has not settled yet settled (meaning it is still an unsettled
|
|
47
|
+
* Promise). This type guards the current instance's `.value` property.
|
|
48
|
+
*/
|
|
49
|
+
isWaiting(): this is Overwrite<this, {
|
|
50
|
+
value: Extract<AsyncValue<Value>, Promise<any> | Error>;
|
|
51
|
+
}>;
|
|
52
|
+
/**
|
|
53
|
+
* Checks if the current `.value` is a rejection error. This type guards the current instance's
|
|
54
|
+
* `.value` property.
|
|
55
|
+
*/
|
|
56
|
+
isError(): this is Overwrite<this, {
|
|
57
|
+
value: Extract<AsyncValue<Value>, Error>;
|
|
58
|
+
}>;
|
|
59
|
+
}
|
|
16
60
|
/**
|
|
17
|
-
* An async property created by {@link asyncProp} for use within declarative elements.
|
|
61
|
+
* An async property created by {@link asyncProp} for use within declarative elements. Do not use
|
|
62
|
+
* this directly as its internal types won't be inferred correctly.
|
|
18
63
|
*
|
|
19
64
|
* @category Internal
|
|
20
65
|
*/
|
|
21
|
-
export
|
|
66
|
+
export type AsyncProp<Value, Params> = Omit<InternalAsyncPropClass<Value, Params>,
|
|
67
|
+
/** Hide these properties to make the `AsyncProp` interface much simpler. */
|
|
68
|
+
'dispatch' | 'equalityCheck' | 'getListenerCount' | 'updateCallback' | 'removeListener' | 'removeAllListeners' | 'listenToEvent' | 'listen'>;
|
|
22
69
|
/**
|
|
23
70
|
* Create an async prop for a declarative element's state.
|
|
24
71
|
*
|
|
25
72
|
* @category Async
|
|
26
73
|
*/
|
|
27
|
-
export declare function asyncProp<Value, Params = void>(init?: CallbackObservableInit<Value, Params>):
|
|
74
|
+
export declare function asyncProp<Value, Params = void>(init?: CallbackObservableInit<Value, Params>): AsyncProp<Value, Params>;
|