@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.
- package/dist/array.d.ts +1 -0
- package/dist/array.js +24 -0
- package/dist/date.d.ts +39 -0
- package/dist/date.js +147 -0
- package/dist/directives/lazy-until.d.ts +43 -0
- package/dist/directives/lazy-until.js +142 -0
- package/dist/directives/measure.d.ts +12 -0
- package/dist/directives/measure.js +24 -0
- package/dist/directives/portal.d.ts +15 -0
- package/dist/directives/portal.js +58 -0
- package/dist/directives/spread-props.d.ts +9 -0
- package/dist/directives/spread-props.js +22 -0
- package/dist/elements/cz-icon.d.ts +8 -0
- package/dist/elements/cz-icon.js +15 -0
- package/dist/elements/cz-spinner.d.ts +1 -0
- package/dist/elements/cz-spinner.js +22 -0
- package/dist/elements/index.d.ts +2 -0
- package/dist/elements/index.js +2 -0
- package/dist/function.d.ts +5 -0
- package/dist/function.js +4 -0
- package/dist/haunted-polymer.d.ts +341 -0
- package/dist/haunted-polymer.js +83 -0
- package/dist/hooks/use-debounce-raf.d.ts +16 -0
- package/dist/hooks/use-debounce-raf.js +36 -0
- package/dist/hooks/use-dropped-files.d.ts +1 -0
- package/dist/hooks/use-dropped-files.js +7 -0
- package/dist/hooks/use-handle-drop.d.ts +1 -0
- package/dist/hooks/use-handle-drop.js +18 -0
- package/dist/hooks/use-host-bounds.d.ts +2 -0
- package/dist/hooks/use-host-bounds.js +12 -0
- package/dist/hooks/use-host.d.ts +3 -0
- package/dist/hooks/use-host.js +6 -0
- package/dist/hooks/use-imperative-api.d.ts +1 -0
- package/dist/hooks/use-imperative-api.js +18 -0
- package/dist/hooks/use-meta.d.ts +8 -0
- package/{lib → dist}/hooks/use-meta.js +3 -5
- package/dist/hooks/use-notify-property.d.ts +2 -0
- package/dist/hooks/use-notify-property.js +19 -0
- package/dist/hooks/use-promise.d.ts +1 -0
- package/dist/hooks/use-promise.js +42 -0
- package/dist/index.d.ts +26 -0
- package/{index.js → dist/index.js} +14 -24
- package/dist/money.d.ts +47 -0
- package/dist/money.js +86 -0
- package/dist/object.d.ts +21 -0
- package/dist/object.js +56 -0
- package/dist/promise.d.ts +10 -0
- package/dist/promise.js +66 -0
- package/dist/reduce/action.d.ts +13 -0
- package/dist/reduce/action.js +10 -0
- package/{lib/reduce/index.js → dist/reduce/index.d.ts} +0 -0
- package/dist/reduce/index.js +2 -0
- package/dist/reduce/reduce.d.ts +1 -0
- package/dist/reduce/reduce.js +12 -0
- package/dist/tag.d.ts +23 -0
- package/dist/tag.js +28 -0
- package/dist/tagged.d.ts +1 -0
- package/{lib → dist}/tagged.js +0 -0
- package/dist/template.d.ts +47 -0
- package/dist/template.js +66 -0
- package/package.json +20 -6
- package/lib/array.js +0 -27
- package/lib/date.js +0 -176
- package/lib/directives/lazy-until.js +0 -163
- package/lib/directives/measure.js +0 -32
- package/lib/directives/portal.js +0 -65
- package/lib/directives/spread-props.js +0 -31
- package/lib/function.js +0 -21
- package/lib/haunted-polymer.js +0 -93
- package/lib/hooks/use-debounce-raf.js +0 -49
- package/lib/hooks/use-dropped-files.js +0 -12
- package/lib/hooks/use-handle-drop.js +0 -22
- package/lib/hooks/use-host-bounds.js +0 -21
- package/lib/hooks/use-host.js +0 -9
- package/lib/hooks/use-imperative-api.js +0 -22
- package/lib/hooks/use-notify-property.js +0 -26
- package/lib/hooks/use-promise.js +0 -74
- package/lib/money.js +0 -105
- package/lib/object.js +0 -26
- package/lib/promise.js +0 -88
- package/lib/reduce/action.js +0 -16
- package/lib/reduce/reduce.js +0 -16
- package/lib/tag.js +0 -34
- package/lib/template.js +0 -89
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neovici/cosmoz-utils",
|
|
3
|
-
"version": "
|
|
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
|
|
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);
|
package/lib/directives/portal.js
DELETED
|
@@ -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
|
-
};
|
package/lib/haunted-polymer.js
DELETED
|
@@ -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
|
-
};
|