@neovici/cosmoz-utils 4.0.0-beta.2 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/dist/array.d.ts +1 -0
  2. package/dist/array.js +24 -0
  3. package/dist/date.d.ts +39 -0
  4. package/dist/date.js +147 -0
  5. package/dist/directives/lazy-until.d.ts +43 -0
  6. package/dist/directives/lazy-until.js +142 -0
  7. package/dist/directives/measure.d.ts +12 -0
  8. package/dist/directives/measure.js +24 -0
  9. package/dist/directives/portal.d.ts +15 -0
  10. package/dist/directives/portal.js +58 -0
  11. package/dist/directives/spread-props.d.ts +9 -0
  12. package/dist/directives/spread-props.js +22 -0
  13. package/dist/elements/cz-icon.d.ts +8 -0
  14. package/dist/elements/cz-icon.js +15 -0
  15. package/dist/elements/cz-spinner.d.ts +1 -0
  16. package/dist/elements/cz-spinner.js +22 -0
  17. package/dist/elements/index.d.ts +2 -0
  18. package/dist/elements/index.js +2 -0
  19. package/dist/function.d.ts +5 -0
  20. package/dist/function.js +4 -0
  21. package/dist/haunted-polymer.d.ts +341 -0
  22. package/dist/haunted-polymer.js +83 -0
  23. package/dist/hooks/use-debounce-raf.d.ts +16 -0
  24. package/dist/hooks/use-debounce-raf.js +36 -0
  25. package/dist/hooks/use-dropped-files.d.ts +1 -0
  26. package/dist/hooks/use-dropped-files.js +7 -0
  27. package/dist/hooks/use-handle-drop.d.ts +1 -0
  28. package/dist/hooks/use-handle-drop.js +18 -0
  29. package/dist/hooks/use-host-bounds.d.ts +2 -0
  30. package/dist/hooks/use-host-bounds.js +12 -0
  31. package/dist/hooks/use-host.d.ts +3 -0
  32. package/dist/hooks/use-host.js +6 -0
  33. package/dist/hooks/use-imperative-api.d.ts +1 -0
  34. package/dist/hooks/use-imperative-api.js +18 -0
  35. package/dist/hooks/use-meta.d.ts +8 -0
  36. package/{lib → dist}/hooks/use-meta.js +3 -5
  37. package/dist/hooks/use-notify-property.d.ts +2 -0
  38. package/dist/hooks/use-notify-property.js +19 -0
  39. package/dist/hooks/use-promise.d.ts +1 -0
  40. package/dist/hooks/use-promise.js +42 -0
  41. package/dist/index.d.ts +26 -0
  42. package/{index.js → dist/index.js} +14 -24
  43. package/dist/money.d.ts +47 -0
  44. package/dist/money.js +86 -0
  45. package/dist/object.d.ts +21 -0
  46. package/dist/object.js +56 -0
  47. package/dist/promise.d.ts +10 -0
  48. package/dist/promise.js +66 -0
  49. package/dist/reduce/action.d.ts +13 -0
  50. package/dist/reduce/action.js +10 -0
  51. package/{lib/reduce/index.js → dist/reduce/index.d.ts} +0 -0
  52. package/dist/reduce/index.js +2 -0
  53. package/dist/reduce/reduce.d.ts +1 -0
  54. package/dist/reduce/reduce.js +12 -0
  55. package/dist/tag.d.ts +23 -0
  56. package/dist/tag.js +28 -0
  57. package/dist/tagged.d.ts +1 -0
  58. package/{lib → dist}/tagged.js +0 -0
  59. package/dist/template.d.ts +47 -0
  60. package/dist/template.js +66 -0
  61. package/package.json +20 -6
  62. package/lib/array.js +0 -27
  63. package/lib/date.js +0 -176
  64. package/lib/directives/lazy-until.js +0 -163
  65. package/lib/directives/measure.js +0 -32
  66. package/lib/directives/portal.js +0 -65
  67. package/lib/directives/spread-props.js +0 -31
  68. package/lib/function.js +0 -21
  69. package/lib/haunted-polymer.js +0 -93
  70. package/lib/hooks/use-debounce-raf.js +0 -49
  71. package/lib/hooks/use-dropped-files.js +0 -12
  72. package/lib/hooks/use-handle-drop.js +0 -22
  73. package/lib/hooks/use-host-bounds.js +0 -21
  74. package/lib/hooks/use-host.js +0 -9
  75. package/lib/hooks/use-imperative-api.js +0 -22
  76. package/lib/hooks/use-notify-property.js +0 -26
  77. package/lib/hooks/use-promise.js +0 -74
  78. package/lib/money.js +0 -105
  79. package/lib/object.js +0 -26
  80. package/lib/promise.js +0 -88
  81. package/lib/reduce/action.js +0 -16
  82. package/lib/reduce/reduce.js +0 -16
  83. package/lib/tag.js +0 -34
  84. package/lib/template.js +0 -89
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neovici/cosmoz-utils",
3
- "version": "4.0.0-beta.2",
3
+ "version": "5.1.0",
4
4
  "description": "Date, money and template management functions commonly needed in Cosmoz views.",
5
5
  "keywords": [
6
6
  "polymer",
@@ -16,12 +16,16 @@
16
16
  },
17
17
  "license": "Apache-2.0",
18
18
  "author": "Neovici Development",
19
- "main": "index.js",
19
+ "main": "dist/index.js",
20
20
  "directories": {
21
21
  "test": "test"
22
22
  },
23
+ "files": [
24
+ "dist/"
25
+ ],
23
26
  "scripts": {
24
- "lint": "eslint --cache --ext .js .",
27
+ "lint": "tsc && eslint --cache .",
28
+ "build": "tsc -p tsconfig.build.json",
25
29
  "start": "wds",
26
30
  "test": "wtr --coverage",
27
31
  "test:watch": "wtr --watch",
@@ -41,14 +45,24 @@
41
45
  "publishConfig": {
42
46
  "access": "public"
43
47
  },
44
- "files": [
45
- "lib/**/*.js"
46
- ],
47
48
  "commitlint": {
48
49
  "extends": [
49
50
  "@commitlint/config-conventional"
50
51
  ]
51
52
  },
53
+ "exports": {
54
+ ".": "./dist/index.js",
55
+ "./object": "./dist/object.js",
56
+ "./function": "./dist/function.js",
57
+ "./array": "./dist/array.js",
58
+ "./promise": "./dist/promise.js",
59
+ "./tag": "./dist/tag.js",
60
+ "./reduce": "./dist/reduce/index.js",
61
+ "./elements": "./dist/elements/index.js",
62
+ "./elements/*": "./dist/elements/*.js",
63
+ "./directives/*": "./dist/directives/*.js",
64
+ "./hooks/*": "./dist/hooks/*.js"
65
+ },
52
66
  "dependencies": {
53
67
  "haunted": "^5.0.0"
54
68
  },
package/lib/array.js DELETED
@@ -1,27 +0,0 @@
1
- import { identity } from './function';
2
-
3
- const array = arr => {
4
- if (arr == null) {
5
- return [];
6
- }
7
- if (Array.isArray(arr)) {
8
- return arr;
9
- }
10
- if (typeof arr === 'string') {
11
- return [arr];
12
- }
13
- if (typeof arr[Symbol.iterator] === 'function') {
14
- return Array.from(arr);
15
- }
16
- return [arr];
17
- },
18
- without = (exclude, predicate = identity) => list => {
19
- const excludes = array(exclude).map(predicate);
20
- return array(list).filter(value => !excludes.includes(predicate(value)));
21
- };
22
-
23
-
24
- export {
25
- array,
26
- without
27
- };
package/lib/date.js DELETED
@@ -1,176 +0,0 @@
1
- const
2
- getValUnitDiff = (date1, date2) => {
3
- const msDiff = date1.getTime() - date2.getTime(),
4
- secDiff = msDiff / 1000,
5
- minDiff = secDiff / 60,
6
- hourDiff = minDiff / 60,
7
- dayDiff = hourDiff / 24,
8
- monthDiff = dayDiff / 30,
9
- yearDiff = monthDiff / 12;
10
- if (Math.abs(yearDiff) >= 1) {
11
- return [yearDiff, 'year'];
12
- }
13
- if (Math.abs(monthDiff) >= 1) {
14
- return [monthDiff, 'month'];
15
- }
16
- if (Math.abs(dayDiff) >= 1) {
17
- return [dayDiff, 'day'];
18
- }
19
- if (Math.abs(hourDiff) >= 1) {
20
- return [hourDiff, 'hour'];
21
- }
22
- if (Math.abs(minDiff) >= 1) {
23
- return [minDiff, 'minute'];
24
- }
25
- return [secDiff, 'second'];
26
- },
27
- rules = { isoBasic: /^\d{4}-\d{2}-\d{2}$/ui },
28
- parse = val => {
29
- if (typeof val === 'string' && rules.isoBasic.test(val)) {
30
- return new Date(`${ val }T00:00`);
31
- }
32
- return new Date(val);
33
- },
34
- /**
35
- * Validate a Date object or date string.
36
- * @param {date/string} date Date to check.
37
- * @return {date} Validated date or undefined on failure.
38
- */
39
- ensureDate = date => {
40
- if (date == null) {
41
- return;
42
- }
43
- if (date instanceof Date && !isNaN(date)) {
44
- return date;
45
- }
46
-
47
- const ensuredDate = parse(date);
48
-
49
- if (ensuredDate instanceof Date && isNaN(ensuredDate)) {
50
- return;
51
- }
52
- return ensuredDate;
53
- },
54
- /**
55
- * Format a date as an ISO-date - YYYY-MM-DD.
56
- * @param {date/string} date Date to be ISO formatted.
57
- * @return {string} ISO formatted date.
58
- */
59
- isoDate = date => {
60
- const d = ensureDate(date);
61
- if (d == null) {
62
- return '';
63
- }
64
- // Sweden uses ISO8601 human-readable
65
- return d.toLocaleDateString('sv', {
66
- year: 'numeric',
67
- month: 'numeric',
68
- day: 'numeric'
69
- });
70
- },
71
-
72
- /**
73
- * Format a date with time as an ISO date with time - YYYY-MM-DD HH:mm:ss.
74
- * @param {date/string} date Date to be ISO formatted.
75
- * @return {string} ISO formatted date.
76
- */
77
- isoDT = date => {
78
- const d = ensureDate(date);
79
- if (d == null) {
80
- return '';
81
- }
82
- // Sweden uses ISO8601 human-readable
83
- return d.toLocaleDateString('sv', {
84
- year: 'numeric',
85
- month: 'numeric',
86
- day: 'numeric',
87
- hour: 'numeric',
88
- minute: 'numeric',
89
- second: 'numeric'
90
- });
91
- },
92
-
93
- /**
94
- * Check if date is in the past.
95
- * @param {date/string} date Date to check.
96
- * @return {boolean} Whether the date is in the past or not.
97
- */
98
- pastDate = date => {
99
- const d = ensureDate(date);
100
- if (d == null) {
101
- return;
102
- }
103
- return d.getTime() < Date.now();
104
- },
105
-
106
- /**
107
- * Get human readable string describing date's difference from now in the current locale language.
108
- * @param {date/string} date Date to check.
109
- * @param {string} locale Localized lang to return string in (undefined = browser)
110
- * @return {string} Date representation string in the current locale language.
111
- */
112
- timeago = (date, locale) => {
113
- const d = ensureDate(date);
114
- if (d == null) {
115
- return '';
116
- }
117
- return new Intl.RelativeTimeFormat(locale, {
118
- localeMatcher: 'best fit', // other values: "lookup"
119
- numeric: 'auto', // other values: "auto"
120
- style: 'long' // other values: "short" or "narrow"
121
- }).format(...getValUnitDiff(d, new Date()));
122
- },
123
-
124
- /**
125
- * Alias for isoDate(date), format a date as an ISO-date - YYYY-MM-DD.
126
- * @param {date/string} date Date to be formatted.
127
- * @return {string} ISO formatted date.
128
- */
129
- renderDate = isoDate,
130
-
131
- pad = number => number < 10 ? '0' + number : number,
132
-
133
- toLocalISOString = date => {
134
- if (!(date instanceof Date)) {
135
- return null;
136
- }
137
- return date.getFullYear() +
138
- '-' + pad(date.getMonth() + 1) +
139
- '-' + pad(date.getDate()) +
140
- 'T' + pad(date.getHours()) +
141
- ':' + pad(date.getMinutes()) +
142
- ':' + pad(date.getSeconds()) +
143
- '.' + (date.getMilliseconds() / 1000).toFixed(3).slice(2, 5);
144
- },
145
-
146
- parseDate = str => {
147
- const ts = Date.parse(str);
148
- if (isNaN(ts)) {
149
- return;
150
- }
151
- return new Date(ts);
152
- },
153
-
154
- inputDate = date => {
155
- const d = ensureDate(date);
156
- if (d == null) {
157
- return;
158
- }
159
- return d.getFullYear() +
160
- '-' + pad(d.getMonth() + 1) +
161
- '-' + pad(d.getDate());
162
-
163
- };
164
-
165
- export {
166
- ensureDate,
167
- isoDate,
168
- isoDT,
169
- pad,
170
- pastDate,
171
- renderDate,
172
- toLocalISOString,
173
- timeago,
174
- parseDate,
175
- inputDate
176
- };
@@ -1,163 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2017 Google LLC
4
- * SPDX-License-Identifier: BSD-3-Clause
5
- */
6
- /* eslint-disable import/group-exports */
7
- import { noChange } from 'lit-html';
8
- import { directive } from 'lit-html/directive.js';
9
- import { isPrimitive } from 'lit-html/directive-helpers.js';
10
- import { AsyncDirective } from 'lit-html/async-directive.js';
11
-
12
- class PseudoWeakRef {
13
- constructor(ref) {
14
- this._ref = ref;
15
- }
16
- disconnect() {
17
- this._ref = undefined;
18
- }
19
- reconnect(ref) {
20
- this._ref = ref;
21
- }
22
- deref() {
23
- return this._ref;
24
- }
25
- }
26
-
27
- class Pauser {
28
- _promise = undefined;
29
- _resolve = undefined;
30
- get() {
31
- return this._promise;
32
- }
33
- pause() {
34
- this._promise ??= new Promise((resolve) => (this._resolve = resolve));
35
- }
36
- resume() {
37
- this._resolve?.();
38
- this._promise = this._resolve = undefined;
39
- }
40
- }
41
-
42
- const isPromise = (x) => {
43
- return !isPrimitive(x) && typeof x.then === 'function';
44
- },
45
- // Effectively infinity, but a SMI.
46
- _infinity = 0x3fffffff;
47
-
48
- export class UntilDirective extends AsyncDirective {
49
- __lastRenderedIndex = _infinity;
50
- __values = [];
51
- __weakThis = new PseudoWeakRef(this);
52
- __pauser = new Pauser();
53
-
54
- render(...args) {
55
- return args.find((x) => !isPromise(x)) ?? noChange;
56
- }
57
-
58
- // eslint-disable-next-line max-statements
59
- update(_part, args) {
60
- const previousValues = this.__values,
61
- previousLength = previousValues.length;
62
- this.__values = args;
63
-
64
- const weakThis = this.__weakThis,
65
- pauser = this.__pauser;
66
-
67
- // If our initial render occurs while disconnected, ensure that the pauser
68
- // and weakThis are in the disconnected state
69
- if (!this.isConnected) {
70
- this.disconnected();
71
- }
72
-
73
- for (let i = 0; i < args.length; i++) {
74
- // If we've rendered a higher-priority value already, stop.
75
- if (i > this.__lastRenderedIndex) {
76
- break;
77
- }
78
-
79
- const value = args[i];
80
-
81
- // Render non-Promise values immediately
82
- if (!isPromise(value)) {
83
- this.__lastRenderedIndex = i;
84
- // Since a lower-priority value will never overwrite a higher-priority
85
- // synchronous value, we can stop processing now.
86
- return value;
87
- }
88
-
89
- // If this is a Promise we've already handled, skip it.
90
- if (i < previousLength && value === previousValues[i]) {
91
- continue;
92
- }
93
-
94
- // Note, the callback avoids closing over `this` so that the directive
95
- // can be gc'ed before the promise resolves; instead `this` is retrieved
96
- // from `weakThis`, which can break the hard reference in the closure when
97
- // the directive disconnects
98
- Promise.resolve(value).then(async (result) => {
99
- // If we're disconnected, wait until we're (maybe) reconnected
100
- // The while loop here handles the case that the connection state
101
- // thrashes, causing the pauser to resume and then get re-paused
102
- while (pauser.get()) {
103
- await pauser.get();
104
- }
105
- // If the callback gets here and there is no `this`, it means that the
106
- // directive has been disconnected and garbage collected and we don't
107
- // need to do anything else
108
- const _this = weakThis.deref();
109
- if (_this !== undefined) {
110
- const index = _this.__values.indexOf(value);
111
- // If state.values doesn't contain the value, we've re-rendered without
112
- // the value, so don't render it. Then, only render if the value is
113
- // higher-priority than what's already been rendered.
114
- if (index > -1 && index <= _this.__lastRenderedIndex) {
115
- _this.__lastRenderedIndex = index;
116
- _this.setValue(result);
117
- }
118
- }
119
- });
120
- }
121
-
122
- return noChange;
123
- }
124
-
125
- disconnected() {
126
- this.__weakThis.disconnect();
127
- this.__pauser.pause();
128
- }
129
-
130
- reconnected() {
131
- this.__weakThis.reconnect(this);
132
- this.__pauser.resume();
133
- }
134
- }
135
-
136
- /**
137
- * Renders one of a series of values, including Promises, to a Part.
138
- *
139
- * Values are rendered in priority order, with the first argument having the
140
- * highest priority and the last argument having the lowest priority. If a
141
- * value is a Promise, low-priority values will be rendered until it resolves.
142
- *
143
- * The priority of values can be used to create placeholder content for async
144
- * data. For example, a Promise with pending content can be the first,
145
- * highest-priority, argument, and a non_promise loading indicator template can
146
- * be used as the second, lower-priority, argument. The loading indicator will
147
- * render immediately, and the primary content will render when the Promise
148
- * resolves.
149
- *
150
- * Example:
151
- *
152
- * ```js
153
- * const content = fetch('./content.txt').then(r => r.text());
154
- * html`${until(content, html`<span>Loading...</span>`)}`
155
- * ```
156
- */
157
- export const lazyUntil = directive(UntilDirective);
158
-
159
- /**
160
- * The type of the class that powers this directive. Necessary for naming the
161
- * directive's return type.
162
- */
163
- // export type {UntilDirective};
@@ -1,32 +0,0 @@
1
- import { nothing } from 'lit-html';
2
- import { Directive, directive } from 'lit-html/directive.js';
3
- import { array } from '../array';
4
-
5
- class MeasureDirective extends Directive {
6
- render() {
7
- return nothing;
8
- }
9
-
10
- update(part, [select, onMeasure]) {
11
- this.measure(part.element, select, onMeasure);
12
- return nothing;
13
- }
14
-
15
- measure(element, select, onMeasure) {
16
- this._observer?.disconnect();
17
- const elements = array(select(element)),
18
- observer = (this._observer = new ResizeObserver((entries) => {
19
- onMeasure(
20
- entries
21
- .sort(
22
- (a, b) => elements.indexOf(a.target) - elements.indexOf(b.target)
23
- )
24
- .map((e) => e.contentRect)
25
- );
26
- }));
27
- elements.forEach((el) => observer.observe(el));
28
- return nothing;
29
- }
30
- }
31
-
32
- export const measure = directive(MeasureDirective);
@@ -1,65 +0,0 @@
1
- import { html, nothing, render } from 'lit-html';
2
- import { AsyncDirective, directive } from 'lit-html/async-directive.js';
3
- import {
4
- setChildPartValue,
5
- clearPart,
6
- removePart,
7
- } from 'lit-html/directive-helpers.js';
8
- const createMarker = () => document.createComment(''),
9
- ChildPart = render(nothing, new DocumentFragment()).constructor;
10
-
11
- /**
12
- * Helper element with a customizable disconnect behavior.
13
- */
14
- class DisconnectObserver extends HTMLElement {
15
- disconnectedCallback() {
16
- this.onDisconnect();
17
- }
18
- }
19
- customElements.define('disconnect-observer', DisconnectObserver);
20
-
21
- class PortalDirective extends AsyncDirective {
22
- render() {
23
- return html`<disconnect-observer
24
- .onDisconnect=${() => {
25
- this.isConnected = false;
26
- this.disconnected();
27
- }}
28
- ></disconnect-observer>`;
29
- }
30
- update(part, [content, outlet = document.body]) {
31
- this.updateOutlet(outlet, content);
32
- return this.render();
33
- }
34
-
35
- updateOutlet(outlet, content) {
36
- if (this._outlet !== outlet) {
37
- this.clearOutlet();
38
- }
39
- this._outlet = outlet;
40
- const part = (this._op ??= new ChildPart(
41
- outlet.appendChild(createMarker()),
42
- outlet.appendChild(createMarker())
43
- ));
44
- setChildPartValue(part, (this.content = content));
45
- }
46
-
47
- clearOutlet() {
48
- const part = this._op;
49
- if (!part) {
50
- return;
51
- }
52
- clearPart(part);
53
- removePart(part);
54
- this._op = undefined;
55
- }
56
-
57
- disconnected() {
58
- this.clearOutlet();
59
- }
60
- reconnected() {
61
- this.updateOutlet(this._outlet, this._content);
62
- }
63
- }
64
-
65
- export const portal = directive(PortalDirective);
@@ -1,31 +0,0 @@
1
- import { nothing } from 'lit-html';
2
- import { Directive, directive } from 'lit-html/directive.js';
3
-
4
- const undefs = (prev, obj) => {
5
- if (!prev || !obj) {
6
- return;
7
- }
8
- const keys = Object.keys(obj);
9
- return Object.fromEntries(
10
- Object.keys(prev).flatMap((k) => (keys.includes(k) ? [] : [[k, undefined]]))
11
- );
12
- };
13
-
14
- class SpreadPropsDirective extends Directive {
15
- render() {
16
- return nothing;
17
- }
18
-
19
- update(part, [props]) {
20
- if (this._props !== props) {
21
- Object.assign(
22
- part.element,
23
- undefs(this._props, props),
24
- (this._props = props)
25
- );
26
- }
27
- return nothing;
28
- }
29
- }
30
-
31
- export const spreadProps = directive(SpreadPropsDirective);
package/lib/function.js DELETED
@@ -1,21 +0,0 @@
1
- const
2
- constant = v => () => v,
3
- constTrue = constant(true),
4
- constUndefined = constant(),
5
- noop = constUndefined,
6
- identity = obj => obj,
7
- or = (...fns) => (...args) => fns.reduce((res, fn) => res || fn(...args), false),
8
- once = (fn, check = constTrue) => {
9
- let result; // eslint-disable-next-line no-return-assign
10
- return (...args) => result ??= check(args) ? fn(...args) : undefined;
11
- };
12
-
13
- export {
14
- constant,
15
- constTrue,
16
- constUndefined,
17
- noop,
18
- identity,
19
- once,
20
- or
21
- };
@@ -1,93 +0,0 @@
1
- import {
2
- BaseScheduler, render
3
- } from 'haunted';
4
-
5
- class Scheduler extends BaseScheduler {
6
- constructor(renderer, host, commitCallback) {
7
- super(renderer, host);
8
- this._commit = commitCallback;
9
- }
10
-
11
- commit(result) {
12
- this._commit(result);
13
- }
14
- }
15
-
16
- /**
17
- * Creates a mixin that mixes a haunted hook with a polymer component.
18
- *
19
- * @param {String} outputPath The property where the result of the hook will be stored (deprecated)
20
- * @param {Function} hook A haunted hook
21
- * @returns {Function} The mixin
22
- */
23
- export const hauntedPolymer = (outputPath, hook) => base => {
24
- const hasOutputPath = hook !== undefined,
25
- _hook = hasOutputPath ? hook : outputPath;
26
-
27
- // TODO: drop outputPath support after all usages are fixed.
28
- if (hasOutputPath) {
29
- // eslint-disable-next-line no-console
30
- console.warn('Haunted Polymer: use of outputPath is deprecated. Instead have the hook return an object with the keys being property names to update.');
31
- }
32
-
33
- return class extends base {
34
- constructor() {
35
- super();
36
-
37
- this._scheduler = new Scheduler( // whenever the state is updated
38
- () => _hook(this), // run the hook with the element as input
39
- this, // using the element as state host
40
- result => hasOutputPath ? this.set(outputPath, result) : this.setProperties(result) // and update the output path with the results
41
- );
42
- }
43
-
44
- connectedCallback() {
45
- super.connectedCallback();
46
- this._scheduler.update();
47
- }
48
-
49
- disconnectedCallback() {
50
- super.disconnectedCallback();
51
- this._scheduler.teardown();
52
- }
53
-
54
- _propertiesChanged(currentProps, changedProps, oldProps) {
55
- super._propertiesChanged(currentProps, changedProps, oldProps);
56
-
57
- // skip haunted state update if the only thing that has changed is the hook output path
58
- if (hasOutputPath && Object.keys(changedProps).length === 1 && changedProps[outputPath] != null) {
59
- return;
60
- }
61
-
62
- // update haunted state only if a polymer prop has changed
63
- if (this._onlyHauntedPropertiesChanged(changedProps)) {
64
- return;
65
- }
66
-
67
- // trigger a haunted update loop
68
- // do it in the next animation frame, so the current loop finishes processing first
69
- cancelAnimationFrame(this._hauntedUpdateFrameHandle);
70
- this._hauntedUpdateFrameHandle = requestAnimationFrame(() => this._scheduler.update());
71
- }
72
-
73
- _onlyHauntedPropertiesChanged(changedProps) {
74
- const props = this.constructor.__properties;
75
-
76
- if (Object.keys(changedProps)
77
- .map(prop => prop.split('.')[0])
78
- // props updated by haunted are not listed or have the `haunted` flag
79
- .every(prop => props[prop] == null || props[prop].haunted)) {
80
- return true;
81
- }
82
-
83
- return false;
84
- }
85
-
86
- renderLitTo(part, outlet) {
87
- // render in the next animation frame to allow the haunted scheduler to finish processing the current state update
88
- // otherwise hooks might be updated twice
89
- cancelAnimationFrame(outlet.__renderAF);
90
- outlet.__renderAF = requestAnimationFrame(() => render(typeof part === 'function' ? part() : part, outlet));
91
- }
92
- };
93
- };