@ax-design/reveal-highlight 0.4.2 → 0.5.3
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/LICENSE +21 -21
- package/README.md +75 -75
- package/build/BaseConfig.d.ts +5 -1
- package/build/BaseConfig.d.ts.map +1 -1
- package/build/CanvasConfig.d.ts +7 -1
- package/build/CanvasConfig.d.ts.map +1 -1
- package/build/ComputedStyleStorage.d.ts.map +1 -1
- package/build/CustomElements.d.ts +20 -4
- package/build/CustomElements.d.ts.map +1 -1
- package/build/RevealBoundryStore.d.ts +4 -0
- package/build/RevealBoundryStore.d.ts.map +1 -1
- package/build/RevealStateManager.d.ts +5 -1
- package/build/RevealStateManager.d.ts.map +1 -1
- package/build/main.js +113 -82
- package/build/utils/types.d.ts +2 -10
- package/build/utils/types.d.ts.map +1 -1
- package/es/BaseConfig.d.ts +46 -42
- package/es/BaseConfig.d.ts.map +1 -1
- package/es/BaseConfig.js +241 -219
- package/es/BaseConfig.js.map +1 -1
- package/es/CanvasConfig.d.ts +21 -15
- package/es/CanvasConfig.d.ts.map +1 -1
- package/es/CanvasConfig.js +332 -320
- package/es/CanvasConfig.js.map +1 -1
- package/es/ComputedStyleStorage.d.ts +8 -8
- package/es/ComputedStyleStorage.d.ts.map +1 -1
- package/es/ComputedStyleStorage.js +68 -58
- package/es/ComputedStyleStorage.js.map +1 -1
- package/es/CustomElements.d.ts +75 -59
- package/es/CustomElements.d.ts.map +1 -1
- package/es/CustomElements.js +296 -233
- package/es/CustomElements.js.map +1 -1
- package/es/Profiler.d.ts +12 -12
- package/es/Profiler.js +31 -31
- package/es/RevealBoundryStore.d.ts +80 -76
- package/es/RevealBoundryStore.d.ts.map +1 -1
- package/es/RevealBoundryStore.js +269 -248
- package/es/RevealBoundryStore.js.map +1 -1
- package/es/RevealStateManager.d.ts +19 -15
- package/es/RevealStateManager.d.ts.map +1 -1
- package/es/RevealStateManager.js +99 -73
- package/es/RevealStateManager.js.map +1 -1
- package/es/SvgConfig.d.ts +16 -16
- package/es/SvgConfig.js +345 -345
- package/es/config.d.ts +4 -4
- package/es/config.js +21 -21
- package/es/index.d.ts +5 -5
- package/es/index.js +205 -205
- package/es/tsconfig.tsbuildinfo +1 -1
- package/es/utils/extractRGBValue.d.ts +1 -1
- package/es/utils/extractRGBValue.js +47 -47
- package/es/utils/isValidateBorderDecorationType.d.ts +2 -2
- package/es/utils/isValidateBorderDecorationType.js +9 -9
- package/es/utils/types.d.ts +94 -102
- package/es/utils/types.d.ts.map +1 -1
- package/es/utils/types.js +1 -1
- package/es/variables.d.ts +1 -1
- package/es/variables.js +1 -1
- package/package.json +35 -34
- package/src/BaseConfig.ts +332 -310
- package/src/CanvasConfig.ts +420 -415
- package/src/ComputedStyleStorage.ts +102 -89
- package/src/CustomElements.ts +344 -272
- package/src/Profiler.ts +44 -44
- package/src/RevealBoundryStore.ts +315 -291
- package/src/RevealStateManager.ts +109 -86
- package/src/SvgConfig.ts +422 -422
- package/src/config.ts +26 -26
- package/src/cssTypedOM.d.ts +52 -52
- package/src/index.ts +219 -219
- package/src/utils/extractRGBValue.ts +58 -58
- package/src/utils/isValidateBorderDecorationType.ts +8 -8
- package/src/utils/types.ts +97 -105
- package/src/variables.ts +1 -1
package/src/CustomElements.ts
CHANGED
|
@@ -1,272 +1,344 @@
|
|
|
1
|
-
import { RevealStateManager } from './RevealStateManager.js';
|
|
2
|
-
import { RevealBoundaryStore } from './RevealBoundryStore.js';
|
|
3
|
-
import { config } from './config.js';
|
|
4
|
-
|
|
5
|
-
function closest(dom: Element, selector: string): Element | null {
|
|
6
|
-
const r = dom.closest(selector);
|
|
7
|
-
if (r) return r;
|
|
8
|
-
const host = findParentShadowRoot(dom)?.host;
|
|
9
|
-
if (!host) return null;
|
|
10
|
-
return closest(host, selector)
|
|
11
|
-
}
|
|
12
|
-
function findParentShadowRoot(x: Node | undefined | null): ShadowRoot | null {
|
|
13
|
-
if (!x) return null;
|
|
14
|
-
if (x.parentNode && x.parentNode.nodeType === document.DOCUMENT_FRAGMENT_NODE) return x.parentNode as ShadowRoot;
|
|
15
|
-
return findParentShadowRoot(x.parentNode);
|
|
16
|
-
}
|
|
17
|
-
class ServerSideHTMLElement {
|
|
18
|
-
root = {
|
|
19
|
-
innerHTML: '',
|
|
20
|
-
querySelector: (_x: string) => null,
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
attachShadow = () => null;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const PatchedHTMLElement =
|
|
27
|
-
typeof globalThis.Window === 'undefined' ? ((ServerSideHTMLElement as unknown) as typeof HTMLElement) : HTMLElement;
|
|
28
|
-
|
|
29
|
-
export class AxRevealProvider extends PatchedHTMLElement {
|
|
30
|
-
static readonly ElementName = 'ax-reveal-provider';
|
|
31
|
-
readonly stateManager = new RevealStateManager();
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export class AxRevealBoundary extends PatchedHTMLElement {
|
|
35
|
-
static readonly ElementName = 'ax-reveal-bound';
|
|
36
|
-
|
|
37
|
-
static readonly removeStorageEvent = 'removeStorage';
|
|
38
|
-
static readonly attachStorageEvent = 'attachStorage';
|
|
39
|
-
static readonly replaceStorageEvent = 'replaceStorage';
|
|
40
|
-
|
|
41
|
-
private root = this.attachShadow({ mode: 'open' });
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
private
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
this.
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (
|
|
75
|
-
this.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
this.
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
this.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
this.
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
:
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
1
|
+
import { RevealStateManager } from './RevealStateManager.js';
|
|
2
|
+
import { RevealBoundaryStore } from './RevealBoundryStore.js';
|
|
3
|
+
import { config } from './config.js';
|
|
4
|
+
|
|
5
|
+
function closest(dom: Element, selector: string): Element | null {
|
|
6
|
+
const r = dom.closest(selector);
|
|
7
|
+
if (r) return r;
|
|
8
|
+
const host = findParentShadowRoot(dom)?.host;
|
|
9
|
+
if (!host) return null;
|
|
10
|
+
return closest(host, selector)
|
|
11
|
+
}
|
|
12
|
+
function findParentShadowRoot(x: Node | undefined | null): ShadowRoot | null {
|
|
13
|
+
if (!x) return null;
|
|
14
|
+
if (x.parentNode && x.parentNode.nodeType === document.DOCUMENT_FRAGMENT_NODE) return x.parentNode as ShadowRoot;
|
|
15
|
+
return findParentShadowRoot(x.parentNode);
|
|
16
|
+
}
|
|
17
|
+
class ServerSideHTMLElement {
|
|
18
|
+
root = {
|
|
19
|
+
innerHTML: '',
|
|
20
|
+
querySelector: (_x: string) => null,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
attachShadow = () => null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const PatchedHTMLElement =
|
|
27
|
+
typeof globalThis.Window === 'undefined' ? ((ServerSideHTMLElement as unknown) as typeof HTMLElement) : HTMLElement;
|
|
28
|
+
|
|
29
|
+
export class AxRevealProvider extends PatchedHTMLElement {
|
|
30
|
+
static readonly ElementName = 'ax-reveal-provider';
|
|
31
|
+
readonly stateManager = new RevealStateManager();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export class AxRevealBoundary extends PatchedHTMLElement {
|
|
35
|
+
static readonly ElementName = 'ax-reveal-bound';
|
|
36
|
+
|
|
37
|
+
static readonly removeStorageEvent = 'removeStorage';
|
|
38
|
+
static readonly attachStorageEvent = 'attachStorage';
|
|
39
|
+
static readonly replaceStorageEvent = 'replaceStorage';
|
|
40
|
+
|
|
41
|
+
private root = this.attachShadow({ mode: 'open' });
|
|
42
|
+
|
|
43
|
+
// Created lazily, the border detection mode is not configured until `register` is called.
|
|
44
|
+
private static _stateManager: RevealStateManager | undefined;
|
|
45
|
+
|
|
46
|
+
static get stateManager() {
|
|
47
|
+
if (!AxRevealBoundary._stateManager) AxRevealBoundary._stateManager = new RevealStateManager();
|
|
48
|
+
return AxRevealBoundary._stateManager;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private _storage!: RevealBoundaryStore | undefined;
|
|
52
|
+
|
|
53
|
+
// The state manager that owns current storage, a provider's or the default one.
|
|
54
|
+
private ownerStateManager: RevealStateManager | undefined;
|
|
55
|
+
|
|
56
|
+
private get storage() {
|
|
57
|
+
return this._storage;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
private set storage(newStorage) {
|
|
61
|
+
const oldStorage = this._storage;
|
|
62
|
+
|
|
63
|
+
if (oldStorage) {
|
|
64
|
+
this.dispatchEvent(new CustomEvent(AxRevealBoundary.removeStorageEvent, { detail: oldStorage }));
|
|
65
|
+
this.ownerStateManager?.removeBoundary(oldStorage);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
this._storage = newStorage;
|
|
69
|
+
|
|
70
|
+
if (newStorage) {
|
|
71
|
+
this.dispatchEvent(new CustomEvent(AxRevealBoundary.attachStorageEvent, { detail: newStorage }));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (oldStorage && newStorage) {
|
|
75
|
+
this.dispatchEvent(
|
|
76
|
+
new CustomEvent(AxRevealBoundary.replaceStorageEvent, {
|
|
77
|
+
detail: { old: oldStorage, new: newStorage },
|
|
78
|
+
})
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public waitForStorage(f: (storage: RevealBoundaryStore) => void) {
|
|
84
|
+
if (this.storage === undefined) {
|
|
85
|
+
this.addEventListener(AxRevealBoundary.attachStorageEvent, () => f(this.storage!), { once: true });
|
|
86
|
+
} else {
|
|
87
|
+
f(this.storage);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private appendStorage(force = false) {
|
|
92
|
+
if (!force && this.storage) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const parent = closest(this, AxRevealProvider.ElementName) as AxRevealProvider;
|
|
97
|
+
const stateManager = parent ? parent.stateManager : AxRevealBoundary.stateManager;
|
|
98
|
+
|
|
99
|
+
this.storage = stateManager.newBoundary(this);
|
|
100
|
+
this.ownerStateManager = stateManager;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Update the position of your pointer.
|
|
105
|
+
* @param ev Pointer event or touch point from the listener.
|
|
106
|
+
*/
|
|
107
|
+
updatePointerPosition = (ev: { clientX: number; clientY: number }) => {
|
|
108
|
+
this.waitForStorage((storage) => {
|
|
109
|
+
storage.clientX = ev.clientX;
|
|
110
|
+
storage.clientY = ev.clientY;
|
|
111
|
+
});
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// Once the browser starts scrolling, pointer events stop (`pointercancel`)
|
|
115
|
+
// but touch events keep coming, so we follow the finger with them instead.
|
|
116
|
+
private touchScrolling = false;
|
|
117
|
+
|
|
118
|
+
handlePointerEnter = () => this.waitForStorage((storage) => storage.onPointerEnterBoundary());
|
|
119
|
+
handlePointerLeave = () => {
|
|
120
|
+
if (this.touchScrolling) return;
|
|
121
|
+
this.waitForStorage((storage) => storage.onPointerLeaveBoundary());
|
|
122
|
+
};
|
|
123
|
+
handlePointerMove = this.updatePointerPosition;
|
|
124
|
+
handlePointerUp = (ev: PointerEvent) => {
|
|
125
|
+
if (ev.pointerType === 'mouse') {
|
|
126
|
+
this.waitForStorage((storage) => storage.switchAnimation());
|
|
127
|
+
} else {
|
|
128
|
+
this.waitForStorage((storage) => storage.clearAll(false));
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
// Fired when the browser takes over the touch for scrolling or zooming,
|
|
132
|
+
// `pointerup` will never come, so the pressed ripple must be cleaned here.
|
|
133
|
+
handlePointerCancel = (ev: PointerEvent) => {
|
|
134
|
+
this.waitForStorage((storage) => {
|
|
135
|
+
if (ev.pointerType === 'touch') {
|
|
136
|
+
this.touchScrolling = true;
|
|
137
|
+
storage.anchorPointer();
|
|
138
|
+
}
|
|
139
|
+
storage.clearAll(false);
|
|
140
|
+
});
|
|
141
|
+
};
|
|
142
|
+
handleTouchMove = (ev: TouchEvent) => {
|
|
143
|
+
if (!this.touchScrolling || !ev.targetTouches.length) return;
|
|
144
|
+
this.updatePointerPosition(ev.targetTouches[0]);
|
|
145
|
+
this.waitForStorage((storage) => storage.anchorPointer());
|
|
146
|
+
};
|
|
147
|
+
handleTouchEnd = (ev: TouchEvent) => {
|
|
148
|
+
if (!this.touchScrolling || ev.targetTouches.length) return;
|
|
149
|
+
this.touchScrolling = false;
|
|
150
|
+
this.handlePointerLeave();
|
|
151
|
+
};
|
|
152
|
+
handlePointerDown = (ev: PointerEvent) =>
|
|
153
|
+
this.waitForStorage((storage) => {
|
|
154
|
+
this.updatePointerPosition(ev);
|
|
155
|
+
storage.initializeAnimation();
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
connectedCallback() {
|
|
159
|
+
this.appendStorage(true);
|
|
160
|
+
if (config.borderDetectionMode === 'strictEdge') {
|
|
161
|
+
this.addEventListener('pointerenter', this.handlePointerEnter);
|
|
162
|
+
this.addEventListener('pointerleave', this.handlePointerLeave);
|
|
163
|
+
this.addEventListener('pointermove', this.handlePointerMove);
|
|
164
|
+
}
|
|
165
|
+
this.addEventListener('pointerdown', this.handlePointerDown);
|
|
166
|
+
this.addEventListener('pointerup', this.handlePointerUp);
|
|
167
|
+
this.addEventListener('pointercancel', this.handlePointerCancel);
|
|
168
|
+
if (config.borderDetectionMode === 'strictEdge') {
|
|
169
|
+
this.addEventListener('touchmove', this.handleTouchMove, { passive: true });
|
|
170
|
+
this.addEventListener('touchend', this.handleTouchEnd, { passive: true });
|
|
171
|
+
this.addEventListener('touchcancel', this.handleTouchEnd, { passive: true });
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
disconnectedCallback() {
|
|
176
|
+
this.storage = undefined;
|
|
177
|
+
this.ownerStateManager = undefined;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
constructor() {
|
|
181
|
+
super();
|
|
182
|
+
this.root.innerHTML = `
|
|
183
|
+
<div>
|
|
184
|
+
<slot></slot>
|
|
185
|
+
</div>`;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export class AxReveal extends PatchedHTMLElement {
|
|
190
|
+
static readonly ElementName = 'ax-reveal';
|
|
191
|
+
private root = this.attachShadow({ mode: 'open' });
|
|
192
|
+
private canvas: HTMLCanvasElement;
|
|
193
|
+
private boundary!: AxRevealBoundary;
|
|
194
|
+
// The storage this element was added to, the boundary may have dropped it already.
|
|
195
|
+
private storage: RevealBoundaryStore | undefined;
|
|
196
|
+
private connection = 0;
|
|
197
|
+
|
|
198
|
+
adoptedCallback() {
|
|
199
|
+
this.disconnectedCallback();
|
|
200
|
+
this.connectedCallback();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
handlePointerDown = (ev: PointerEvent) => {
|
|
204
|
+
this.setPointerCapture(ev.pointerId);
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
disconnectedCallback() {
|
|
208
|
+
this.connection++;
|
|
209
|
+
this.storage && this.storage.removeReveal(this.canvas);
|
|
210
|
+
this.storage = undefined;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
connectedCallback() {
|
|
214
|
+
this.boundary = closest(this, AxRevealBoundary.ElementName) as AxRevealBoundary;
|
|
215
|
+
if (!this.boundary)
|
|
216
|
+
throw new SyntaxError(
|
|
217
|
+
'You must use ' + AxRevealBoundary.ElementName + ' as the boundary of reveal highlight!'
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
const connection = ++this.connection;
|
|
221
|
+
this.boundary.waitForStorage((storage) =>
|
|
222
|
+
setTimeout(() => {
|
|
223
|
+
// Disconnected or reconnected before the timer fired.
|
|
224
|
+
if (connection !== this.connection) return;
|
|
225
|
+
this.storage = storage;
|
|
226
|
+
storage.addReveal(this.canvas, this);
|
|
227
|
+
}, 0)
|
|
228
|
+
);
|
|
229
|
+
this.addEventListener('pointerdown', this.handlePointerDown);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
constructor() {
|
|
233
|
+
super();
|
|
234
|
+
this.root.innerHTML = `
|
|
235
|
+
<div class="ax-reveal">
|
|
236
|
+
<canvas></canvas>
|
|
237
|
+
<div class="content"><slot></slot></div>
|
|
238
|
+
</div>
|
|
239
|
+
<style>
|
|
240
|
+
.ax-reveal { display: content; }
|
|
241
|
+
.ax-reveal * { user-drag: none; -webkit-user-drag: none; touch-action: var(--reveal-touch-action, manipulation); user-select: none; }
|
|
242
|
+
.content { position: relative; }
|
|
243
|
+
canvas { top: 0; left: 0; pointer-events: none; width: 100%; height: 100%; position: absolute; }
|
|
244
|
+
:host { display: inline-block; position: relative; }
|
|
245
|
+
:host([block]) { display: block; }
|
|
246
|
+
:host([inline-block]) { display: inline-block; }
|
|
247
|
+
:host([flex]) { display: flex; }
|
|
248
|
+
:host([inline-flex]) { display: inline-flex; }
|
|
249
|
+
:host([grid]) { display: grid; }
|
|
250
|
+
:host([inline-grid]) { display: inline-grid; }
|
|
251
|
+
::slotted(*) { user-drag: none; -webkit-user-drag: none; touch-action: var(--reveal-touch-action, manipulation); user-select: none; }
|
|
252
|
+
::slotted(button) { outline:none; }
|
|
253
|
+
</style>`;
|
|
254
|
+
this.canvas = this.root.querySelector('canvas')!;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export class AxRevealNg extends PatchedHTMLElement {
|
|
259
|
+
static readonly ElementName = 'ax-reveal-ng';
|
|
260
|
+
private root = this.attachShadow({ mode: 'open' });
|
|
261
|
+
private svg: SVGElement;
|
|
262
|
+
private boundary!: AxRevealBoundary;
|
|
263
|
+
// The storage this element was added to, the boundary may have dropped it already.
|
|
264
|
+
private storage: RevealBoundaryStore | undefined;
|
|
265
|
+
private connection = 0;
|
|
266
|
+
|
|
267
|
+
adoptedCallback() {
|
|
268
|
+
this.disconnectedCallback();
|
|
269
|
+
this.connectedCallback();
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
handlePointerDown = (ev: PointerEvent) => {
|
|
273
|
+
this.setPointerCapture(ev.pointerId);
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
disconnectedCallback() {
|
|
277
|
+
this.connection++;
|
|
278
|
+
this.storage && this.storage.removeReveal(this.svg);
|
|
279
|
+
this.storage = undefined;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
connectedCallback() {
|
|
283
|
+
this.boundary = closest(this, AxRevealBoundary.ElementName) as AxRevealBoundary;
|
|
284
|
+
if (!this.boundary)
|
|
285
|
+
throw new SyntaxError(
|
|
286
|
+
'You must use ' + AxRevealBoundary.ElementName + ' as the boundary of reveal highlight!'
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
const connection = ++this.connection;
|
|
290
|
+
this.boundary.waitForStorage((storage) =>
|
|
291
|
+
setTimeout(() => {
|
|
292
|
+
// Disconnected or reconnected before the timer fired.
|
|
293
|
+
if (connection !== this.connection) return;
|
|
294
|
+
this.storage = storage;
|
|
295
|
+
storage.addReveal(this.svg, this);
|
|
296
|
+
}, 0)
|
|
297
|
+
);
|
|
298
|
+
this.addEventListener('pointerdown', this.handlePointerDown);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
constructor() {
|
|
302
|
+
super();
|
|
303
|
+
this.root.innerHTML = `
|
|
304
|
+
<div class="ax-reveal">
|
|
305
|
+
<svg>
|
|
306
|
+
<defs>
|
|
307
|
+
<radialGradient id="borderGrad" gradientUnits="userSpaceOnUse" r="10">
|
|
308
|
+
<stop id="borderCenter" offset="0%" />
|
|
309
|
+
<stop id="borderOut" offset="100%" />
|
|
310
|
+
</radialGradient>
|
|
311
|
+
<radialGradient id="fillGrad" gradientUnits="userSpaceOnUse" r="10">
|
|
312
|
+
<stop id="fillCenter" offset="0%" />
|
|
313
|
+
<stop id="fillOut" offset="100%" />
|
|
314
|
+
</radialGradient>
|
|
315
|
+
<radialGradient id="rippleGrad" gradientUnits="userSpaceOnUse" r="10">
|
|
316
|
+
<stop id="rippleCenter" offset="0%" />
|
|
317
|
+
<stop id="rippleMiddle" offset="0%" />
|
|
318
|
+
<stop id="rippleOut" offset="0%" />
|
|
319
|
+
</radialGradient>
|
|
320
|
+
</defs>
|
|
321
|
+
<path id="borderPath" fill="url(#borderGrad)" />
|
|
322
|
+
<path id="fillPath" fill="url(#fillGrad)" />
|
|
323
|
+
<path id="ripplePath" fill="url(#rippleGrad)" />
|
|
324
|
+
</svg>
|
|
325
|
+
<div class="content"><slot></slot></div>
|
|
326
|
+
</div>
|
|
327
|
+
<style>
|
|
328
|
+
.ax-reveal { display: contents; }
|
|
329
|
+
.ax-reveal * { user-drag: none; -webkit-user-drag: none; touch-action: var(--reveal-touch-action, manipulation); user-select: none; }
|
|
330
|
+
.content { position: relative; }
|
|
331
|
+
svg { top: 0; left: 0; pointer-events: none; width: 100%; height: 100%; position: absolute; }
|
|
332
|
+
:host { display: inline-block; position: relative; }
|
|
333
|
+
:host([block]) { display: block; }
|
|
334
|
+
:host([inline-block]) { display: inline-block; }
|
|
335
|
+
:host([flex]) { display: flex; }
|
|
336
|
+
:host([inline-flex]) { display: inline-flex; }
|
|
337
|
+
:host([grid]) { display: grid; }
|
|
338
|
+
:host([inline-grid]) { display: inline-grid; }
|
|
339
|
+
::slotted(*) { user-drag: none; -webkit-user-drag: none; touch-action: var(--reveal-touch-action, manipulation); user-select: none; }
|
|
340
|
+
::slotted(button) { outline:none; }
|
|
341
|
+
</style>`;
|
|
342
|
+
this.svg = this.root.querySelector('svg')!;
|
|
343
|
+
}
|
|
344
|
+
}
|