drab 7.0.2 → 8.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/base/index.d.ts +122 -48
- package/dist/base/index.d.ts.map +1 -1
- package/dist/base/index.js +10 -7
- package/dist/contextmenu/index.d.ts +90 -35
- package/dist/contextmenu/index.d.ts.map +1 -1
- package/dist/define.d.ts +0 -1
- package/dist/define.d.ts.map +1 -1
- package/dist/define.js +0 -1
- package/dist/editor/index.d.ts +90 -35
- package/dist/editor/index.d.ts.map +1 -1
- package/dist/fullscreen/index.d.ts +90 -36
- package/dist/fullscreen/index.d.ts.map +1 -1
- package/dist/fullscreen/index.js +3 -14
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/intersect/index.d.ts +90 -36
- package/dist/intersect/index.d.ts.map +1 -1
- package/dist/intersect/index.js +1 -11
- package/dist/prefetch/index.d.ts +62 -25
- package/dist/prefetch/index.d.ts.map +1 -1
- package/dist/prefetch/index.js +17 -30
- package/dist/share/index.d.ts +120 -47
- package/dist/share/index.d.ts.map +1 -1
- package/dist/tablesort/index.d.ts +120 -47
- package/dist/tablesort/index.d.ts.map +1 -1
- package/dist/tablesort/index.js +54 -54
- package/dist/tabs/index.d.ts +61 -24
- package/dist/tabs/index.d.ts.map +1 -1
- package/dist/tabs/index.js +10 -2
- package/dist/types/index.d.ts +0 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/util/validate.d.ts.map +1 -1
- package/dist/util/validate.js +2 -1
- package/dist/wakelock/index.d.ts +120 -47
- package/dist/wakelock/index.d.ts.map +1 -1
- package/dist/wakelock/index.js +1 -2
- package/package.json +4 -4
- package/src/base/index.ts +10 -7
- package/src/contextmenu/index.ts +2 -3
- package/src/define.ts +0 -1
- package/src/editor/index.ts +1 -2
- package/src/fullscreen/index.ts +6 -18
- package/src/index.ts +0 -1
- package/src/intersect/index.ts +2 -14
- package/src/prefetch/index.ts +21 -36
- package/src/tablesort/index.ts +64 -63
- package/src/tabs/index.ts +16 -2
- package/src/types/index.ts +0 -2
- package/src/util/validate.ts +2 -1
- package/src/wakelock/index.ts +2 -5
- package/dist/dialog/define.d.ts +0 -2
- package/dist/dialog/define.d.ts.map +0 -1
- package/dist/dialog/define.js +0 -3
- package/dist/dialog/index.d.ts +0 -1079
- package/dist/dialog/index.d.ts.map +0 -1
- package/dist/dialog/index.js +0 -90
- package/src/dialog/define.ts +0 -4
- package/src/dialog/index.ts +0 -120
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/wakelock/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,KAAK,iBAAiB,EAGtB,KAAK,iBAAiB,EACtB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,kBAChB,SAAQ,iBAAiB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/wakelock/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,KAAK,iBAAiB,EAGtB,KAAK,iBAAiB,EACtB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,kBAChB,SAAQ,iBAAiB,EAAE,iBAAiB;IAC5C,+DAA+D;IAC/D,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,QAAS,SAAQ,aAAuC;;;IAoBpE,6CAA6C;IACvC,OAAO;IAqBb,2DAA2D;IACrD,OAAO;IAKJ,KAAK;IAoCL,OAAO;CAGhB"}
|
package/dist/wakelock/index.js
CHANGED
|
@@ -88,9 +88,8 @@ export class WakeLock extends Lifecycle(Trigger(Content(Announce()))) {
|
|
|
88
88
|
// When the tab is not visible, the wakeLock is automatically released.
|
|
89
89
|
// This requests it back if it exists, if it is `null`, that
|
|
90
90
|
// means it was removed. In which case, it shouldn't be requested again.
|
|
91
|
-
if (this.#wakeLock)
|
|
91
|
+
if (this.#wakeLock)
|
|
92
92
|
this.request();
|
|
93
|
-
}
|
|
94
93
|
}, document);
|
|
95
94
|
}
|
|
96
95
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "drab",
|
|
3
3
|
"description": "Interactivity for You",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "8.0.0",
|
|
5
5
|
"homepage": "https://drab.robino.dev",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": {
|
|
@@ -151,8 +151,8 @@
|
|
|
151
151
|
"!src/**/*.test.ts"
|
|
152
152
|
],
|
|
153
153
|
"scripts": {
|
|
154
|
-
"check": "tsc
|
|
155
|
-
"dev": "tsc --watch",
|
|
156
|
-
"build": "tsc"
|
|
154
|
+
"check": "tsc",
|
|
155
|
+
"dev": "tsc --watch -p tsconfig.build.json",
|
|
156
|
+
"build": "tsc -p tsconfig.build.json"
|
|
157
157
|
}
|
|
158
158
|
}
|
package/src/base/index.ts
CHANGED
|
@@ -17,7 +17,7 @@ export const Lifecycle = <T extends Constructor<HTMLElement>>(
|
|
|
17
17
|
) =>
|
|
18
18
|
class Lifecycle extends Super {
|
|
19
19
|
/** To clean up event listeners added to `document` when the element is removed. */
|
|
20
|
-
|
|
20
|
+
controller = new AbortController();
|
|
21
21
|
|
|
22
22
|
constructor(...args: any[]) {
|
|
23
23
|
super(...args);
|
|
@@ -56,8 +56,10 @@ export const Lifecycle = <T extends Constructor<HTMLElement>>(
|
|
|
56
56
|
target: EventTarget = document.body,
|
|
57
57
|
options: AddEventListenerOptions = {},
|
|
58
58
|
) {
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
target.addEventListener(type, listener, {
|
|
60
|
+
...options,
|
|
61
|
+
signal: this.controller.signal,
|
|
62
|
+
});
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
/**
|
|
@@ -85,7 +87,7 @@ export const Lifecycle = <T extends Constructor<HTMLElement>>(
|
|
|
85
87
|
/** Called when custom element is removed from the page. */
|
|
86
88
|
disconnectedCallback() {
|
|
87
89
|
this.destroy();
|
|
88
|
-
this
|
|
90
|
+
this.controller.abort();
|
|
89
91
|
}
|
|
90
92
|
};
|
|
91
93
|
|
|
@@ -113,7 +115,8 @@ export const Trigger = <T extends Constructor<HTMLElement>>(
|
|
|
113
115
|
/**
|
|
114
116
|
* Event for the `trigger` to execute.
|
|
115
117
|
*
|
|
116
|
-
* For example, set to `"mouseover"` to execute the event when the user
|
|
118
|
+
* For example, set to `"mouseover"` to execute the event when the user
|
|
119
|
+
* hovers the mouse over the `trigger`, instead of when they click it.
|
|
117
120
|
*
|
|
118
121
|
* @default "click"
|
|
119
122
|
*/
|
|
@@ -275,7 +278,7 @@ export const Announce = <T extends Constructor<HTMLElement>>(
|
|
|
275
278
|
* A single `Announcer` element to share between all drab elements to announce
|
|
276
279
|
* interactive changes.
|
|
277
280
|
*/
|
|
278
|
-
static
|
|
281
|
+
static announcer = Announcer.init();
|
|
279
282
|
|
|
280
283
|
constructor(...args: any[]) {
|
|
281
284
|
super(...args);
|
|
@@ -285,6 +288,6 @@ export const Announce = <T extends Constructor<HTMLElement>>(
|
|
|
285
288
|
* @param message message to announce to screen readers
|
|
286
289
|
*/
|
|
287
290
|
announce(message: string) {
|
|
288
|
-
Announce
|
|
291
|
+
Announce.announcer.announce(message);
|
|
289
292
|
}
|
|
290
293
|
};
|
package/src/contextmenu/index.ts
CHANGED
|
@@ -7,15 +7,14 @@ import {
|
|
|
7
7
|
} from "../base/index.js";
|
|
8
8
|
|
|
9
9
|
export interface ContextMenuAttributes
|
|
10
|
-
extends TriggerAttributes,
|
|
11
|
-
ContentAttributes {}
|
|
10
|
+
extends TriggerAttributes, ContentAttributes {}
|
|
12
11
|
|
|
13
12
|
/**
|
|
14
13
|
* Displays content when the `trigger` element is right clicked, or long pressed on mobile.
|
|
15
14
|
*/
|
|
16
15
|
export class ContextMenu extends Lifecycle(Trigger(Content())) {
|
|
17
16
|
/** Tracks the long press duration on mobile. */
|
|
18
|
-
#touchTimer:
|
|
17
|
+
#touchTimer: number | undefined;
|
|
19
18
|
|
|
20
19
|
constructor() {
|
|
21
20
|
super();
|
package/src/define.ts
CHANGED
package/src/editor/index.ts
CHANGED
package/src/fullscreen/index.ts
CHANGED
|
@@ -7,8 +7,7 @@ import {
|
|
|
7
7
|
} from "../base/index.js";
|
|
8
8
|
|
|
9
9
|
export interface FullscreenAttributes
|
|
10
|
-
extends TriggerAttributes,
|
|
11
|
-
ContentAttributes {}
|
|
10
|
+
extends TriggerAttributes, ContentAttributes {}
|
|
12
11
|
|
|
13
12
|
/**
|
|
14
13
|
* Toggles the `documentElement` or `content` element to fullscreen mode.
|
|
@@ -20,23 +19,9 @@ export class Fullscreen extends Lifecycle(Trigger(Content())) {
|
|
|
20
19
|
super();
|
|
21
20
|
}
|
|
22
21
|
|
|
23
|
-
/**
|
|
24
|
-
* @returns `true` if fullscreen is currently enabled.
|
|
25
|
-
*/
|
|
26
|
-
#isFullscreen() {
|
|
27
|
-
return document.fullscreenElement !== null;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* @returns `true` if fullscreen is supported.
|
|
32
|
-
*/
|
|
33
|
-
#fullscreenSupported() {
|
|
34
|
-
return "requestFullscreen" in document.documentElement;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
22
|
/** Enables or disables fullscreen mode based on the current state. */
|
|
38
23
|
toggle() {
|
|
39
|
-
if (
|
|
24
|
+
if (document.fullscreenElement !== null) {
|
|
40
25
|
document.exitFullscreen();
|
|
41
26
|
} else {
|
|
42
27
|
try {
|
|
@@ -51,7 +36,10 @@ export class Fullscreen extends Lifecycle(Trigger(Content())) {
|
|
|
51
36
|
this.listener(() => this.toggle());
|
|
52
37
|
|
|
53
38
|
for (const trigger of this.triggers()) {
|
|
54
|
-
if (
|
|
39
|
+
if (
|
|
40
|
+
!("requestFullscreen" in document.documentElement) &&
|
|
41
|
+
"disabled" in trigger
|
|
42
|
+
) {
|
|
55
43
|
trigger.disabled = true;
|
|
56
44
|
}
|
|
57
45
|
}
|
package/src/index.ts
CHANGED
package/src/intersect/index.ts
CHANGED
|
@@ -7,8 +7,7 @@ import {
|
|
|
7
7
|
} from "../base/index.js";
|
|
8
8
|
|
|
9
9
|
export interface IntersectAttributes
|
|
10
|
-
extends TriggerAttributes,
|
|
11
|
-
ContentAttributes {
|
|
10
|
+
extends TriggerAttributes, ContentAttributes {
|
|
12
11
|
/** Number between 0 and 1 representing the visible portion of the `trigger`. */
|
|
13
12
|
threshold?: number;
|
|
14
13
|
}
|
|
@@ -40,17 +39,6 @@ export class Intersect extends Lifecycle(Trigger(Content())) {
|
|
|
40
39
|
super();
|
|
41
40
|
}
|
|
42
41
|
|
|
43
|
-
/**
|
|
44
|
-
* How much of the `trigger` should be visible for the intersection to occur.
|
|
45
|
-
* For example, given a threshold of `.5`, the intersection would occur when
|
|
46
|
-
* the `trigger` is 50% visible.
|
|
47
|
-
*
|
|
48
|
-
* @default 0
|
|
49
|
-
*/
|
|
50
|
-
get #threshold() {
|
|
51
|
-
return Number(this.getAttribute("threshold") ?? 0);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
42
|
override mount() {
|
|
55
43
|
const observer = new IntersectionObserver(
|
|
56
44
|
(entries) => {
|
|
@@ -71,7 +59,7 @@ export class Intersect extends Lifecycle(Trigger(Content())) {
|
|
|
71
59
|
);
|
|
72
60
|
}
|
|
73
61
|
},
|
|
74
|
-
{ threshold: this
|
|
62
|
+
{ threshold: Number(this.getAttribute("threshold") ?? 0) },
|
|
75
63
|
);
|
|
76
64
|
|
|
77
65
|
for (const trigger of this.triggers()) observer.observe(trigger);
|
package/src/prefetch/index.ts
CHANGED
|
@@ -77,28 +77,16 @@ export class Prefetch extends Lifecycle(Trigger()) {
|
|
|
77
77
|
super();
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
/** When to prefetch the url. */
|
|
81
|
-
get #strategy() {
|
|
82
|
-
return this.getAttribute("strategy");
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/** Prerender with the Speculation Rules API. */
|
|
86
|
-
get #prerender() {
|
|
87
|
-
return this.hasAttribute("prerender");
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/** `url` to prefetch on `mount`. */
|
|
91
|
-
get #url() {
|
|
92
|
-
return this.getAttribute("url");
|
|
93
|
-
}
|
|
94
|
-
|
|
95
80
|
/**
|
|
96
81
|
* Appends `<link rel="prefetch">` or `<script type="speculationrules">`
|
|
97
82
|
* to the head of the document.
|
|
98
83
|
*
|
|
99
84
|
* @param options Configuration options.
|
|
100
85
|
*/
|
|
101
|
-
prefetch(
|
|
86
|
+
prefetch({
|
|
87
|
+
url,
|
|
88
|
+
prerender,
|
|
89
|
+
}: {
|
|
102
90
|
/** `url` to prefetch. */
|
|
103
91
|
url: string;
|
|
104
92
|
|
|
@@ -107,8 +95,6 @@ export class Prefetch extends Lifecycle(Trigger()) {
|
|
|
107
95
|
*/
|
|
108
96
|
prerender?: boolean;
|
|
109
97
|
}) {
|
|
110
|
-
const { url } = options;
|
|
111
|
-
|
|
112
98
|
// if not the current page and not already prefetched
|
|
113
99
|
if (!(url === window.location.href) && !this.#prefetchedUrls.has(url)) {
|
|
114
100
|
this.#prefetchedUrls.add(url);
|
|
@@ -124,7 +110,7 @@ export class Prefetch extends Lifecycle(Trigger()) {
|
|
|
124
110
|
prefetch: [{ source: "list", urls: [url] }],
|
|
125
111
|
};
|
|
126
112
|
|
|
127
|
-
if (
|
|
113
|
+
if (prerender) rules.prerender = rules.prefetch;
|
|
128
114
|
|
|
129
115
|
const script = document.createElement("script");
|
|
130
116
|
script.type = "speculationrules";
|
|
@@ -141,16 +127,17 @@ export class Prefetch extends Lifecycle(Trigger()) {
|
|
|
141
127
|
}
|
|
142
128
|
|
|
143
129
|
override mount() {
|
|
130
|
+
const prerender = this.hasAttribute("prerender");
|
|
131
|
+
const url = this.getAttribute("url");
|
|
132
|
+
|
|
144
133
|
// immediately prefetch the `url` attribute if it exists
|
|
145
|
-
if (this
|
|
146
|
-
this.prefetch({ url: this.#url, prerender: this.#prerender });
|
|
134
|
+
if (url) this.prefetch({ url, prerender });
|
|
147
135
|
|
|
148
136
|
// prefetch the `trigger` elements
|
|
149
137
|
const anchors = this.triggers(HTMLAnchorElement);
|
|
150
|
-
const
|
|
151
|
-
const strategy = this.#strategy;
|
|
138
|
+
const strategy = this.getAttribute("strategy");
|
|
152
139
|
|
|
153
|
-
let prefetchTimer:
|
|
140
|
+
let prefetchTimer: number;
|
|
154
141
|
|
|
155
142
|
const listener =
|
|
156
143
|
(delay = 200) =>
|
|
@@ -164,22 +151,20 @@ export class Prefetch extends Lifecycle(Trigger()) {
|
|
|
164
151
|
|
|
165
152
|
const reset = () => clearTimeout(prefetchTimer);
|
|
166
153
|
|
|
167
|
-
const observer = new IntersectionObserver((entries) => {
|
|
168
|
-
for (const entry of entries) {
|
|
169
|
-
if (entry.isIntersecting) {
|
|
170
|
-
this.prefetch({
|
|
171
|
-
url: (entry.target as HTMLAnchorElement).href,
|
|
172
|
-
prerender,
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
|
|
178
154
|
for (const anchor of anchors) {
|
|
179
155
|
if (strategy === "load") {
|
|
180
156
|
this.prefetch({ url: anchor.href, prerender });
|
|
181
157
|
} else if (strategy === "visible") {
|
|
182
|
-
|
|
158
|
+
new IntersectionObserver((entries) => {
|
|
159
|
+
for (const entry of entries) {
|
|
160
|
+
if (entry.isIntersecting) {
|
|
161
|
+
this.prefetch({
|
|
162
|
+
url: (entry.target as HTMLAnchorElement).href,
|
|
163
|
+
prerender,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}).observe(anchor);
|
|
183
168
|
} else {
|
|
184
169
|
// "hover" - default
|
|
185
170
|
anchor.addEventListener("mouseover", listener());
|
package/src/tablesort/index.ts
CHANGED
|
@@ -8,8 +8,7 @@ import {
|
|
|
8
8
|
} from "../base/index.js";
|
|
9
9
|
|
|
10
10
|
export interface TableSortAttributes
|
|
11
|
-
extends TriggerAttributes,
|
|
12
|
-
ContentAttributes {}
|
|
11
|
+
extends TriggerAttributes, ContentAttributes {}
|
|
13
12
|
|
|
14
13
|
export interface TableSortTriggerAttributes {
|
|
15
14
|
"data-type": "string" | "boolean" | "number";
|
|
@@ -78,7 +77,7 @@ export class TableSort extends Lifecycle(Trigger(Content(Announce()))) {
|
|
|
78
77
|
const asc = this.#setAttributes(trigger);
|
|
79
78
|
|
|
80
79
|
Array.from(tbody.querySelectorAll("tr"))
|
|
81
|
-
.sort(comparer(trigger, asc))
|
|
80
|
+
.sort(TableSort.#comparer(trigger, asc))
|
|
82
81
|
.forEach((tr) => tbody.appendChild(tr));
|
|
83
82
|
|
|
84
83
|
this.announce(
|
|
@@ -98,71 +97,73 @@ export class TableSort extends Lifecycle(Trigger(Content(Announce()))) {
|
|
|
98
97
|
}
|
|
99
98
|
}
|
|
100
99
|
}
|
|
101
|
-
}
|
|
102
100
|
|
|
103
|
-
// adapted from: https://stackoverflow.com/questions/14267781/sorting-html-table-with-javascript/49041392#49041392
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
101
|
+
// adapted from: https://stackoverflow.com/questions/14267781/sorting-html-table-with-javascript/49041392#49041392
|
|
102
|
+
static #comparer(th: HTMLElement, ascending: boolean) {
|
|
103
|
+
// this function is returned and used by `sort`
|
|
104
|
+
const sorter = (a: HTMLTableRowElement, b: HTMLTableRowElement) => {
|
|
105
|
+
// find the column to sort by using the index of the `th`
|
|
106
|
+
const columnIndex = Array.from(th.parentNode?.children ?? []).indexOf(th);
|
|
107
|
+
|
|
108
|
+
const compare = (aVal: string, bVal: string) => {
|
|
109
|
+
// default to `string` sorting
|
|
110
|
+
const dataType = (th.dataset.type ?? "string") as
|
|
111
|
+
| "string"
|
|
112
|
+
| "boolean"
|
|
113
|
+
| "number";
|
|
114
|
+
|
|
115
|
+
if (dataType === "string") {
|
|
116
|
+
const collator = new Intl.Collator();
|
|
117
|
+
return collator.compare(aVal, bVal);
|
|
118
|
+
} else if (dataType === "boolean") {
|
|
119
|
+
return TableSort.#falsyBoolean(aVal) === TableSort.#falsyBoolean(bVal)
|
|
120
|
+
? 0
|
|
121
|
+
: TableSort.#falsyBoolean(aVal)
|
|
122
|
+
? -1
|
|
123
|
+
: 1;
|
|
124
|
+
} else {
|
|
125
|
+
// "number"
|
|
126
|
+
return Number(aVal) - Number(bVal);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
return compare(
|
|
131
|
+
TableSort.#getValue(ascending ? a : b, columnIndex),
|
|
132
|
+
TableSort.#getValue(ascending ? b : a, columnIndex),
|
|
133
|
+
);
|
|
130
134
|
};
|
|
131
135
|
|
|
132
|
-
return
|
|
133
|
-
|
|
134
|
-
getValue(ascending ? b : a, columnIndex),
|
|
135
|
-
);
|
|
136
|
-
};
|
|
136
|
+
return sorter;
|
|
137
|
+
}
|
|
137
138
|
|
|
138
|
-
|
|
139
|
-
|
|
139
|
+
/**
|
|
140
|
+
* @param tr the row
|
|
141
|
+
* @param i index of the `td` to find
|
|
142
|
+
* @returns a string, the `data-value` attribute, or the `textContent`
|
|
143
|
+
*/
|
|
144
|
+
static #getValue(tr: HTMLTableRowElement, i: number) {
|
|
145
|
+
const cell = tr.children[i];
|
|
140
146
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
*/
|
|
146
|
-
const getValue = (tr: HTMLTableRowElement, i: number) => {
|
|
147
|
-
const cell = tr.children[i];
|
|
148
|
-
if (cell instanceof HTMLElement) {
|
|
149
|
-
// first look for `data-value` attribute, then use `textContent`
|
|
150
|
-
return cell.dataset.value ?? cell.textContent ?? "";
|
|
151
|
-
}
|
|
152
|
-
return "";
|
|
153
|
-
};
|
|
147
|
+
if (cell instanceof HTMLElement) {
|
|
148
|
+
// first look for `data-value` attribute, then use `textContent`
|
|
149
|
+
return cell.dataset.value ?? cell.textContent ?? "";
|
|
150
|
+
}
|
|
154
151
|
|
|
155
|
-
|
|
156
|
-
* if value is one of these and type is boolean
|
|
157
|
-
* it should be considered falsy
|
|
158
|
-
* since actually `Boolean("false") === true`
|
|
159
|
-
* @param val string pulled from the textContent or attr
|
|
160
|
-
* @returns a boolean of the provided string
|
|
161
|
-
*/
|
|
162
|
-
const falsyBoolean = (val: string) => {
|
|
163
|
-
if (["0", "false", "null", "undefined"].includes(val)) {
|
|
164
|
-
return false;
|
|
152
|
+
return "";
|
|
165
153
|
}
|
|
166
154
|
|
|
167
|
-
|
|
168
|
-
|
|
155
|
+
static #falsyStrings = new Set(["0", "false", "null", "undefined"]);
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* if value is one of these and type is boolean
|
|
159
|
+
* it should be considered falsy
|
|
160
|
+
* since actually `Boolean("false") === true`
|
|
161
|
+
* @param val string pulled from the textContent or attr
|
|
162
|
+
* @returns a boolean of the provided string
|
|
163
|
+
*/
|
|
164
|
+
static #falsyBoolean(val: string) {
|
|
165
|
+
if (TableSort.#falsyStrings.has(val)) return false;
|
|
166
|
+
|
|
167
|
+
return Boolean(val);
|
|
168
|
+
}
|
|
169
|
+
}
|
package/src/tabs/index.ts
CHANGED
|
@@ -35,7 +35,14 @@ export interface TabsAttributes extends TriggerAttributes {
|
|
|
35
35
|
*/
|
|
36
36
|
export class Tabs extends Lifecycle(Trigger()) {
|
|
37
37
|
/** Supported keys for keyboard navigation. */
|
|
38
|
-
#keys = [
|
|
38
|
+
readonly #keys = [
|
|
39
|
+
"ArrowRight",
|
|
40
|
+
"ArrowDown",
|
|
41
|
+
"ArrowLeft",
|
|
42
|
+
"ArrowUp",
|
|
43
|
+
"Home",
|
|
44
|
+
"End",
|
|
45
|
+
];
|
|
39
46
|
|
|
40
47
|
/** Currently selected tab. */
|
|
41
48
|
#selected: { tab?: HTMLAnchorElement; index: number } = { index: 0 };
|
|
@@ -74,6 +81,7 @@ export class Tabs extends Lifecycle(Trigger()) {
|
|
|
74
81
|
|
|
75
82
|
for (const tab of this.#tabs) {
|
|
76
83
|
const panel = this.querySelector(tab.hash);
|
|
84
|
+
|
|
77
85
|
if (!(panel instanceof HTMLElement))
|
|
78
86
|
throw new Error(`Tabs: No HTMLElement with ID of ${tab.hash} found.`);
|
|
79
87
|
|
|
@@ -86,13 +94,19 @@ export class Tabs extends Lifecycle(Trigger()) {
|
|
|
86
94
|
override mount() {
|
|
87
95
|
// create tablist
|
|
88
96
|
const [first, ...rest] = this.#tabs;
|
|
97
|
+
|
|
89
98
|
let common = this.#ancestors(first);
|
|
99
|
+
|
|
90
100
|
for (let i = 0; i < rest.length; i++) {
|
|
91
101
|
common = common.intersection(this.#ancestors(rest[i]));
|
|
92
102
|
}
|
|
103
|
+
|
|
93
104
|
const [tablist] = common;
|
|
94
|
-
|
|
105
|
+
|
|
106
|
+
if (!tablist) {
|
|
95
107
|
throw new Error("Tabs: No common parent element found for triggers.");
|
|
108
|
+
}
|
|
109
|
+
|
|
96
110
|
tablist.role = "tablist";
|
|
97
111
|
tablist.ariaOrientation = this.#orientation;
|
|
98
112
|
|
package/src/types/index.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { AnnouncerAttributes } from "../announcer/index.js";
|
|
2
2
|
import type { ContextMenuAttributes } from "../contextmenu/index.js";
|
|
3
|
-
import type { DialogAttributes } from "../dialog/index.js";
|
|
4
3
|
import type { EditorAttributes } from "../editor/index.js";
|
|
5
4
|
import type { FullscreenAttributes } from "../fullscreen/index.js";
|
|
6
5
|
import type { IntersectAttributes } from "../intersect/index.js";
|
|
@@ -13,7 +12,6 @@ import type { WakeLockAttributes } from "../wakelock/index.js";
|
|
|
13
12
|
export interface Attributes {
|
|
14
13
|
announcer: AnnouncerAttributes;
|
|
15
14
|
contextmenu: ContextMenuAttributes;
|
|
16
|
-
dialog: DialogAttributes;
|
|
17
15
|
editor: EditorAttributes;
|
|
18
16
|
fullscreen: FullscreenAttributes;
|
|
19
17
|
intersect: IntersectAttributes;
|
package/src/util/validate.ts
CHANGED
|
@@ -9,8 +9,9 @@ export const validate = <T extends HTMLElement>(
|
|
|
9
9
|
actual: unknown,
|
|
10
10
|
expected: Constructor<T>,
|
|
11
11
|
) => {
|
|
12
|
-
if (!(actual instanceof expected))
|
|
12
|
+
if (!(actual instanceof expected)) {
|
|
13
13
|
throw new TypeError(`${actual} is not an instance of ${expected.name}.`);
|
|
14
|
+
}
|
|
14
15
|
|
|
15
16
|
return actual;
|
|
16
17
|
};
|
package/src/wakelock/index.ts
CHANGED
|
@@ -8,8 +8,7 @@ import {
|
|
|
8
8
|
} from "../base/index.js";
|
|
9
9
|
|
|
10
10
|
export interface WakeLockAttributes
|
|
11
|
-
extends TriggerAttributes,
|
|
12
|
-
ContentAttributes {
|
|
11
|
+
extends TriggerAttributes, ContentAttributes {
|
|
13
12
|
/** Auto request wakelock when user returns to inactive tab. */
|
|
14
13
|
"auto-lock"?: boolean;
|
|
15
14
|
|
|
@@ -118,9 +117,7 @@ export class WakeLock extends Lifecycle(Trigger(Content(Announce()))) {
|
|
|
118
117
|
// When the tab is not visible, the wakeLock is automatically released.
|
|
119
118
|
// This requests it back if it exists, if it is `null`, that
|
|
120
119
|
// means it was removed. In which case, it shouldn't be requested again.
|
|
121
|
-
if (this.#wakeLock)
|
|
122
|
-
this.request();
|
|
123
|
-
}
|
|
120
|
+
if (this.#wakeLock) this.request();
|
|
124
121
|
},
|
|
125
122
|
document,
|
|
126
123
|
);
|
package/dist/dialog/define.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../../src/dialog/define.ts"],"names":[],"mappings":""}
|
package/dist/dialog/define.js
DELETED