@runopencode/rx-stencil 0.4.4 → 0.5.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/cjs/{index-CbERigo8.js → index-DWhjpI-K.js} +396 -41
- package/dist/{esm/set-property-CpZKE-Xu.js → cjs/index-Dssn3hdS.js} +2 -61
- package/dist/cjs/index.cjs.js +280 -244
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/mutation-observable-qY7nC854.js +152 -0
- package/dist/cjs/properties-observable-DXbVBslA.js +23 -0
- package/dist/cjs/property-observable-CPp5WEjC.js +86 -0
- package/dist/cjs/rx-async.cjs.entry.js +21 -14
- package/dist/cjs/rx-stencil.cjs.js +3 -3
- package/dist/cjs/schedule-render-DG4hFv5E.js +53 -0
- package/dist/cjs/set-property-C3KARzdl.js +33 -0
- package/dist/cjs/stencil-uD4ZIy1h.js +75 -0
- package/dist/cjs/test-properties-observable.cjs.entry.js +27 -0
- package/dist/cjs/test-property-observable.cjs.entry.js +31 -0
- package/dist/cjs/test-schedule-render.cjs.entry.js +28 -0
- package/dist/cjs/test-view-child-observable-shadow-dom.cjs.entry.js +40 -0
- package/dist/cjs/until-disconnected-BTCr-3q2.js +27 -0
- package/dist/collection/collection-manifest.json +9 -2
- package/dist/collection/components/async/async.js +42 -10
- package/dist/collection/components/index.js +1 -1
- package/dist/collection/rx/decorator/content-child.js +34 -0
- package/dist/collection/rx/decorator/content-children.js +34 -0
- package/dist/collection/rx/decorator/index.js +6 -2
- package/dist/collection/rx/decorator/query-selector-all.js +6 -38
- package/dist/collection/rx/decorator/query-selector.js +6 -51
- package/dist/collection/rx/decorator/view-child.js +34 -0
- package/dist/collection/rx/decorator/view-children.js +34 -0
- package/dist/collection/rx/index.js +1 -0
- package/dist/collection/rx/observable/connected-observable.js +27 -0
- package/dist/collection/rx/observable/content-child-observable.js +24 -0
- package/dist/collection/rx/observable/content-children-observable.js +15 -0
- package/dist/collection/rx/observable/from-event.js +26 -0
- package/dist/collection/rx/observable/index.js +9 -4
- package/dist/collection/rx/observable/mutation-observable.js +6 -0
- package/dist/collection/rx/observable/properties-observable.js +5 -0
- package/dist/collection/rx/observable/property-observable.js +72 -17
- package/dist/collection/rx/observable/render-observable.js +18 -9
- package/dist/collection/rx/observable/view-child-observable.js +30 -0
- package/dist/collection/rx/observable/view-children-observable.js +21 -0
- package/dist/collection/rx/operator/index.js +4 -3
- package/dist/collection/rx/operator/to-property.js +7 -7
- package/dist/collection/rx/operator/until-disconnected.js +12 -94
- package/dist/collection/rx/operator/while-connected.js +39 -0
- package/dist/collection/rx/subscriber/index.js +1 -1
- package/dist/collection/rx/subscriber/set-property.js +13 -0
- package/dist/collection/rx/types.js +1 -0
- package/dist/collection/tests/rx/observable/from-event/test-from-event.component.js +30 -0
- package/dist/collection/tests/rx/observable/properties-observable/test-properties-observable.component.js +85 -0
- package/dist/collection/tests/rx/observable/property-observable/test-property-observable.component.js +47 -0
- package/dist/collection/tests/rx/observable/render-observable.unit.js +38 -0
- package/dist/collection/tests/rx/observable/view-child-observable/test-view-child-observable-shadow-dom.component.js +96 -0
- package/dist/collection/tests/rx/operator/schedule-render/test-schedule-render.component.js +42 -0
- package/dist/collection/tests/rx/operator/to-property.unit.js +28 -0
- package/dist/collection/tests/rx/operator/until-disconnected.unit.js +25 -0
- package/dist/collection/tests/rx/operator/while-connected/test-while-connected.component.js +32 -0
- package/dist/collection/tests/rx/subscriber/set-property.unit.js +53 -0
- package/dist/collection/utils/decorator.js +33 -0
- package/dist/collection/utils/index.js +1 -1
- package/dist/collection/utils/rxjs.js +67 -0
- package/dist/collection/utils/stencil.js +66 -0
- package/dist/collection/utils/values-registry.js +40 -0
- package/dist/components/index.js +1 -1
- package/dist/components/index2.js +1 -0
- package/dist/components/mutation-observable.js +1 -0
- package/dist/components/properties-observable.js +1 -0
- package/dist/components/property-observable.js +1 -0
- package/dist/components/rx-async.js +1 -1
- package/dist/components/schedule-render.js +1 -0
- package/dist/components/set-property.js +1 -1
- package/dist/components/stencil.js +1 -0
- package/dist/components/test-properties-observable.d.ts +11 -0
- package/dist/components/test-properties-observable.js +1 -0
- package/dist/components/test-property-observable.d.ts +11 -0
- package/dist/components/test-property-observable.js +1 -0
- package/dist/components/test-schedule-render.d.ts +11 -0
- package/dist/components/test-schedule-render.js +1 -0
- package/dist/components/test-view-child-observable-shadow-dom.d.ts +11 -0
- package/dist/components/test-view-child-observable-shadow-dom.js +1 -0
- package/dist/components/until-disconnected.js +1 -0
- package/dist/esm/{index-BIBww8qU.js → index-BCGlW-2C.js} +396 -42
- package/dist/{cjs/set-property-BZHuI0P5.js → esm/index-Bn8mRT4P.js} +1 -67
- package/dist/esm/index.js +266 -240
- package/dist/esm/loader.js +3 -3
- package/dist/esm/mutation-observable-xA7xgk29.js +145 -0
- package/dist/esm/properties-observable-Bzq-rZ4c.js +21 -0
- package/dist/esm/property-observable-BKyQe0OR.js +84 -0
- package/dist/esm/rx-async.entry.js +18 -11
- package/dist/esm/rx-stencil.js +4 -4
- package/dist/esm/schedule-render-BGCI5FMG.js +50 -0
- package/dist/esm/set-property-CgrvJ28c.js +31 -0
- package/dist/esm/stencil-BQCAKjCT.js +68 -0
- package/dist/esm/test-properties-observable.entry.js +25 -0
- package/dist/esm/test-property-observable.entry.js +29 -0
- package/dist/esm/test-schedule-render.entry.js +26 -0
- package/dist/esm/test-view-child-observable-shadow-dom.entry.js +38 -0
- package/dist/esm/until-disconnected-D2pF81SM.js +25 -0
- package/dist/rx-stencil/index.esm.js +1 -1
- package/dist/rx-stencil/p-7c570c65.entry.js +1 -0
- package/dist/rx-stencil/p-BCGlW-2C.js +3 -0
- package/dist/rx-stencil/p-BLLg2g3n.js +1 -0
- package/dist/rx-stencil/p-BQCAKjCT.js +1 -0
- package/dist/rx-stencil/p-Bn8mRT4P.js +1 -0
- package/dist/rx-stencil/p-D1zETqVV.js +1 -0
- package/dist/rx-stencil/p-DHIVm3-O.js +1 -0
- package/dist/rx-stencil/p-J0xLdrjW.js +1 -0
- package/dist/rx-stencil/p-Sf5sf4Pq.js +1 -0
- package/dist/rx-stencil/p-a4c71f45.entry.js +1 -0
- package/dist/rx-stencil/p-b2c6ba01.entry.js +1 -0
- package/dist/rx-stencil/p-dc654207.entry.js +1 -0
- package/dist/rx-stencil/p-e661490a.entry.js +1 -0
- package/dist/rx-stencil/p-wVeMJABH.js +1 -0
- package/dist/rx-stencil/rx-stencil.esm.js +1 -1
- package/dist/types/components/async/async.d.ts +9 -2
- package/dist/types/components/index.d.ts +1 -1
- package/dist/types/components.d.ts +92 -2
- package/dist/types/rx/decorator/content-child.d.ts +3 -0
- package/dist/types/rx/decorator/content-children.d.ts +3 -0
- package/dist/types/rx/decorator/index.d.ts +6 -2
- package/dist/types/rx/decorator/query-selector-all.d.ts +7 -21
- package/dist/types/rx/decorator/query-selector.d.ts +7 -29
- package/dist/types/rx/decorator/view-child.d.ts +27 -0
- package/dist/types/rx/decorator/view-children.d.ts +11 -0
- package/dist/types/rx/index.d.ts +1 -0
- package/dist/types/rx/observable/connected-observable.d.ts +9 -0
- package/dist/types/rx/observable/content-child-observable.d.ts +5 -0
- package/dist/types/rx/observable/content-children-observable.d.ts +5 -0
- package/dist/types/rx/observable/from-event.d.ts +26 -0
- package/dist/types/rx/observable/index.d.ts +9 -4
- package/dist/types/rx/observable/mutation-observable.d.ts +6 -0
- package/dist/types/rx/observable/properties-observable.d.ts +5 -0
- package/dist/types/rx/observable/property-observable.d.ts +1 -1
- package/dist/types/rx/observable/render-observable.d.ts +6 -1
- package/dist/types/rx/observable/view-child-observable.d.ts +17 -0
- package/dist/types/rx/observable/view-children-observable.d.ts +5 -0
- package/dist/types/rx/operator/index.d.ts +4 -3
- package/dist/types/rx/operator/to-property.d.ts +1 -3
- package/dist/types/rx/operator/while-connected.d.ts +22 -0
- package/dist/types/rx/subscriber/index.d.ts +1 -1
- package/dist/types/rx/subscriber/set-property.d.ts +13 -0
- package/dist/types/rx/types.d.ts +12 -0
- package/dist/types/stencil-public-runtime.d.ts +74 -55
- package/dist/types/tests/rx/observable/properties-observable/test-properties-observable.component.d.ts +9 -0
- package/dist/types/tests/rx/observable/property-observable/test-property-observable.component.d.ts +8 -0
- package/dist/types/tests/rx/observable/render-observable.unit.d.ts +1 -0
- package/dist/types/tests/rx/observable/view-child-observable/test-view-child-observable-shadow-dom.component.d.ts +12 -0
- package/dist/types/tests/rx/operator/schedule-render/test-schedule-render.component.d.ts +7 -0
- package/dist/types/tests/rx/operator/to-property.unit.d.ts +1 -0
- package/dist/types/tests/rx/operator/until-disconnected.unit.d.ts +1 -0
- package/dist/types/tests/rx/subscriber/set-property.unit.d.ts +1 -0
- package/dist/types/utils/decorator.d.ts +11 -0
- package/dist/types/utils/index.d.ts +1 -1
- package/dist/types/utils/rxjs.d.ts +31 -0
- package/dist/types/utils/stencil.d.ts +54 -0
- package/dist/types/utils/values-registry.d.ts +10 -0
- package/loader/index.d.ts +1 -1
- package/package.json +19 -10
- package/dist/collection/utils/get-property-descriptor.js +0 -17
- package/dist/rx-stencil/p-77100dee.entry.js +0 -1
- package/dist/rx-stencil/p-BIBww8qU.js +0 -2
- package/dist/rx-stencil/p-IbpJ_cRo.js +0 -1
- package/dist/types/utils/get-property-descriptor.d.ts +0 -7
|
@@ -1,23 +1,32 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getElement, } from "@stencil/core";
|
|
2
|
+
import { identity, startWith, Subject, } from "rxjs";
|
|
3
|
+
import { getComponentTagName, isRendered, } from "../../utils/stencil";
|
|
4
|
+
let observables = new WeakMap();
|
|
2
5
|
/**
|
|
3
|
-
* Returns an observable that emits when the component render()
|
|
6
|
+
* Returns an observable that emits when the component `render()`
|
|
4
7
|
* function is called. Value will be emitted after the next
|
|
5
8
|
* microtask (next tick).
|
|
9
|
+
*
|
|
10
|
+
* If component is already rendered, the observable will emit
|
|
11
|
+
* immediately.
|
|
12
|
+
*
|
|
13
|
+
* Uses hot observable pattern.
|
|
6
14
|
*/
|
|
7
15
|
export function renderObservable(cmp) {
|
|
8
16
|
if ('function' !== typeof cmp.render) {
|
|
9
|
-
throw new Error(
|
|
17
|
+
throw new Error(`Component "${getComponentTagName(cmp)}" does not have a render function.`);
|
|
10
18
|
}
|
|
11
|
-
|
|
19
|
+
let element = getElement(cmp);
|
|
20
|
+
if (!observables.has(element)) {
|
|
12
21
|
let previousRender = cmp.render;
|
|
22
|
+
let subject = new Subject();
|
|
13
23
|
cmp.render = function () {
|
|
14
24
|
Promise.resolve().then(() => {
|
|
15
|
-
|
|
25
|
+
subject.next();
|
|
16
26
|
});
|
|
17
27
|
return previousRender.call(this);
|
|
18
28
|
};
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
});
|
|
29
|
+
observables.set(element, subject.asObservable());
|
|
30
|
+
}
|
|
31
|
+
return observables.get(element).pipe(isRendered(cmp) ? startWith(() => void 0) : identity);
|
|
23
32
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { getElement, } from "@stencil/core";
|
|
2
|
+
import { map, startWith, } from "rxjs";
|
|
3
|
+
import { getHostRef, isEmulatedViewChild, usesShadowDom, } from "../../utils/stencil";
|
|
4
|
+
import { distinctUntilElementChanged } from "../../utils/rxjs";
|
|
5
|
+
import { renderObservable } from "./render-observable";
|
|
6
|
+
export function viewChildObservable(cmp, selector, options) {
|
|
7
|
+
let element = getElement(cmp);
|
|
8
|
+
let hostRef = getHostRef(cmp);
|
|
9
|
+
let rendered = renderObservable(cmp);
|
|
10
|
+
options = Object.assign({ distinct: true }, options);
|
|
11
|
+
if ((hostRef.$renderCount$ || 0) > 0) {
|
|
12
|
+
rendered = rendered.pipe(startWith(void 0));
|
|
13
|
+
}
|
|
14
|
+
// In shadow DOM, this is quite cheap, we can query only shadow DOM and skip the light DOM.
|
|
15
|
+
if (usesShadowDom(cmp)) {
|
|
16
|
+
return rendered.pipe(map(() => element.shadowRoot.querySelector(selector)), distinctUntilElementChanged(options.distinct));
|
|
17
|
+
}
|
|
18
|
+
// When shadow DOM is emulated, this is more expensive, we need to query light DOM and use first element
|
|
19
|
+
// which matches the selector, and it is not a child of any emulated slot node.
|
|
20
|
+
return rendered.pipe(map(() => {
|
|
21
|
+
let candidates = element.querySelectorAll(selector);
|
|
22
|
+
for (let i = 0; i < candidates.length; i++) {
|
|
23
|
+
let candidate = candidates[i];
|
|
24
|
+
if (isEmulatedViewChild(candidate, element)) {
|
|
25
|
+
return candidate;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}), distinctUntilElementChanged(options.distinct));
|
|
30
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { getElement, } from "@stencil/core";
|
|
2
|
+
import { map, startWith, } from "rxjs";
|
|
3
|
+
import { getHostRef, isEmulatedViewChild, usesShadowDom, } from "../../utils/stencil";
|
|
4
|
+
import { distinctUntilElementsChanged } from "../../utils/rxjs";
|
|
5
|
+
import { renderObservable } from "./render-observable";
|
|
6
|
+
export function viewChildrenObservable(cmp, selector, options) {
|
|
7
|
+
let element = getElement(cmp);
|
|
8
|
+
let hostRef = getHostRef(cmp);
|
|
9
|
+
let rendered = renderObservable(cmp);
|
|
10
|
+
options = Object.assign({ distinct: true }, options);
|
|
11
|
+
if ((hostRef.$renderCount$ || 0) > 0) {
|
|
12
|
+
rendered = rendered.pipe(startWith(void 0));
|
|
13
|
+
}
|
|
14
|
+
// In shadow DOM, this is quite cheap, we can query only shadow DOM and skip the light DOM.
|
|
15
|
+
if (usesShadowDom(cmp)) {
|
|
16
|
+
return rendered.pipe(map(() => Array.from(element.shadowRoot.querySelectorAll(selector))), distinctUntilElementsChanged(options.distinct));
|
|
17
|
+
}
|
|
18
|
+
// When shadow DOM is emulated, this is more expensive, we need to query light DOM and use elements
|
|
19
|
+
// which matches the selector, and it is not a child of any emulated slot node.
|
|
20
|
+
return rendered.pipe(map(() => Array.from(element.querySelectorAll(selector))), map((candidates) => candidates.filter((candidate) => isEmulatedViewChild(candidate, element))), distinctUntilElementsChanged(options.distinct));
|
|
21
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
1
|
+
export * from './schedule-render';
|
|
2
|
+
export * from './to-property';
|
|
3
|
+
export * from './until-disconnected';
|
|
4
|
+
export * from './while-connected';
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
+
import { Build, } from "@stencil/core";
|
|
1
2
|
import { tap, } from "rxjs";
|
|
2
|
-
import {
|
|
3
|
+
import { getHostRef } from "../../utils";
|
|
3
4
|
/**
|
|
4
5
|
* Use this function to tap into a value stream and flush value to
|
|
5
|
-
* component property.
|
|
6
|
-
* function (function will detect that value is passed instead of
|
|
7
|
-
* observable).
|
|
6
|
+
* component property.
|
|
8
7
|
*/
|
|
9
8
|
export function toProperty(cmp, property) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
if (Build.isDev && !cmp.hasOwnProperty(property)) {
|
|
10
|
+
let ref = getHostRef(cmp);
|
|
11
|
+
console.warn(`It seams that ${property} does not exist on component ${ref.$cmpMeta$.$tagName$}. This warning will not be displayed in production environment.`);
|
|
12
|
+
}
|
|
13
13
|
return (source) => {
|
|
14
14
|
return source.pipe(tap((value) => {
|
|
15
15
|
cmp[property] = value;
|
|
@@ -1,104 +1,22 @@
|
|
|
1
1
|
import { getElement, } from "@stencil/core";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
* A map of component observables that are being watched for
|
|
5
|
-
* disconnect callback invocation. A weak map is being used
|
|
6
|
-
* so that the component instance can be garbage collected.
|
|
7
|
-
*
|
|
8
|
-
* {@internal}
|
|
9
|
-
*/
|
|
10
|
-
let disconnectObservables = new WeakMap();
|
|
11
|
-
/**
|
|
12
|
-
* Creates an observable that emits a value when the component
|
|
13
|
-
* is disconnected from DOM and method `disconnectedCallback()`
|
|
14
|
-
* is invoked. StencilJS will supress the invocation of this
|
|
15
|
-
* method if it is not defined on the component.
|
|
16
|
-
*
|
|
17
|
-
* {@internal}
|
|
18
|
-
*/
|
|
19
|
-
let createUsingDisconnectedCallback = function (cmp) {
|
|
20
|
-
let previousDisconnected = cmp.disconnectedCallback;
|
|
21
|
-
if (!previousDisconnected) {
|
|
22
|
-
throw new Error(`Component "${cmp.constructor.name}" does not have a "disconnectedCallback()" method defined.`);
|
|
23
|
-
}
|
|
24
|
-
let disconnectedSubject$ = new Subject();
|
|
25
|
-
cmp.disconnectedCallback = function () {
|
|
26
|
-
if (previousDisconnected) {
|
|
27
|
-
previousDisconnected.call(cmp);
|
|
28
|
-
}
|
|
29
|
-
disconnectedSubject$.next();
|
|
30
|
-
};
|
|
31
|
-
return disconnectedSubject$.asObservable();
|
|
32
|
-
};
|
|
33
|
-
/**
|
|
34
|
-
* Mutation observer is our next heuristic. We will monitor parent
|
|
35
|
-
* node of the component and emit a value when the component is
|
|
36
|
-
* disconnected from DOM. This will only work, of course, if the
|
|
37
|
-
* component is not the root node of the application and component
|
|
38
|
-
* is already within DOM.
|
|
39
|
-
*
|
|
40
|
-
* {@internal}
|
|
41
|
-
*/
|
|
42
|
-
let createUsingMutationObserver = function (cmp) {
|
|
43
|
-
let element = getElement(cmp);
|
|
44
|
-
if (null === element.parentNode) {
|
|
45
|
-
throw new Error(`Component "${cmp.constructor.name}" is not within DOM.`);
|
|
46
|
-
}
|
|
47
|
-
return new Observable((observer) => {
|
|
48
|
-
let mutationObserver = new MutationObserver((mutations) => {
|
|
49
|
-
mutations.forEach((record) => {
|
|
50
|
-
for (let node of Array.from(record.removedNodes)) {
|
|
51
|
-
if (node !== element) {
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
observer.next();
|
|
55
|
-
observer.complete();
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
mutationObserver.observe(element.parentNode, {
|
|
60
|
-
childList: true,
|
|
61
|
-
subtree: true,
|
|
62
|
-
});
|
|
63
|
-
return () => {
|
|
64
|
-
mutationObserver.disconnect();
|
|
65
|
-
// we can not re-use this observable, so we have to delete it
|
|
66
|
-
disconnectObservables.delete(cmp);
|
|
67
|
-
};
|
|
68
|
-
});
|
|
69
|
-
};
|
|
70
|
-
/**
|
|
71
|
-
* Creates an observable that emits a value when the component
|
|
72
|
-
* is disconnected from DOM.
|
|
73
|
-
*
|
|
74
|
-
* {@internal}
|
|
75
|
-
*/
|
|
76
|
-
function createDisconnectObservable(cmp) {
|
|
77
|
-
let functions = [
|
|
78
|
-
createUsingDisconnectedCallback,
|
|
79
|
-
createUsingMutationObserver,
|
|
80
|
-
];
|
|
81
|
-
for (let fn of functions) {
|
|
82
|
-
try {
|
|
83
|
-
disconnectObservables.set(cmp, fn(cmp));
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
catch (e) {
|
|
87
|
-
// noop
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
throw new Error(`Could not create disconnect observable for component "${cmp.constructor.name}".`);
|
|
91
|
-
}
|
|
2
|
+
import { Subject, takeUntil, } from "rxjs";
|
|
3
|
+
let observables = new WeakMap();
|
|
92
4
|
/**
|
|
93
5
|
* Operator that unsubscribes from the source observable when
|
|
94
6
|
* the component is disconnected from DOM.
|
|
95
7
|
*/
|
|
96
8
|
export function untilDisconnected(cmp) {
|
|
97
9
|
return (source) => {
|
|
98
|
-
|
|
99
|
-
|
|
10
|
+
let element = getElement(cmp);
|
|
11
|
+
if (!observables.has(element)) {
|
|
12
|
+
let observable = new Subject();
|
|
13
|
+
let previous = cmp.disconnectedCallback;
|
|
14
|
+
cmp.disconnectedCallback = function () {
|
|
15
|
+
previous === null || previous === void 0 ? void 0 : previous.call(this);
|
|
16
|
+
observable.next();
|
|
17
|
+
};
|
|
18
|
+
observables.set(element, observable.asObservable());
|
|
100
19
|
}
|
|
101
|
-
|
|
102
|
-
return source.pipe(takeUntil(disconnectObservable$));
|
|
20
|
+
return source.pipe(takeUntil(observables.get(element)));
|
|
103
21
|
};
|
|
104
22
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { getElement, } from "@stencil/core";
|
|
2
|
+
import { filter, Subject, tap, merge, } from "rxjs";
|
|
3
|
+
/**
|
|
4
|
+
* Operator that emits values from the source observable only
|
|
5
|
+
* while the component is connected to DOM.
|
|
6
|
+
*
|
|
7
|
+
* This can be useful for cases where you want to move components in and out of the DOM,
|
|
8
|
+
* but still want to receive values from an observable while the component is connected
|
|
9
|
+
* and react to them.
|
|
10
|
+
*/
|
|
11
|
+
export function whileConnected(cmp, options) {
|
|
12
|
+
return (source) => {
|
|
13
|
+
let element = getElement(cmp);
|
|
14
|
+
let reemit = (options === null || options === void 0 ? void 0 : options.reemit) || false;
|
|
15
|
+
if (!reemit) {
|
|
16
|
+
return source.pipe(filter(() => element.isConnected));
|
|
17
|
+
}
|
|
18
|
+
let captured = false;
|
|
19
|
+
let last = undefined;
|
|
20
|
+
let reemiter = new Subject();
|
|
21
|
+
let previousConnectedCallback = cmp.connectedCallback;
|
|
22
|
+
cmp.connectedCallback = function () {
|
|
23
|
+
previousConnectedCallback === null || previousConnectedCallback === void 0 ? void 0 : previousConnectedCallback.call(this);
|
|
24
|
+
if (!captured) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
reemiter.next(last);
|
|
28
|
+
captured = false;
|
|
29
|
+
last = undefined;
|
|
30
|
+
};
|
|
31
|
+
return merge(reemiter, source.pipe(tap((value) => {
|
|
32
|
+
if (element.isConnected) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
captured = true;
|
|
36
|
+
last = value;
|
|
37
|
+
}), filter(() => element.isConnected)));
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export * from './set-property';
|
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
import { forceUpdate, } from "@stencil/core";
|
|
2
|
+
/**
|
|
3
|
+
* Set a property on a Stencil component and optionally schedule a render.
|
|
4
|
+
*
|
|
5
|
+
* This function returns a setter function that can be used to update the property value. Common use case
|
|
6
|
+
* is to set it as subscriber to an observable, so that the property is updated whenever the observable
|
|
7
|
+
* emits a new value.
|
|
8
|
+
*
|
|
9
|
+
* @param {ComponentInterface} cmp Component instance on which the property is to be set.
|
|
10
|
+
* @param {string} property Name of the property to be set on the component.
|
|
11
|
+
* @param {SetPropertyOptions} options Options to control the behavior of the property setter,
|
|
12
|
+
* such as whether to schedule a render and whether to do
|
|
13
|
+
* it on the next tick.
|
|
14
|
+
*/
|
|
2
15
|
export function setProperty(cmp, property, options = {}) {
|
|
3
16
|
let resolvedOptions = Object.assign({ scheduleRender: false, nextTick: true }, options);
|
|
4
17
|
return (value) => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Host, h, } from "@stencil/core";
|
|
2
|
+
import { fromEvent, untilDisconnected, } from "../../../../rx";
|
|
3
|
+
export class TestFromEvent {
|
|
4
|
+
constructor() {
|
|
5
|
+
this._elementCounter = 0;
|
|
6
|
+
this._delegateCounter = 0;
|
|
7
|
+
}
|
|
8
|
+
connectedCallback() {
|
|
9
|
+
fromEvent(this, 'click')
|
|
10
|
+
.pipe(untilDisconnected(this))
|
|
11
|
+
.subscribe(() => {
|
|
12
|
+
this._elementCounter++;
|
|
13
|
+
});
|
|
14
|
+
fromEvent(this, 'click', 'span')
|
|
15
|
+
.pipe(untilDisconnected(this))
|
|
16
|
+
.subscribe(() => {
|
|
17
|
+
this._delegateCounter++;
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
render() {
|
|
21
|
+
return (h(Host, { key: '7a79760391921fbf7fb2a5f253bb01d060dd61e4' }, this._elementCounter, "/", h("span", { key: '74da459845a6d1c635d21ab7d781b70ab41fbbc5', id: "delegate" }, this._delegateCounter)));
|
|
22
|
+
}
|
|
23
|
+
static get is() { return "test-from-event"; }
|
|
24
|
+
static get states() {
|
|
25
|
+
return {
|
|
26
|
+
"_elementCounter": {},
|
|
27
|
+
"_delegateCounter": {}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Host, h, } from "@stencil/core";
|
|
2
|
+
import { map, } from "rxjs";
|
|
3
|
+
import { propertiesObservable, untilDisconnected, } from "../../../../rx";
|
|
4
|
+
export class TestPropertiesObservable {
|
|
5
|
+
constructor() {
|
|
6
|
+
this._value = undefined;
|
|
7
|
+
}
|
|
8
|
+
connectedCallback() {
|
|
9
|
+
propertiesObservable(this, 'foo', 'bar', 'baz')
|
|
10
|
+
.pipe(map(([foo, bar, baz]) => {
|
|
11
|
+
this._value = `Foo: "${foo}", Bar: "${bar}", Baz: "${baz}"`;
|
|
12
|
+
}), untilDisconnected(this))
|
|
13
|
+
.subscribe();
|
|
14
|
+
}
|
|
15
|
+
render() {
|
|
16
|
+
return (h(Host, { key: 'b69107bec9636608215a705991bbbb0bf17ad303' }, this._value));
|
|
17
|
+
}
|
|
18
|
+
static get is() { return "test-properties-observable"; }
|
|
19
|
+
static get properties() {
|
|
20
|
+
return {
|
|
21
|
+
"foo": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"mutable": false,
|
|
24
|
+
"complexType": {
|
|
25
|
+
"original": "string",
|
|
26
|
+
"resolved": "string",
|
|
27
|
+
"references": {}
|
|
28
|
+
},
|
|
29
|
+
"required": true,
|
|
30
|
+
"optional": false,
|
|
31
|
+
"docs": {
|
|
32
|
+
"tags": [],
|
|
33
|
+
"text": ""
|
|
34
|
+
},
|
|
35
|
+
"getter": false,
|
|
36
|
+
"setter": false,
|
|
37
|
+
"reflect": false,
|
|
38
|
+
"attribute": "foo"
|
|
39
|
+
},
|
|
40
|
+
"bar": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"mutable": false,
|
|
43
|
+
"complexType": {
|
|
44
|
+
"original": "string",
|
|
45
|
+
"resolved": "string",
|
|
46
|
+
"references": {}
|
|
47
|
+
},
|
|
48
|
+
"required": true,
|
|
49
|
+
"optional": false,
|
|
50
|
+
"docs": {
|
|
51
|
+
"tags": [],
|
|
52
|
+
"text": ""
|
|
53
|
+
},
|
|
54
|
+
"getter": false,
|
|
55
|
+
"setter": false,
|
|
56
|
+
"reflect": false,
|
|
57
|
+
"attribute": "bar"
|
|
58
|
+
},
|
|
59
|
+
"baz": {
|
|
60
|
+
"type": "string",
|
|
61
|
+
"mutable": false,
|
|
62
|
+
"complexType": {
|
|
63
|
+
"original": "string",
|
|
64
|
+
"resolved": "string",
|
|
65
|
+
"references": {}
|
|
66
|
+
},
|
|
67
|
+
"required": true,
|
|
68
|
+
"optional": false,
|
|
69
|
+
"docs": {
|
|
70
|
+
"tags": [],
|
|
71
|
+
"text": ""
|
|
72
|
+
},
|
|
73
|
+
"getter": false,
|
|
74
|
+
"setter": false,
|
|
75
|
+
"reflect": false,
|
|
76
|
+
"attribute": "baz"
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
static get states() {
|
|
81
|
+
return {
|
|
82
|
+
"_value": {}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Host, h, } from "@stencil/core";
|
|
2
|
+
import { propertyObservable, setProperty, untilDisconnected, } from "../../../../rx";
|
|
3
|
+
export class TestPropertyObservable {
|
|
4
|
+
constructor() {
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
this.prop = 'foo';
|
|
7
|
+
}
|
|
8
|
+
connectedCallback() {
|
|
9
|
+
propertyObservable(this, 'prop')
|
|
10
|
+
.pipe(untilDisconnected(this))
|
|
11
|
+
.subscribe(setProperty(this, 'value', {
|
|
12
|
+
scheduleRender: true,
|
|
13
|
+
}));
|
|
14
|
+
}
|
|
15
|
+
async setValue(value) {
|
|
16
|
+
this.prop = value;
|
|
17
|
+
}
|
|
18
|
+
render() {
|
|
19
|
+
return (h(Host, { key: '092d6fe0477d9ddfc771b152fe132c26e5dc04f0' }, this.value));
|
|
20
|
+
}
|
|
21
|
+
static get is() { return "test-property-observable"; }
|
|
22
|
+
static get methods() {
|
|
23
|
+
return {
|
|
24
|
+
"setValue": {
|
|
25
|
+
"complexType": {
|
|
26
|
+
"signature": "(value: string) => Promise<void>",
|
|
27
|
+
"parameters": [{
|
|
28
|
+
"name": "value",
|
|
29
|
+
"type": "string",
|
|
30
|
+
"docs": ""
|
|
31
|
+
}],
|
|
32
|
+
"references": {
|
|
33
|
+
"Promise": {
|
|
34
|
+
"location": "global",
|
|
35
|
+
"id": "global::Promise"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"return": "Promise<void>"
|
|
39
|
+
},
|
|
40
|
+
"docs": {
|
|
41
|
+
"text": "",
|
|
42
|
+
"tags": []
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { describe, it, expect, } from "@stencil/vitest";
|
|
2
|
+
import { vi } from "vitest";
|
|
3
|
+
import { renderObservable } from "../../../rx";
|
|
4
|
+
vi.mock('../../../utils/stencil', () => ({
|
|
5
|
+
getComponentTagName: vi.fn(() => 'foo'),
|
|
6
|
+
isRendered: vi.fn(() => false),
|
|
7
|
+
}));
|
|
8
|
+
describe('renderObservable()', () => {
|
|
9
|
+
it('Emits on each render.', async () => {
|
|
10
|
+
let cmp = new ComponentMockWithRender();
|
|
11
|
+
let count = 0;
|
|
12
|
+
let subscription = renderObservable(cmp).subscribe(() => {
|
|
13
|
+
count++;
|
|
14
|
+
});
|
|
15
|
+
cmp.render();
|
|
16
|
+
cmp.render();
|
|
17
|
+
cmp.render();
|
|
18
|
+
await Promise.resolve();
|
|
19
|
+
expect(count).toStrictEqual(3);
|
|
20
|
+
subscription.unsubscribe();
|
|
21
|
+
cmp.render();
|
|
22
|
+
await Promise.resolve();
|
|
23
|
+
expect(count).toStrictEqual(3);
|
|
24
|
+
});
|
|
25
|
+
it('Throws if component does not have a render function.', () => {
|
|
26
|
+
let cmp = new ComponentMockWithoutRender();
|
|
27
|
+
expect(() => {
|
|
28
|
+
renderObservable(cmp);
|
|
29
|
+
}).toThrow('Component "foo" does not have a render function.');
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
class ComponentMockWithoutRender {
|
|
33
|
+
}
|
|
34
|
+
class ComponentMockWithRender {
|
|
35
|
+
render() {
|
|
36
|
+
// noop.
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { Host, h, } from "@stencil/core";
|
|
2
|
+
import { viewChildObservable } from "../../../../rx";
|
|
3
|
+
export class TestViewChildObservableShadowDom {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.which = 'all';
|
|
6
|
+
this._log = [];
|
|
7
|
+
}
|
|
8
|
+
async getLog() {
|
|
9
|
+
return this._log;
|
|
10
|
+
}
|
|
11
|
+
async clearLog() {
|
|
12
|
+
this._log = [];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* {@inheritdoc}
|
|
16
|
+
*/
|
|
17
|
+
connectedCallback() {
|
|
18
|
+
viewChildObservable(this, 'div')
|
|
19
|
+
.subscribe((el) => {
|
|
20
|
+
this._log.push(`viewChildObservable@connectedCallback: ${el === null || el === void 0 ? void 0 : el.id}`);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
render() {
|
|
24
|
+
return (h(Host, { key: '3d253195f6c56cf48990e6daf7dde10971753a74' }, this.which !== 'even'
|
|
25
|
+
? (h("div", { id: "test-1", class: "odd all", key: "test-1" }, "1"))
|
|
26
|
+
: null, this.which !== 'odd'
|
|
27
|
+
? (h("div", { id: "test-2", class: "even all", key: "test-2" }, "2"))
|
|
28
|
+
: null, this.which !== 'even'
|
|
29
|
+
? (h("div", { id: "test-3", class: "odd all", key: "test-3" }, "3"))
|
|
30
|
+
: null, h("slot", { key: '141bd2c2626e1b89acc55ee79d7fa89e4b767e52' })));
|
|
31
|
+
}
|
|
32
|
+
static get is() { return "test-view-child-observable-shadow-dom"; }
|
|
33
|
+
static get encapsulation() { return "shadow"; }
|
|
34
|
+
static get properties() {
|
|
35
|
+
return {
|
|
36
|
+
"which": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"mutable": false,
|
|
39
|
+
"complexType": {
|
|
40
|
+
"original": "'even' | 'odd' | 'all'",
|
|
41
|
+
"resolved": "\"all\" | \"even\" | \"odd\"",
|
|
42
|
+
"references": {}
|
|
43
|
+
},
|
|
44
|
+
"required": false,
|
|
45
|
+
"optional": false,
|
|
46
|
+
"docs": {
|
|
47
|
+
"tags": [],
|
|
48
|
+
"text": ""
|
|
49
|
+
},
|
|
50
|
+
"getter": false,
|
|
51
|
+
"setter": false,
|
|
52
|
+
"reflect": false,
|
|
53
|
+
"attribute": "which",
|
|
54
|
+
"defaultValue": "'all'"
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
static get methods() {
|
|
59
|
+
return {
|
|
60
|
+
"getLog": {
|
|
61
|
+
"complexType": {
|
|
62
|
+
"signature": "() => Promise<string[]>",
|
|
63
|
+
"parameters": [],
|
|
64
|
+
"references": {
|
|
65
|
+
"Promise": {
|
|
66
|
+
"location": "global",
|
|
67
|
+
"id": "global::Promise"
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"return": "Promise<string[]>"
|
|
71
|
+
},
|
|
72
|
+
"docs": {
|
|
73
|
+
"text": "",
|
|
74
|
+
"tags": []
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"clearLog": {
|
|
78
|
+
"complexType": {
|
|
79
|
+
"signature": "() => Promise<void>",
|
|
80
|
+
"parameters": [],
|
|
81
|
+
"references": {
|
|
82
|
+
"Promise": {
|
|
83
|
+
"location": "global",
|
|
84
|
+
"id": "global::Promise"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"return": "Promise<void>"
|
|
88
|
+
},
|
|
89
|
+
"docs": {
|
|
90
|
+
"text": "",
|
|
91
|
+
"tags": []
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Host, h, } from "@stencil/core";
|
|
2
|
+
import { fromEvent, scheduleRender, untilDisconnected, } from "../../../../rx";
|
|
3
|
+
export class TestScheduleRender {
|
|
4
|
+
constructor() {
|
|
5
|
+
this._counter = 0;
|
|
6
|
+
}
|
|
7
|
+
connectedCallback() {
|
|
8
|
+
fromEvent(this, 'click')
|
|
9
|
+
.pipe(scheduleRender(this), untilDisconnected(this))
|
|
10
|
+
.subscribe(() => {
|
|
11
|
+
this._counter++;
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
async increase() {
|
|
15
|
+
this._counter++;
|
|
16
|
+
}
|
|
17
|
+
render() {
|
|
18
|
+
return (h(Host, { key: '66f26c1ef51b9e595d13926b1e46d1c7cb015566' }, this._counter));
|
|
19
|
+
}
|
|
20
|
+
static get is() { return "test-schedule-render"; }
|
|
21
|
+
static get methods() {
|
|
22
|
+
return {
|
|
23
|
+
"increase": {
|
|
24
|
+
"complexType": {
|
|
25
|
+
"signature": "() => Promise<void>",
|
|
26
|
+
"parameters": [],
|
|
27
|
+
"references": {
|
|
28
|
+
"Promise": {
|
|
29
|
+
"location": "global",
|
|
30
|
+
"id": "global::Promise"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"return": "Promise<void>"
|
|
34
|
+
},
|
|
35
|
+
"docs": {
|
|
36
|
+
"text": "",
|
|
37
|
+
"tags": []
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|