element-vir 17.0.2 → 18.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/dist/declarative-element/declarative-element.d.ts +2 -2
- package/dist/declarative-element/define-element-no-inputs.js +2 -3
- package/dist/declarative-element/directives/async-prop.d.ts +3 -3
- package/dist/declarative-element/directives/async-prop.js +7 -7
- package/dist/declarative-element/directives/create-attribute-directive.d.ts +1 -1
- package/dist/declarative-element/directives/create-attribute-directive.js +3 -3
- package/dist/declarative-element/directives/render-async.directive.d.ts +5 -5
- package/dist/declarative-element/directives/test-id.directive.d.ts +3 -3
- package/dist/declarative-element/properties/element-events.js +1 -1
- package/dist/declarative-element/properties/element-updater-proxy.d.ts +2 -0
- package/dist/declarative-element/properties/element-updater-proxy.js +14 -12
- package/dist/declarative-element/properties/observable-prop/interval-observable-prop.d.ts +37 -0
- package/dist/declarative-element/properties/observable-prop/interval-observable-prop.js +55 -0
- package/dist/declarative-element/properties/observable-prop/observable-prop.d.ts +13 -0
- package/dist/declarative-element/properties/observable-prop/observable-prop.js +14 -0
- package/dist/declarative-element/properties/observable-prop/setter-observable-prop.d.ts +18 -0
- package/dist/declarative-element/properties/observable-prop/setter-observable-prop.js +42 -0
- package/dist/declarative-element/properties/observable-prop/updatable-observable-prop.d.ts +40 -0
- package/dist/declarative-element/properties/observable-prop/updatable-observable-prop.js +61 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +4 -2
- package/package.json +27 -24
- package/dist/declarative-element/properties/observable-property/create-observable-property.d.ts +0 -43
- package/dist/declarative-element/properties/observable-property/create-observable-property.js +0 -98
- package/dist/declarative-element/properties/observable-property/observable-property.d.ts +0 -12
- package/dist/declarative-element/properties/observable-property/observable-property.js +0 -13
|
@@ -9,7 +9,7 @@ import { EventDescriptorMap, EventsInitMap } from './properties/element-events';
|
|
|
9
9
|
import { ElementPropertyDescriptorMap, PropertyInitMapBase } from './properties/element-properties';
|
|
10
10
|
import { FlattenElementVirStateSetup } from './properties/element-vir-state-setup';
|
|
11
11
|
import { HostClassNamesMap } from './properties/host-classes';
|
|
12
|
-
import {
|
|
12
|
+
import { ObservablePropListenerMap } from './properties/observable-prop/observable-prop';
|
|
13
13
|
import type { RenderCallback, RenderParams, UpdateStateCallback } from './render-callback';
|
|
14
14
|
export type DeclarativeElementHost<TagName extends CustomElementTagName = any, Inputs extends PropertyInitMapBase = any, StateInit extends PropertyInitMapBase = any, EventsInit extends EventsInitMap = any, HostClassKeys extends BaseCssPropertyName<TagName> = any, CssVarKeys extends BaseCssPropertyName<TagName> = any> = RequiredAndNotNullBy<Omit<DeclarativeElement<TagName, Inputs, StateInit, EventsInit, HostClassKeys, CssVarKeys, any>, Exclude<keyof StaticDeclarativeElementProperties<any, any, any, any, any, any, any>, keyof HTMLElement>>, 'shadowRoot'>;
|
|
15
15
|
export type DeclarativeElementDefinition<TagName extends CustomElementTagName = any, Inputs extends PropertyInitMapBase = any, StateInit extends PropertyInitMapBase = any, EventsInit extends EventsInitMap = any, HostClassKeys extends BaseCssPropertyName<TagName> = any, CssVarKeys extends BaseCssPropertyName<TagName> = any, RenderOutputGeneric = any> = (new () => DeclarativeElementHost<TagName, Inputs, StateInit, EventsInit, HostClassKeys, CssVarKeys>) & StaticDeclarativeElementProperties<TagName, Inputs, StateInit, EventsInit, HostClassKeys, CssVarKeys, RenderOutputGeneric> & {
|
|
@@ -35,7 +35,7 @@ export declare abstract class DeclarativeElement<TagName extends CustomElementTa
|
|
|
35
35
|
abstract _lastRenderedProps: Pick<RenderParams<any, Inputs, StateInit, any, any, any>, 'inputs' | 'state'>;
|
|
36
36
|
abstract render(): unknown;
|
|
37
37
|
abstract readonly instanceState: FlattenElementVirStateSetup<StateInit>;
|
|
38
|
-
abstract readonly observablePropertyListenerMap:
|
|
38
|
+
abstract readonly observablePropertyListenerMap: ObservablePropListenerMap<StateInit & Inputs>;
|
|
39
39
|
abstract readonly instanceInputs: Inputs;
|
|
40
40
|
abstract assignInputs(inputs: {} extends Required<Inputs> ? never : Partial<Inputs>): void;
|
|
41
41
|
abstract _haveInputsBeenSet: boolean;
|
|
@@ -4,7 +4,6 @@ var __setFunctionName = (this && this.__setFunctionName) || function (f, name, p
|
|
|
4
4
|
};
|
|
5
5
|
import { ensureError, getObjectTypedKeys, kebabCaseToCamelCase, } from '@augment-vir/common';
|
|
6
6
|
import { defineCssVars } from 'lit-css-vars';
|
|
7
|
-
import { property } from 'lit/decorators.js';
|
|
8
7
|
import { css } from '../template-transforms/vir-css/vir-css';
|
|
9
8
|
import { DeclarativeElement, } from './declarative-element';
|
|
10
9
|
import { IgnoreInputsNotBeenSetBeforeWarningSymbol, defaultDeclarativeElementDefinitionOptions, } from './definition-options';
|
|
@@ -12,7 +11,7 @@ import { hasDeclarativeElementParent } from './has-declarative-element-parent';
|
|
|
12
11
|
import { assignInputs } from './properties/assign-inputs';
|
|
13
12
|
import { assertValidCssProperties } from './properties/css-properties';
|
|
14
13
|
import { createEventDescriptorMap } from './properties/element-events';
|
|
15
|
-
import { createElementUpdaterProxy } from './properties/element-updater-proxy';
|
|
14
|
+
import { bindReactiveProperty, createElementUpdaterProxy } from './properties/element-updater-proxy';
|
|
16
15
|
import { createHostClassNamesMap } from './properties/host-classes';
|
|
17
16
|
import { applyHostClasses, hostClassNamesToStylesInput } from './properties/styles';
|
|
18
17
|
import { createRenderParams } from './render-callback';
|
|
@@ -146,7 +145,7 @@ export function defineElementNoInputs(initInput) {
|
|
|
146
145
|
this.instanceState = createElementUpdaterProxy(this, !initInput.options?.allowPolymorphicState);
|
|
147
146
|
const stateInitStatic = initInput.stateInitStatic || {};
|
|
148
147
|
getObjectTypedKeys(stateInitStatic).forEach((stateKey) => {
|
|
149
|
-
|
|
148
|
+
bindReactiveProperty(this, stateKey);
|
|
150
149
|
this.instanceState[stateKey] = stateInitStatic[stateKey];
|
|
151
150
|
});
|
|
152
151
|
this.definition = anonymousClass;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { JsonCompatibleObject, MaybePromise } from '@augment-vir/common';
|
|
2
2
|
import { ElementVirStateSetup } from '../properties/element-vir-state-setup';
|
|
3
|
-
import {
|
|
3
|
+
import { ObservableProp } from '../properties/observable-prop/observable-prop';
|
|
4
4
|
export type AsyncPropValue<ValueType> = Error | MaybePromise<Awaited<ValueType>>;
|
|
5
5
|
export type AsyncPropTriggerInputBase = JsonCompatibleObject;
|
|
6
6
|
export type AsyncPropUpdateCallback<TriggerInput extends AsyncPropTriggerInputBase, UpdaterInput, ReturnType> = Exclude<TriggerInput, undefined> extends never ? () => ReturnType : Exclude<UpdaterInput, undefined> extends never ? (trigger: TriggerInput) => ReturnType : (trigger: TriggerInput, inputs: UpdaterInput) => ReturnType;
|
|
@@ -18,7 +18,7 @@ export type AsyncPropInit<ValueType, TriggerInput extends AsyncPropTriggerInputB
|
|
|
18
18
|
*/
|
|
19
19
|
updateCallback: AsyncPropUpdateCallback<TriggerInput, UpdaterInput, Promise<Awaited<ValueType>>>;
|
|
20
20
|
};
|
|
21
|
-
export type
|
|
21
|
+
export type AsyncObservableProp<ValueType, TriggerInput extends AsyncPropTriggerInputBase, UpdaterInput> = ObservableProp<AsyncPropValue<ValueType>> & {
|
|
22
22
|
setNewPromise(newPromise: Promise<Awaited<ValueType>>): void;
|
|
23
23
|
updateTrigger: AsyncPropUpdateCallback<TriggerInput, UpdaterInput, void>;
|
|
24
24
|
setResolvedValue(resolvedValue: Awaited<ValueType>): void;
|
|
@@ -28,4 +28,4 @@ export type AsyncObservableProperty<ValueType, TriggerInput extends AsyncPropTri
|
|
|
28
28
|
*/
|
|
29
29
|
forceUpdate: AsyncPropUpdateCallback<TriggerInput, UpdaterInput, void>;
|
|
30
30
|
};
|
|
31
|
-
export declare function asyncProp<ValueType, TriggerInput extends AsyncPropTriggerInputBase = {}, UpdaterInput = undefined>(...args: [AsyncPropInit<ValueType, TriggerInput, UpdaterInput>] | []): ElementVirStateSetup<
|
|
31
|
+
export declare function asyncProp<ValueType, TriggerInput extends AsyncPropTriggerInputBase = {}, UpdaterInput = undefined>(...args: [AsyncPropInit<ValueType, TriggerInput, UpdaterInput>] | []): ElementVirStateSetup<AsyncObservableProp<ValueType, TriggerInput, UpdaterInput>>;
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { areJsonEqual, createDeferredPromiseWrapper, ensureError, } from '@augment-vir/common';
|
|
2
|
-
import {
|
|
2
|
+
import { createSetterObservableProp } from '../properties/observable-prop/setter-observable-prop';
|
|
3
3
|
const notSetSymbol = Symbol('not set');
|
|
4
4
|
function setupAsyncProp(init) {
|
|
5
5
|
let lastTrigger = notSetSymbol;
|
|
6
6
|
let lastSetPromise;
|
|
7
7
|
const promiseUpdater = init && 'updateCallback' in init ? init.updateCallback : undefined;
|
|
8
8
|
let waitingForValuePromise = createDeferredPromiseWrapper();
|
|
9
|
-
const
|
|
9
|
+
const baseObservableProp = createSetterObservableProp(waitingForValuePromise.promise);
|
|
10
10
|
function resetWaitingForValuePromise() {
|
|
11
11
|
waitingForValuePromise = createDeferredPromiseWrapper();
|
|
12
|
-
|
|
12
|
+
baseObservableProp.setValue(waitingForValuePromise.promise);
|
|
13
13
|
}
|
|
14
14
|
function resolveValue(value) {
|
|
15
15
|
waitingForValuePromise.resolve(value);
|
|
16
|
-
|
|
16
|
+
baseObservableProp.setValue(value);
|
|
17
17
|
}
|
|
18
18
|
function rejectValue(error) {
|
|
19
19
|
waitingForValuePromise.reject(error);
|
|
20
|
-
|
|
20
|
+
baseObservableProp.setValue(error);
|
|
21
21
|
}
|
|
22
22
|
function setPromise(newPromise) {
|
|
23
23
|
if (newPromise === lastSetPromise) {
|
|
@@ -89,7 +89,7 @@ function setupAsyncProp(init) {
|
|
|
89
89
|
setPromise(newPromise);
|
|
90
90
|
},
|
|
91
91
|
setResolvedValue(value) {
|
|
92
|
-
if (value !==
|
|
92
|
+
if (value !== baseObservableProp.value) {
|
|
93
93
|
if (waitingForValuePromise.isSettled()) {
|
|
94
94
|
resetWaitingForValuePromise();
|
|
95
95
|
}
|
|
@@ -108,7 +108,7 @@ function setupAsyncProp(init) {
|
|
|
108
108
|
throw new Error('Cannot run forceUpdate when updateCallback was not set on the asyncProp.');
|
|
109
109
|
}),
|
|
110
110
|
};
|
|
111
|
-
return Object.assign(
|
|
111
|
+
return Object.assign(baseObservableProp, extraProperties);
|
|
112
112
|
}
|
|
113
113
|
export function asyncProp(...args) {
|
|
114
114
|
return {
|
|
@@ -4,7 +4,7 @@ export declare function createAttributeDirective(attributeName: string): {
|
|
|
4
4
|
attributeDirective(attributeValue: string): import("lit-html/directive").DirectiveResult<{
|
|
5
5
|
new (partInfo: PartInfo): {
|
|
6
6
|
readonly element: Element;
|
|
7
|
-
render(
|
|
7
|
+
render(attributeValue: string): symbol;
|
|
8
8
|
readonly _$isConnected: boolean;
|
|
9
9
|
update(_part: import("lit-html").Part, props: unknown[]): unknown;
|
|
10
10
|
};
|
|
@@ -7,10 +7,10 @@ export function createAttributeDirective(attributeName) {
|
|
|
7
7
|
class extends Directive {
|
|
8
8
|
constructor(partInfo) {
|
|
9
9
|
super(partInfo);
|
|
10
|
-
this.element = extractElement(partInfo,
|
|
10
|
+
this.element = extractElement(partInfo, attributeName);
|
|
11
11
|
}
|
|
12
|
-
render(
|
|
13
|
-
this.element.setAttribute(attributeName,
|
|
12
|
+
render(attributeValue) {
|
|
13
|
+
this.element.setAttribute(attributeName, attributeValue);
|
|
14
14
|
return noChange;
|
|
15
15
|
}
|
|
16
16
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare function renderAsync<T, FallbackResult, ResolutionRenderResult = never, ErrorRenderResult = never>(asyncProp:
|
|
3
|
-
export declare function renderAsync<T, FallbackResult, ResolutionRenderResult = never, ErrorRenderResult = never>(asyncProp:
|
|
4
|
-
export declare function renderAsync<T, FallbackResult, ResolutionRenderResult = never, ErrorRenderResult = never>(asyncProp:
|
|
5
|
-
export declare function renderAsync<T, FallbackResult, ResolutionRenderResult = never, ErrorRenderResult = never>(asyncProp:
|
|
1
|
+
import { AsyncObservableProp } from './async-prop';
|
|
2
|
+
export declare function renderAsync<T, FallbackResult, ResolutionRenderResult = never, ErrorRenderResult = never>(asyncProp: AsyncObservableProp<T, any, any>, fallback: FallbackResult, resolutionRender: (resolved: Awaited<T>) => ResolutionRenderResult, errorRender: (error: Error) => ErrorRenderResult): FallbackResult | ResolutionRenderResult | ErrorRenderResult;
|
|
3
|
+
export declare function renderAsync<T, FallbackResult, ResolutionRenderResult = never, ErrorRenderResult = never>(asyncProp: AsyncObservableProp<T, any, any>, fallback: FallbackResult, resolutionRender: (resolved: Awaited<T>) => ResolutionRenderResult, errorRender?: undefined): FallbackResult | ResolutionRenderResult | string;
|
|
4
|
+
export declare function renderAsync<T, FallbackResult, ResolutionRenderResult = never, ErrorRenderResult = never>(asyncProp: AsyncObservableProp<T, any, any>, fallback: FallbackResult, resolutionRender: undefined, errorRender: (error: Error) => ErrorRenderResult): FallbackResult | Awaited<T> | ErrorRenderResult;
|
|
5
|
+
export declare function renderAsync<T, FallbackResult, ResolutionRenderResult = never, ErrorRenderResult = never>(asyncProp: AsyncObservableProp<T, any, any>, fallback: FallbackResult, resolutionRender?: undefined, errorRender?: undefined): FallbackResult | Awaited<T> | string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export declare const testId: (attributeValue: string) => import("
|
|
2
|
-
new (partInfo: import("
|
|
1
|
+
export declare const testId: (attributeValue: string) => import("lit-html/directive").DirectiveResult<{
|
|
2
|
+
new (partInfo: import("lit-html/directive").PartInfo): {
|
|
3
3
|
readonly element: Element;
|
|
4
|
-
render(
|
|
4
|
+
render(attributeValue: string): symbol;
|
|
5
5
|
readonly _$isConnected: boolean;
|
|
6
6
|
update(_part: import("lit-html").Part, props: unknown[]): unknown;
|
|
7
7
|
};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import { DeclarativeElement } from '../declarative-element';
|
|
2
2
|
import { PropertyInitMapBase } from './element-properties';
|
|
3
|
+
/** Binds the given property key as a reactive property on the given element. */
|
|
4
|
+
export declare function bindReactiveProperty(element: HTMLElement, propertyKey: PropertyKey): void;
|
|
3
5
|
export declare function createElementUpdaterProxy<PropertyInitGeneric extends PropertyInitMapBase>(element: DeclarativeElement, verifyExists: boolean): PropertyInitGeneric;
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { property } from 'lit/decorators.js';
|
|
2
2
|
import { isElementVirStateSetup } from './element-vir-state-setup';
|
|
3
|
-
import {
|
|
3
|
+
import { isObservableProp } from './observable-prop/observable-prop';
|
|
4
|
+
/** Binds the given property key as a reactive property on the given element. */
|
|
5
|
+
export function bindReactiveProperty(element, propertyKey) {
|
|
6
|
+
if (!(propertyKey in element)) {
|
|
7
|
+
property()(element, propertyKey);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
4
10
|
function assertValidPropertyName(propKey, element, elementTagName) {
|
|
5
11
|
if (typeof propKey !== 'string' && typeof propKey !== 'number' && typeof propKey !== 'symbol') {
|
|
6
12
|
throw new Error(`Property name must be a string, got type '${typeof propKey}' from: '${String(propKey)}' for '${elementTagName.toLowerCase()}'`);
|
|
@@ -21,11 +27,7 @@ export function createElementUpdaterProxy(element, verifyExists) {
|
|
|
21
27
|
assertValidPropertyName(propertyKey, element, element.tagName);
|
|
22
28
|
}
|
|
23
29
|
else {
|
|
24
|
-
|
|
25
|
-
* No need to check if it's already a property or not, as the property function already
|
|
26
|
-
* makes that check.
|
|
27
|
-
*/
|
|
28
|
-
property()(element, propertyKey);
|
|
30
|
+
bindReactiveProperty(element, propertyKey);
|
|
29
31
|
}
|
|
30
32
|
}
|
|
31
33
|
function valueGetter(target, propertyKey) {
|
|
@@ -34,7 +36,7 @@ export function createElementUpdaterProxy(element, verifyExists) {
|
|
|
34
36
|
}
|
|
35
37
|
const propsProxy = new Proxy({}, {
|
|
36
38
|
get: valueGetter,
|
|
37
|
-
set
|
|
39
|
+
set(target, propertyKey, rawNewValue) {
|
|
38
40
|
const newValue = isElementVirStateSetup(rawNewValue)
|
|
39
41
|
? rawNewValue._elementVirStateSetup()
|
|
40
42
|
: rawNewValue;
|
|
@@ -51,12 +53,12 @@ export function createElementUpdaterProxy(element, verifyExists) {
|
|
|
51
53
|
}
|
|
52
54
|
const existingPropertyListener = element.observablePropertyListenerMap[propertyKey];
|
|
53
55
|
if (oldValue !== newValue &&
|
|
54
|
-
|
|
56
|
+
isObservableProp(oldValue) &&
|
|
55
57
|
existingPropertyListener?.length) {
|
|
56
58
|
/** Stop listening to the old value now that we have a new value */
|
|
57
59
|
oldValue.removeListener(existingPropertyListener);
|
|
58
60
|
}
|
|
59
|
-
if (
|
|
61
|
+
if (isObservableProp(newValue)) {
|
|
60
62
|
/** If we're using an existing observable property */
|
|
61
63
|
if (existingPropertyListener) {
|
|
62
64
|
newValue.addListener(existingPropertyListener);
|
|
@@ -69,14 +71,14 @@ export function createElementUpdaterProxy(element, verifyExists) {
|
|
|
69
71
|
newValue.addListener(newListener);
|
|
70
72
|
}
|
|
71
73
|
}
|
|
72
|
-
else if (
|
|
74
|
+
else if (isObservableProp(oldValue)) {
|
|
73
75
|
/** Clear out old listener that is no longer used. */
|
|
74
76
|
element.observablePropertyListenerMap[propertyKey] = undefined;
|
|
75
77
|
}
|
|
76
78
|
setValueOnElement(newValue);
|
|
77
79
|
return true;
|
|
78
80
|
},
|
|
79
|
-
ownKeys
|
|
81
|
+
ownKeys(target) {
|
|
80
82
|
return Reflect.ownKeys(target);
|
|
81
83
|
},
|
|
82
84
|
getOwnPropertyDescriptor(target, propertyName) {
|
|
@@ -91,7 +93,7 @@ export function createElementUpdaterProxy(element, verifyExists) {
|
|
|
91
93
|
}
|
|
92
94
|
return undefined;
|
|
93
95
|
},
|
|
94
|
-
has
|
|
96
|
+
has(target, propertyName) {
|
|
95
97
|
return Reflect.has(target, propertyName);
|
|
96
98
|
},
|
|
97
99
|
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Duration, DurationUnit } from 'date-vir';
|
|
2
|
+
import { TriggerUpdateFunction, UpdatableObservableProp, UpdatableObservablePropSetup } from './updatable-observable-prop';
|
|
3
|
+
export type IntervalObservablePropSetup<ValueType, UpdateInputType> = UpdatableObservablePropSetup<ValueType, UpdateInputType> & {
|
|
4
|
+
/** Update interval. */
|
|
5
|
+
updateInterval: Duration<DurationUnit.Milliseconds>;
|
|
6
|
+
/**
|
|
7
|
+
* If set to true, the interval observable prop will not automatically start its internal
|
|
8
|
+
* interval.
|
|
9
|
+
*/
|
|
10
|
+
startPaused?: boolean | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* The minimum duration between triggers. If an automatic or manual trigger happens twice within
|
|
13
|
+
* this duration, the second one will not do anything.
|
|
14
|
+
*/
|
|
15
|
+
rateLimit?: Duration<DurationUnit.Milliseconds> | undefined;
|
|
16
|
+
};
|
|
17
|
+
export type IntervalObservableProp<ValueType, UpdateInputType> = Omit<UpdatableObservableProp<ValueType, UpdateInputType>, 'triggerUpdate'> & {
|
|
18
|
+
/** Manually force the observable prop to update outside of its normal interval. */
|
|
19
|
+
forceUpdate: TriggerUpdateFunction<ValueType, UpdateInputType>;
|
|
20
|
+
/**
|
|
21
|
+
* Pauses the update interval, if it isn't already paused. Use .resumeInterval() to start the
|
|
22
|
+
* interval again. Under the hood, this actually clears the interval entirely.
|
|
23
|
+
*/
|
|
24
|
+
pauseInterval(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Resumes the update interval if it was paused. Under the hood, this creates a new interval
|
|
27
|
+
* entirely, as .pauseInterval() actually clears it.
|
|
28
|
+
*/
|
|
29
|
+
resumeInterval(): void;
|
|
30
|
+
/** Cleans up the interval observable prop. */
|
|
31
|
+
destroy(): void;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* This creates an updatable observable prop that will automatically update itself at the given
|
|
35
|
+
* interval.
|
|
36
|
+
*/
|
|
37
|
+
export declare function createIntervalObservableProp<ValueType, UpdateInputType = undefined>(setup: IntervalObservablePropSetup<ValueType, UpdateInputType>): IntervalObservableProp<ValueType, UpdateInputType>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { createUpdatableObservableProp, } from './updatable-observable-prop';
|
|
2
|
+
/**
|
|
3
|
+
* This creates an updatable observable prop that will automatically update itself at the given
|
|
4
|
+
* interval.
|
|
5
|
+
*/
|
|
6
|
+
export function createIntervalObservableProp(setup) {
|
|
7
|
+
let latestInputs = setup.initInput;
|
|
8
|
+
const baseObservableProp = createUpdatableObservableProp(setup);
|
|
9
|
+
let latestIntervalId = undefined;
|
|
10
|
+
let lastUpdateTimestamp = 0;
|
|
11
|
+
const shouldRunInterval = setup.updateInterval.milliseconds > 0 &&
|
|
12
|
+
Math.abs(setup.updateInterval.milliseconds) !== Infinity;
|
|
13
|
+
let lastOutput = baseObservableProp.value;
|
|
14
|
+
baseObservableProp.addListener((value) => (lastOutput = value));
|
|
15
|
+
function updateValue(...newInputs) {
|
|
16
|
+
if (newInputs.length) {
|
|
17
|
+
latestInputs = newInputs[0];
|
|
18
|
+
}
|
|
19
|
+
const now = Date.now();
|
|
20
|
+
const shouldIgnoreDueToRateLimiting = setup.rateLimit &&
|
|
21
|
+
setup.rateLimit.milliseconds > 0 &&
|
|
22
|
+
now - lastUpdateTimestamp < setup.rateLimit?.milliseconds;
|
|
23
|
+
if (shouldIgnoreDueToRateLimiting) {
|
|
24
|
+
return lastOutput;
|
|
25
|
+
}
|
|
26
|
+
lastUpdateTimestamp = now;
|
|
27
|
+
return baseObservableProp.triggerUpdate(latestInputs);
|
|
28
|
+
}
|
|
29
|
+
function resumeInterval() {
|
|
30
|
+
if (shouldRunInterval && latestIntervalId == undefined) {
|
|
31
|
+
latestIntervalId = window.setInterval(() => {
|
|
32
|
+
updateValue();
|
|
33
|
+
}, Math.ceil(setup.updateInterval.milliseconds));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function pauseInterval() {
|
|
37
|
+
if (latestIntervalId != undefined) {
|
|
38
|
+
window.clearInterval(latestIntervalId);
|
|
39
|
+
latestIntervalId = undefined;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (!setup.startPaused) {
|
|
43
|
+
resumeInterval();
|
|
44
|
+
}
|
|
45
|
+
const observablePropertyWithInterval = Object.assign(baseObservableProp, {
|
|
46
|
+
forceUpdate: updateValue,
|
|
47
|
+
pauseInterval,
|
|
48
|
+
resumeInterval,
|
|
49
|
+
destroy() {
|
|
50
|
+
pauseInterval();
|
|
51
|
+
baseObservableProp.destroy();
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
return observablePropertyWithInterval;
|
|
55
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PropertyInitMapBase } from '../element-properties';
|
|
2
|
+
export type ObservablePropListener<T> = (value: T) => void;
|
|
3
|
+
export type ObservablePropListenerMap<OriginalPropertyMap extends PropertyInitMapBase> = Partial<Record<keyof OriginalPropertyMap, ObservablePropListener<any> | undefined>>;
|
|
4
|
+
export type ObservableProp<ValueType> = {
|
|
5
|
+
/** Add the given listener. Returns a callback which will remove the listener. */
|
|
6
|
+
addListener(listener: ObservablePropListener<ValueType>): () => boolean;
|
|
7
|
+
/** Remove the given listener by reference. */
|
|
8
|
+
removeListener(listener: ObservablePropListener<ValueType>): boolean;
|
|
9
|
+
destroy(): void;
|
|
10
|
+
value: ValueType;
|
|
11
|
+
};
|
|
12
|
+
export declare const basicObservablePropShape: import("object-shape-tester").ShapeDefinition<ObservableProp<any>, false>;
|
|
13
|
+
export declare function isObservableProp<ValueType = unknown>(input: unknown): input is ObservableProp<ValueType>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { defineShape, isValidShape, unknownShape } from 'object-shape-tester';
|
|
2
|
+
export const basicObservablePropShape = defineShape({
|
|
3
|
+
addListener() {
|
|
4
|
+
return () => false;
|
|
5
|
+
},
|
|
6
|
+
removeListener() {
|
|
7
|
+
return false;
|
|
8
|
+
},
|
|
9
|
+
destroy() { },
|
|
10
|
+
value: unknownShape(),
|
|
11
|
+
});
|
|
12
|
+
export function isObservableProp(input) {
|
|
13
|
+
return isValidShape(input, basicObservablePropShape, { allowExtraKeys: true });
|
|
14
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { referenceEqualityCheck } from '../../../util/equality';
|
|
2
|
+
import { ObservableProp } from './observable-prop';
|
|
3
|
+
/** A simple ObservableProp with a setter. */
|
|
4
|
+
export type SetterObservableProp<ValueType> = ObservableProp<ValueType> & {
|
|
5
|
+
setValue(newValue: ValueType): void;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Easy and quick way to create an ObservableProp. Includes a setValue method with equality checking
|
|
9
|
+
* for easily emitting changes.
|
|
10
|
+
*/
|
|
11
|
+
export declare function createSetterObservableProp<ValueType>(
|
|
12
|
+
/** The value at which the `SetterObservableProp` will start at. */
|
|
13
|
+
initValue: ValueType,
|
|
14
|
+
/**
|
|
15
|
+
* The function used to determine if a set value is actually new. Defaults to simple reference
|
|
16
|
+
* equality.
|
|
17
|
+
*/
|
|
18
|
+
equalityCallback?: typeof referenceEqualityCheck): SetterObservableProp<ValueType>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { referenceEqualityCheck } from '../../../util/equality';
|
|
2
|
+
/**
|
|
3
|
+
* Easy and quick way to create an ObservableProp. Includes a setValue method with equality checking
|
|
4
|
+
* for easily emitting changes.
|
|
5
|
+
*/
|
|
6
|
+
export function createSetterObservableProp(
|
|
7
|
+
/** The value at which the `SetterObservableProp` will start at. */
|
|
8
|
+
initValue,
|
|
9
|
+
/**
|
|
10
|
+
* The function used to determine if a set value is actually new. Defaults to simple reference
|
|
11
|
+
* equality.
|
|
12
|
+
*/
|
|
13
|
+
equalityCallback = referenceEqualityCheck) {
|
|
14
|
+
const listeners = new Set();
|
|
15
|
+
function fireListeners() {
|
|
16
|
+
listeners.forEach((listener) => listener(observableProperty.value));
|
|
17
|
+
}
|
|
18
|
+
function removeListener(listener) {
|
|
19
|
+
return listeners.delete(listener);
|
|
20
|
+
}
|
|
21
|
+
const observableProperty = {
|
|
22
|
+
value: initValue,
|
|
23
|
+
setValue(newValue) {
|
|
24
|
+
if (!equalityCallback(observableProperty.value, newValue)) {
|
|
25
|
+
observableProperty.value = newValue;
|
|
26
|
+
fireListeners();
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
addListener(listener) {
|
|
30
|
+
const shouldAddListener = !listeners.has(listener);
|
|
31
|
+
if (shouldAddListener) {
|
|
32
|
+
listeners.add(listener);
|
|
33
|
+
}
|
|
34
|
+
return () => removeListener(listener);
|
|
35
|
+
},
|
|
36
|
+
removeListener,
|
|
37
|
+
destroy() {
|
|
38
|
+
listeners.clear();
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
return observableProperty;
|
|
42
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { referenceEqualityCheck } from '../../../util/equality';
|
|
2
|
+
import { ObservableProp } from './observable-prop';
|
|
3
|
+
/** Callback for updating the `UpdatableObservableProp`. */
|
|
4
|
+
export type UpdaterCallback<ValueType, UpdateInputType> = (inputs: UpdateInputType, lastValue: ValueType | undefined) => ValueType;
|
|
5
|
+
/** Function for updating the `UpdatableObservableProp`. */
|
|
6
|
+
export type TriggerUpdateFunction<ValueType, UpdateInputType> = (inputs?: UpdateInputType) => ValueType;
|
|
7
|
+
export type UpdatableObservableProp<ValueType, UpdateInputType> = ObservableProp<ValueType | Awaited<ValueType>> & {
|
|
8
|
+
/**
|
|
9
|
+
* Trigger the `UpdatableObservableProp` to update itself. Requires the inputs that the
|
|
10
|
+
* observable prop's updateCallback requires.
|
|
11
|
+
*/
|
|
12
|
+
triggerUpdate: TriggerUpdateFunction<ValueType, UpdateInputType>;
|
|
13
|
+
/** The number of times that the prop has been updated. Mostly only useful for debugging. */
|
|
14
|
+
readonly updateCount: number;
|
|
15
|
+
/**
|
|
16
|
+
* The last value that was resolved. This will be undefined if there has never, so far, been a
|
|
17
|
+
* resolved value.
|
|
18
|
+
*/
|
|
19
|
+
latestResolvedValue: ValueType extends Promise<any> ? Awaited<ValueType> | undefined : ValueType;
|
|
20
|
+
};
|
|
21
|
+
/** Setup required for creating an `UpdatableObservableProp`. */
|
|
22
|
+
export type UpdatableObservablePropSetup<ValueType, UpdateInputType> = {
|
|
23
|
+
/** Initial value for the observable prop. */
|
|
24
|
+
initInput: UpdateInputType;
|
|
25
|
+
/** The callback which will be called in order to update the observable prop. */
|
|
26
|
+
updateCallback: UpdaterCallback<ValueType, UpdateInputType>;
|
|
27
|
+
/**
|
|
28
|
+
* The function used to determine if a new value is actually new. Defaults to simple reference
|
|
29
|
+
* equality.
|
|
30
|
+
*/
|
|
31
|
+
equalityCallback?: typeof referenceEqualityCheck | undefined;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* An ObservableProp that requires an updater callback on setup. Future updates then call this
|
|
35
|
+
* updater callback rather than directly setting a value (`SetterObservableProp` merely sets a
|
|
36
|
+
* value).
|
|
37
|
+
*/
|
|
38
|
+
export declare function createUpdatableObservableProp<ValueType, UpdateInputType = undefined>(
|
|
39
|
+
/** Setup object required for creating the UpdatableObservableProp. */
|
|
40
|
+
setup: UpdatableObservablePropSetup<ValueType, UpdateInputType>): UpdatableObservableProp<ValueType, UpdateInputType>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { referenceEqualityCheck } from '../../../util/equality';
|
|
2
|
+
import { createSetterObservableProp } from './setter-observable-prop';
|
|
3
|
+
/**
|
|
4
|
+
* An ObservableProp that requires an updater callback on setup. Future updates then call this
|
|
5
|
+
* updater callback rather than directly setting a value (`SetterObservableProp` merely sets a
|
|
6
|
+
* value).
|
|
7
|
+
*/
|
|
8
|
+
export function createUpdatableObservableProp(
|
|
9
|
+
/** Setup object required for creating the UpdatableObservableProp. */
|
|
10
|
+
setup) {
|
|
11
|
+
const areEqual = setup.equalityCallback ?? referenceEqualityCheck;
|
|
12
|
+
let lastInputs = setup.initInput;
|
|
13
|
+
let internalUpdateCount = 0;
|
|
14
|
+
const innerSimpleObservableProp = createSetterObservableProp(undefined, areEqual);
|
|
15
|
+
function updateValue(...inputs) {
|
|
16
|
+
internalUpdateCount++;
|
|
17
|
+
if (inputs.length) {
|
|
18
|
+
lastInputs = inputs[0];
|
|
19
|
+
}
|
|
20
|
+
const newValue = setup.updateCallback(lastInputs, innerSimpleObservableProp.value);
|
|
21
|
+
if (newValue instanceof Promise) {
|
|
22
|
+
const wrappedPromise = new Promise(async (resolve, reject) => {
|
|
23
|
+
try {
|
|
24
|
+
const resolvedValue = await newValue;
|
|
25
|
+
observableWithUpdater.latestResolvedValue =
|
|
26
|
+
resolvedValue;
|
|
27
|
+
innerSimpleObservableProp.setValue(resolvedValue);
|
|
28
|
+
resolve(resolvedValue);
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
reject(error);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
/** Set the promise so consumers know it's loading. */
|
|
35
|
+
innerSimpleObservableProp.setValue(wrappedPromise);
|
|
36
|
+
return wrappedPromise;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
innerSimpleObservableProp.setValue(newValue);
|
|
40
|
+
observableWithUpdater.latestResolvedValue = newValue;
|
|
41
|
+
return newValue;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const observableWithUpdater = Object.assign(innerSimpleObservableProp, {
|
|
45
|
+
triggerUpdate: updateValue,
|
|
46
|
+
latestResolvedValue: undefined,
|
|
47
|
+
updateCount: internalUpdateCount,
|
|
48
|
+
});
|
|
49
|
+
Object.defineProperty(observableWithUpdater, 'updateCount', {
|
|
50
|
+
get() {
|
|
51
|
+
return internalUpdateCount;
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
try {
|
|
55
|
+
updateValue(setup.initInput);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
console.error(error);
|
|
59
|
+
}
|
|
60
|
+
return observableWithUpdater;
|
|
61
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -23,8 +23,10 @@ export * from './declarative-element/properties/element-events';
|
|
|
23
23
|
export * from './declarative-element/properties/element-properties';
|
|
24
24
|
export * from './declarative-element/properties/element-vir-state-setup';
|
|
25
25
|
export * from './declarative-element/properties/host-classes';
|
|
26
|
-
export * from './declarative-element/properties/observable-
|
|
27
|
-
export * from './declarative-element/properties/observable-
|
|
26
|
+
export * from './declarative-element/properties/observable-prop/interval-observable-prop';
|
|
27
|
+
export * from './declarative-element/properties/observable-prop/observable-prop';
|
|
28
|
+
export * from './declarative-element/properties/observable-prop/setter-observable-prop';
|
|
29
|
+
export * from './declarative-element/properties/observable-prop/updatable-observable-prop';
|
|
28
30
|
export * from './declarative-element/properties/per-instance';
|
|
29
31
|
export * from './declarative-element/properties/styles';
|
|
30
32
|
export * from './declarative-element/properties/tag-name';
|
package/dist/index.js
CHANGED
|
@@ -22,8 +22,10 @@ export * from './declarative-element/properties/element-events';
|
|
|
22
22
|
export * from './declarative-element/properties/element-properties';
|
|
23
23
|
export * from './declarative-element/properties/element-vir-state-setup';
|
|
24
24
|
export * from './declarative-element/properties/host-classes';
|
|
25
|
-
export * from './declarative-element/properties/observable-
|
|
26
|
-
export * from './declarative-element/properties/observable-
|
|
25
|
+
export * from './declarative-element/properties/observable-prop/interval-observable-prop';
|
|
26
|
+
export * from './declarative-element/properties/observable-prop/observable-prop';
|
|
27
|
+
export * from './declarative-element/properties/observable-prop/setter-observable-prop';
|
|
28
|
+
export * from './declarative-element/properties/observable-prop/updatable-observable-prop';
|
|
27
29
|
export * from './declarative-element/properties/per-instance';
|
|
28
30
|
export * from './declarative-element/properties/styles';
|
|
29
31
|
export * from './declarative-element/properties/tag-name';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "element-vir",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "18.0.0",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"custom",
|
|
6
6
|
"web",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"docs": "virmator docs",
|
|
30
30
|
"format": "virmator format",
|
|
31
31
|
"publish": "virmator publish \"npm run compile && npm run test:all\"",
|
|
32
|
-
"start": "npm install && virmator frontend",
|
|
32
|
+
"start": "npm run compile && npm install && virmator frontend",
|
|
33
33
|
"test": "virmator test-web",
|
|
34
34
|
"test:all": "concurrently -c auto --kill-others-on-fail --colors --names types,tests,spelling,format,docs \"npm run test:types\" \"npm run test:coverage\" \"npm run test:spelling\" \"npm run test:format\" \"npm run test:docs\"",
|
|
35
35
|
"test:coverage": "virmator test-web coverage",
|
|
@@ -40,19 +40,21 @@
|
|
|
40
40
|
"test:types": "tsc --noEmit"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@augment-vir/common": "^22.
|
|
44
|
-
"
|
|
45
|
-
"lit
|
|
43
|
+
"@augment-vir/common": "^22.1.0",
|
|
44
|
+
"date-vir": "^5.0.0",
|
|
45
|
+
"lit": "^3.1.0",
|
|
46
|
+
"lit-css-vars": "^3.0.7",
|
|
47
|
+
"lit-html": "^3.1.0",
|
|
46
48
|
"object-shape-tester": "^1.0.2",
|
|
47
49
|
"run-time-assertions": "^0.2.1"
|
|
48
50
|
},
|
|
49
51
|
"devDependencies": {
|
|
50
|
-
"@augment-vir/browser-testing": "^22.
|
|
51
|
-
"@augment-vir/node-js": "^22.
|
|
52
|
+
"@augment-vir/browser-testing": "^22.1.0",
|
|
53
|
+
"@augment-vir/node-js": "^22.1.0",
|
|
52
54
|
"@istanbuljs/nyc-config-typescript": "^1.0.2",
|
|
53
55
|
"@open-wc/testing": "^4.0.0",
|
|
54
|
-
"@types/chai": "^4.3.
|
|
55
|
-
"@types/mocha": "^10.0.
|
|
56
|
+
"@types/chai": "^4.3.11",
|
|
57
|
+
"@types/mocha": "^10.0.6",
|
|
56
58
|
"@web/dev-server-esbuild": "^1.0.1",
|
|
57
59
|
"@web/test-runner": "^0.18.0",
|
|
58
60
|
"@web/test-runner-commands": "^0.9.0",
|
|
@@ -60,34 +62,35 @@
|
|
|
60
62
|
"@web/test-runner-visual-regression": "^0.9.0",
|
|
61
63
|
"ansi-colors": "^4.1.3",
|
|
62
64
|
"concurrently": "^8.2.2",
|
|
63
|
-
"cspell": "^8.
|
|
64
|
-
"dependency-cruiser": "^15.
|
|
65
|
-
"element-book": "^10.1.
|
|
66
|
-
"
|
|
65
|
+
"cspell": "^8.1.3",
|
|
66
|
+
"dependency-cruiser": "^15.5.0",
|
|
67
|
+
"element-book": "^10.1.9",
|
|
68
|
+
"element-vir": "file:./",
|
|
69
|
+
"esbuild": "^0.19.9",
|
|
67
70
|
"istanbul-smart-text-reporter": "^1.1.3",
|
|
68
71
|
"markdown-code-example-inserter": "^0.3.3",
|
|
69
72
|
"mocha-spec-reporter-with-file-names": "^0.0.3",
|
|
70
73
|
"npm-check-updates": "~16.12.3",
|
|
71
74
|
"nyc": "^15.1.0",
|
|
72
|
-
"prettier": "^3.1.
|
|
75
|
+
"prettier": "^3.1.1",
|
|
73
76
|
"prettier-plugin-interpolated-html-tags": "^1.0.3",
|
|
74
77
|
"prettier-plugin-jsdoc": "^1.1.1",
|
|
75
78
|
"prettier-plugin-multiline-arrays": "^3.0.1",
|
|
76
79
|
"prettier-plugin-organize-imports": "^3.2.4",
|
|
77
|
-
"prettier-plugin-packagejson": "^2.4.
|
|
80
|
+
"prettier-plugin-packagejson": "^2.4.7",
|
|
78
81
|
"prettier-plugin-sort-json": "^3.1.0",
|
|
79
|
-
"prettier-plugin-toml": "^
|
|
80
|
-
"ts-node": "^10.9.
|
|
81
|
-
"type-fest": "^4.8.
|
|
82
|
-
"typedoc": "^0.25.
|
|
82
|
+
"prettier-plugin-toml": "^2.0.1",
|
|
83
|
+
"ts-node": "^10.9.2",
|
|
84
|
+
"type-fest": "^4.8.3",
|
|
85
|
+
"typedoc": "^0.25.4",
|
|
83
86
|
"typescript": "~5.2.2",
|
|
84
|
-
"
|
|
87
|
+
"vira": "^2.5.4",
|
|
88
|
+
"virmator": "^11.1.4",
|
|
85
89
|
"vite": "^4.5.0",
|
|
86
|
-
"vite-tsconfig-paths": "^4.2.
|
|
90
|
+
"vite-tsconfig-paths": "^4.2.2"
|
|
87
91
|
},
|
|
88
92
|
"overrides": {
|
|
89
|
-
"lit": "^
|
|
90
|
-
"
|
|
91
|
-
"@open-wc/testing-helpers": "2.3.0"
|
|
93
|
+
"lit": "^3.1.0",
|
|
94
|
+
"element-vir": "*"
|
|
92
95
|
}
|
|
93
96
|
}
|
package/dist/declarative-element/properties/observable-property/create-observable-property.d.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { referenceEqualityCheck } from '../../../util/equality';
|
|
2
|
-
import { ObservableProperty } from './observable-property';
|
|
3
|
-
export type ObservablePropertyWithSetter<ValueType> = ObservableProperty<ValueType> & {
|
|
4
|
-
setValue(newValue: ValueType): void;
|
|
5
|
-
};
|
|
6
|
-
/**
|
|
7
|
-
* Easy and quick way to create an ObservableProperty. Includes a setValue method with equality
|
|
8
|
-
* checking for easily emitting changes.
|
|
9
|
-
*/
|
|
10
|
-
export declare function createObservablePropertyWithSetter<ValueType>(initValue: ValueType, equalityCallback?: typeof referenceEqualityCheck): ObservablePropertyWithSetter<ValueType>;
|
|
11
|
-
export type UpdaterCallback<ValueType, UpdateInputType> = Exclude<UpdateInputType, undefined> extends never ? () => ValueType : (inputs: UpdateInputType) => ValueType;
|
|
12
|
-
export type ObservablePropertyWithUpdaterCallback<ValueType, UpdateInputType> = ObservableProperty<ValueType | Awaited<ValueType>> & {
|
|
13
|
-
triggerUpdate: UpdaterCallback<ValueType, UpdateInputType>;
|
|
14
|
-
/**
|
|
15
|
-
* The last value that was resolved. This will be undefined if there has never, so far, been a
|
|
16
|
-
* resolved value.
|
|
17
|
-
*/
|
|
18
|
-
latestResolvedValue: ValueType extends Promise<any> ? Awaited<ValueType> | undefined : ValueType;
|
|
19
|
-
};
|
|
20
|
-
export type ObservablePropertyWithUpdaterSetup<ValueType, UpdateInputType> = {
|
|
21
|
-
initInput: UpdateInputType;
|
|
22
|
-
updateCallback: UpdaterCallback<ValueType, UpdateInputType>;
|
|
23
|
-
equalityCallback?: typeof referenceEqualityCheck | undefined;
|
|
24
|
-
};
|
|
25
|
-
export declare function createObservablePropertyWithUpdater<ValueType, UpdateInputType = undefined>(setup: ObservablePropertyWithUpdaterSetup<ValueType, UpdateInputType>): ObservablePropertyWithUpdaterCallback<ValueType, UpdateInputType>;
|
|
26
|
-
export type ObservablePropertyWithIntervalSetup<ValueType, UpdateInputType> = ObservablePropertyWithUpdaterSetup<ValueType, UpdateInputType> & {
|
|
27
|
-
/** Interval duration in Milliseconds. */
|
|
28
|
-
intervalMs: number;
|
|
29
|
-
};
|
|
30
|
-
export type ObservablePropertyWithInterval<ValueType, UpdateInputType> = Omit<ObservablePropertyWithUpdaterCallback<ValueType, UpdateInputType>, 'triggerUpdate'> & {
|
|
31
|
-
forceUpdate: UpdaterCallback<ValueType, UpdateInputType>;
|
|
32
|
-
/**
|
|
33
|
-
* Pauses the update interval, if it isn't already paused. Use .resumeInterval() to start the
|
|
34
|
-
* interval again. Under the hood, this actually clears the interval entirely.
|
|
35
|
-
*/
|
|
36
|
-
pauseInterval(): void;
|
|
37
|
-
/**
|
|
38
|
-
* Resumes the update interval if it was paused. Under the hood, this creates a new interval
|
|
39
|
-
* entirely, as .pauseInterval() actually clears it.
|
|
40
|
-
*/
|
|
41
|
-
resumeInterval(): void;
|
|
42
|
-
};
|
|
43
|
-
export declare function createObservablePropertyWithIntervalUpdate<ValueType, UpdateInputType = undefined>(setup: ObservablePropertyWithIntervalSetup<ValueType, UpdateInputType>): ObservablePropertyWithInterval<ValueType, UpdateInputType>;
|
package/dist/declarative-element/properties/observable-property/create-observable-property.js
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { referenceEqualityCheck } from '../../../util/equality';
|
|
2
|
-
/**
|
|
3
|
-
* Easy and quick way to create an ObservableProperty. Includes a setValue method with equality
|
|
4
|
-
* checking for easily emitting changes.
|
|
5
|
-
*/
|
|
6
|
-
export function createObservablePropertyWithSetter(initValue, equalityCallback = referenceEqualityCheck) {
|
|
7
|
-
const listeners = new Set();
|
|
8
|
-
function fireListeners() {
|
|
9
|
-
listeners.forEach((listener) => listener(observableProperty.value));
|
|
10
|
-
}
|
|
11
|
-
const observableProperty = {
|
|
12
|
-
value: initValue,
|
|
13
|
-
setValue(newValue) {
|
|
14
|
-
if (!equalityCallback(observableProperty.value, newValue)) {
|
|
15
|
-
observableProperty.value = newValue;
|
|
16
|
-
fireListeners();
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
addListener(listener) {
|
|
20
|
-
const shouldAddListener = !listeners.has(listener);
|
|
21
|
-
if (shouldAddListener) {
|
|
22
|
-
listeners.add(listener);
|
|
23
|
-
}
|
|
24
|
-
return shouldAddListener;
|
|
25
|
-
},
|
|
26
|
-
removeListener(listener) {
|
|
27
|
-
return listeners.delete(listener);
|
|
28
|
-
},
|
|
29
|
-
};
|
|
30
|
-
return observableProperty;
|
|
31
|
-
}
|
|
32
|
-
export function createObservablePropertyWithUpdater(setup) {
|
|
33
|
-
const areEqual = setup.equalityCallback ?? referenceEqualityCheck;
|
|
34
|
-
const innerSimpleObservableProperty = createObservablePropertyWithSetter(undefined, areEqual);
|
|
35
|
-
function updateValue(inputs) {
|
|
36
|
-
const newValue = setup.updateCallback(inputs);
|
|
37
|
-
if (newValue instanceof Promise) {
|
|
38
|
-
const wrappedPromise = new Promise(async (resolve, reject) => {
|
|
39
|
-
try {
|
|
40
|
-
const resolvedValue = await newValue;
|
|
41
|
-
observableWithUpdater.latestResolvedValue =
|
|
42
|
-
resolvedValue;
|
|
43
|
-
innerSimpleObservableProperty.setValue(resolvedValue);
|
|
44
|
-
resolve(resolvedValue);
|
|
45
|
-
}
|
|
46
|
-
catch (error) {
|
|
47
|
-
reject(error);
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
/** Set the promise so consumers know it's loading. */
|
|
51
|
-
innerSimpleObservableProperty.setValue(wrappedPromise);
|
|
52
|
-
return wrappedPromise;
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
innerSimpleObservableProperty.setValue(newValue);
|
|
56
|
-
observableWithUpdater.latestResolvedValue =
|
|
57
|
-
newValue;
|
|
58
|
-
return newValue;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
const observableWithUpdater = Object.assign(innerSimpleObservableProperty, {
|
|
62
|
-
triggerUpdate: updateValue,
|
|
63
|
-
latestResolvedValue: undefined,
|
|
64
|
-
});
|
|
65
|
-
updateValue(setup.initInput);
|
|
66
|
-
return observableWithUpdater;
|
|
67
|
-
}
|
|
68
|
-
export function createObservablePropertyWithIntervalUpdate(setup) {
|
|
69
|
-
let latestInputs = setup.initInput;
|
|
70
|
-
const baseObservableProperty = createObservablePropertyWithUpdater(setup);
|
|
71
|
-
let latestIntervalId = undefined;
|
|
72
|
-
function updateValue(inputs) {
|
|
73
|
-
if (inputs) {
|
|
74
|
-
latestInputs = inputs;
|
|
75
|
-
}
|
|
76
|
-
return baseObservableProperty.triggerUpdate(latestInputs);
|
|
77
|
-
}
|
|
78
|
-
const shouldRunInterval = !!setup.intervalMs && setup.intervalMs !== Infinity;
|
|
79
|
-
function resumeInterval() {
|
|
80
|
-
if (shouldRunInterval && latestIntervalId == undefined) {
|
|
81
|
-
latestIntervalId = window.setInterval(() => {
|
|
82
|
-
updateValue();
|
|
83
|
-
}, setup.intervalMs);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
resumeInterval();
|
|
87
|
-
const observablePropertyWithInterval = Object.assign(baseObservableProperty, {
|
|
88
|
-
forceUpdate: updateValue,
|
|
89
|
-
pauseInterval() {
|
|
90
|
-
if (latestIntervalId != undefined) {
|
|
91
|
-
window.clearInterval(latestIntervalId);
|
|
92
|
-
latestIntervalId = undefined;
|
|
93
|
-
}
|
|
94
|
-
},
|
|
95
|
-
resumeInterval,
|
|
96
|
-
});
|
|
97
|
-
return observablePropertyWithInterval;
|
|
98
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { PropertyInitMapBase } from '../element-properties';
|
|
2
|
-
export type ObservablePropertyListener<T> = (value: T) => void;
|
|
3
|
-
export type ObservablePropertyListenerMap<OriginalPropertyMap extends PropertyInitMapBase> = Partial<Record<keyof OriginalPropertyMap, ObservablePropertyListener<any> | undefined>>;
|
|
4
|
-
export type ObservableProperty<ValueType> = {
|
|
5
|
-
/** Add the given listener. */
|
|
6
|
-
addListener(listener: ObservablePropertyListener<ValueType>): boolean;
|
|
7
|
-
/** Remove the given listener by reference. */
|
|
8
|
-
removeListener(listener: ObservablePropertyListener<ValueType>): boolean;
|
|
9
|
-
value: ValueType;
|
|
10
|
-
};
|
|
11
|
-
export declare const basicObservablePropertyShape: import("object-shape-tester").ShapeDefinition<ObservableProperty<any>, false>;
|
|
12
|
-
export declare function isObservableProperty<ValueType = unknown>(input: unknown): input is ObservableProperty<ValueType>;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { defineShape, isValidShape, unknownShape } from 'object-shape-tester';
|
|
2
|
-
export const basicObservablePropertyShape = defineShape({
|
|
3
|
-
addListener() {
|
|
4
|
-
return false;
|
|
5
|
-
},
|
|
6
|
-
removeListener() {
|
|
7
|
-
return false;
|
|
8
|
-
},
|
|
9
|
-
value: unknownShape(),
|
|
10
|
-
});
|
|
11
|
-
export function isObservableProperty(input) {
|
|
12
|
-
return isValidShape(input, basicObservablePropertyShape, { allowExtraKeys: true });
|
|
13
|
-
}
|