snail.view 1.0.1 → 1.0.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/dist/snail.view.d.ts +14 -6
- package/dist/snail.view.js +65 -3
- package/dist/snail.view.umd.js +355 -0
- package/package.json +1 -1
package/dist/snail.view.d.ts
CHANGED
|
@@ -203,6 +203,19 @@ type ElementSize = {
|
|
|
203
203
|
height: number;
|
|
204
204
|
};
|
|
205
205
|
|
|
206
|
+
/**
|
|
207
|
+
* 视图观察者
|
|
208
|
+
* 1、观察元素尺寸、位置变化
|
|
209
|
+
* 注意事项:
|
|
210
|
+
* 1、不提供全局【观察者】对象;这个涉到不少子scope的销毁,在全局挂着始终不好
|
|
211
|
+
*/
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* 使用【观察者】
|
|
215
|
+
* @returns 全新的【观察者】+作用域
|
|
216
|
+
*/
|
|
217
|
+
declare function useObserver(): IObserver & IScope;
|
|
218
|
+
|
|
206
219
|
/**
|
|
207
220
|
* css样式数据结构
|
|
208
221
|
* 1、高度、宽度、边框、内外边距样式
|
|
@@ -418,15 +431,10 @@ type TransitionStyle = {
|
|
|
418
431
|
* 2、【后续支持】构建style标签,并生成css样式插入到页面
|
|
419
432
|
*/
|
|
420
433
|
|
|
421
|
-
/**
|
|
422
|
-
* 使用【样式管理器】
|
|
423
|
-
* @returns 全新的【样式管理器】
|
|
424
|
-
*/
|
|
425
|
-
declare function useStyle(): IStyleManager;
|
|
426
434
|
/**
|
|
427
435
|
* 全局的【样式管理器】
|
|
428
436
|
*/
|
|
429
437
|
declare const style: IStyleManager;
|
|
430
438
|
|
|
431
|
-
export { configLink, link, linkMap, style, useAnimation, useLink,
|
|
439
|
+
export { configLink, link, linkMap, style, useAnimation, useLink, useObserver };
|
|
432
440
|
export type { AlignStyle, AllStyle, BorderStyle, ElementSize, IAnimationManager, ILinkManager, IObserver, IStyleManager, LinkElement, LinkFile, LinkOptions, MarginStyle, PaddingStyle, SizeOptions, SizeStyle, TransitionEffectOptions, TransitionStyle };
|
package/dist/snail.view.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//@ sourceURL=/snail.view.js
|
|
2
|
-
import { throwIfFalse, checkScope, throwIfNullOrUndefined, throwIfTrue, useScope, useScopes, mountScope, extract, hasOwnProperty, tidyString, event, mustString, isArrayNotEmpty, isStringNotEmpty, version } from 'snail.core';
|
|
2
|
+
import { throwIfFalse, checkScope, throwIfNullOrUndefined, throwIfTrue, useScope, useScopes, mountScope, extract, hasOwnProperty, tidyString, event, mustString, isArrayNotEmpty, isStringNotEmpty, version, run, mustFunction } from 'snail.core';
|
|
3
3
|
|
|
4
4
|
function buildAlign(style, align, isFlex) {
|
|
5
5
|
if (isFlex == true) {
|
|
@@ -237,7 +237,7 @@ function useLink(options) {
|
|
|
237
237
|
if (!linkEle.element) {
|
|
238
238
|
linkEle.element = document.createElement("link");
|
|
239
239
|
linkEle.element.href = (options.version || LINK_CONFIG.version || version).formart(linkEle.file);
|
|
240
|
-
linkEle.element.rel = "
|
|
240
|
+
linkEle.element.rel = "stylesheet";
|
|
241
241
|
linkEle.element.disabled = true;
|
|
242
242
|
link2.theme && linkEle.element.setAttribute("data-theme", link2.theme);
|
|
243
243
|
const container = options.container || LINK_CONFIG.container || getLinkDefaultContainer();
|
|
@@ -278,4 +278,66 @@ function configLink(options) {
|
|
|
278
278
|
return link;
|
|
279
279
|
}
|
|
280
280
|
|
|
281
|
-
|
|
281
|
+
function useObserver() {
|
|
282
|
+
const scopes = useScopes();
|
|
283
|
+
function onEvent(target, name, fn) {
|
|
284
|
+
checkScope(manager, "onEvent: observer destroyed.");
|
|
285
|
+
throwIfFalse(target instanceof Element || target === window, "onEvent: target must be a Element or Window");
|
|
286
|
+
mustString(name, "onEvent: name");
|
|
287
|
+
mustFunction(fn, "onEvent: fn");
|
|
288
|
+
target.addEventListener(name, fn);
|
|
289
|
+
return scopes.get().onDestroy(() => target.removeEventListener(name, fn));
|
|
290
|
+
}
|
|
291
|
+
function onSize(el, fn) {
|
|
292
|
+
checkScope(manager, "onSize: observer destroyed.");
|
|
293
|
+
throwIfFalse(el instanceof Element, "onSize: el must be a Element.");
|
|
294
|
+
const scope = scopes.get();
|
|
295
|
+
var preSize = void 0;
|
|
296
|
+
function calcSize() {
|
|
297
|
+
if (scope.destroyed == false) {
|
|
298
|
+
const rect = el.getBoundingClientRect();
|
|
299
|
+
const isChange = preSize == void 0 || preSize.width != rect.width || preSize.height != rect.height;
|
|
300
|
+
if (isChange == true) {
|
|
301
|
+
preSize = Object.freeze({
|
|
302
|
+
width: rect.width,
|
|
303
|
+
height: rect.height
|
|
304
|
+
});
|
|
305
|
+
run(fn, preSize);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
const resizeObserver = "ResizeObserver" in window ? new ResizeObserver(calcSize) : void 0;
|
|
310
|
+
const timer = resizeObserver ? resizeObserver.observe(el) : setInterval(calcSize, 100);
|
|
311
|
+
setTimeout(calcSize);
|
|
312
|
+
return scope.onDestroy(() => {
|
|
313
|
+
resizeObserver && resizeObserver.disconnect();
|
|
314
|
+
timer && clearInterval(timer);
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
function onClient(el, fn) {
|
|
318
|
+
checkScope(manager, "onClient: observer destroyed.");
|
|
319
|
+
throwIfFalse(el instanceof Element, "onClient: el must be a Element.");
|
|
320
|
+
const scope = scopes.get();
|
|
321
|
+
var preRect = void 0;
|
|
322
|
+
const timer = setInterval(function () {
|
|
323
|
+
if (scope.destroyed == false) {
|
|
324
|
+
const rect = el.getBoundingClientRect();
|
|
325
|
+
const isChange = preRect == void 0 || rect.x != preRect.x || rect.y != preRect.y || rect.width != preRect.width || rect.height != preRect.height;
|
|
326
|
+
if (isChange == true) {
|
|
327
|
+
preRect = DOMRectReadOnly.fromRect(rect);
|
|
328
|
+
run(fn, preRect);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}, 100);
|
|
332
|
+
return scope.onDestroy(() => clearInterval(timer));
|
|
333
|
+
}
|
|
334
|
+
const manager = mountScope({
|
|
335
|
+
onEvent,
|
|
336
|
+
onSize,
|
|
337
|
+
onClient
|
|
338
|
+
});
|
|
339
|
+
manager.onDestroy(scopes.destroy);
|
|
340
|
+
return Object.freeze(manager);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export { configLink, link, linkMap, style, useAnimation, useLink, useObserver };
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
//@ sourceURL=/snail.view.js
|
|
2
|
+
(function (global, factory) {
|
|
3
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('snail.core')) :
|
|
4
|
+
typeof define === 'function' && define.amd ? define(['exports', 'snail.core'], factory) :
|
|
5
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.SnailView = global.SnailView || {}, global.Snail));
|
|
6
|
+
})(this, (function (exports, snail_core) { 'use strict';
|
|
7
|
+
|
|
8
|
+
function buildAlign(style, align, isFlex) {
|
|
9
|
+
if (isFlex == true) {
|
|
10
|
+
const map = {
|
|
11
|
+
"left": "start",
|
|
12
|
+
"center": "center",
|
|
13
|
+
"right": "end",
|
|
14
|
+
"top": "start",
|
|
15
|
+
"middle": "center",
|
|
16
|
+
"bottom": "end"
|
|
17
|
+
};
|
|
18
|
+
const aV = map[align.align],
|
|
19
|
+
vaV = map[align.valign];
|
|
20
|
+
aV && (style.justifyContent = aV);
|
|
21
|
+
vaV && (style.alignItems = vaV);
|
|
22
|
+
} else {
|
|
23
|
+
align.align && (style.textAlign = align.align);
|
|
24
|
+
align.valign && (style.verticalAlign = align.valign);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function buildSize(style, size, styleName, isFlex) {
|
|
28
|
+
if (size) {
|
|
29
|
+
var fixed = size.size;
|
|
30
|
+
if (isFlex && size.flex != void 0) {
|
|
31
|
+
fixed = void 0;
|
|
32
|
+
style.flex = String(size.flex);
|
|
33
|
+
}
|
|
34
|
+
if (fixed != void 0) {
|
|
35
|
+
style[styleName] = fixed;
|
|
36
|
+
} else {
|
|
37
|
+
size.min != void 0 && (style[`min-${styleName}`] = size.min);
|
|
38
|
+
size.max != void 0 && (style[`max-${styleName}`] = size.max);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function buildMargin(style, margin) {
|
|
43
|
+
if (margin) {
|
|
44
|
+
margin.margin && (style.margin = margin.margin);
|
|
45
|
+
margin.marginTop && (style.marginTop = margin.marginTop);
|
|
46
|
+
margin.marginRight && (style.marginRight = margin.marginRight);
|
|
47
|
+
margin.marginBottom && (style.marginBottom = margin.marginBottom);
|
|
48
|
+
margin.marginLeft && (style.marginLeft = margin.marginLeft);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function buildBorder(style, border) {
|
|
52
|
+
if (border) {
|
|
53
|
+
border.borderRadius && (style.borderRadius = border.borderRadius);
|
|
54
|
+
border.border && (style.border = border.border);
|
|
55
|
+
border.borderTop && (style.borderTop = border.borderTop);
|
|
56
|
+
border.borderRight && (style.borderRight = border.borderRight);
|
|
57
|
+
border.borderBottom && (style.borderBottom = border.borderBottom);
|
|
58
|
+
border.borderLeft && (style.borderLeft = border.borderLeft);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function buildPadding(style, padding) {
|
|
62
|
+
if (padding) {
|
|
63
|
+
padding.padding && (style.padding = padding.padding);
|
|
64
|
+
padding.paddingTop && (style.paddingTop = padding.paddingTop);
|
|
65
|
+
padding.paddingRight && (style.paddingRight = padding.paddingRight);
|
|
66
|
+
padding.paddingBottom && (style.paddingBottom = padding.paddingBottom);
|
|
67
|
+
padding.paddingLeft && (style.paddingLeft = padding.paddingLeft);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function buildTransition(style, transition) {
|
|
71
|
+
if (transition) {
|
|
72
|
+
transition.transition && (style.transition = transition.transition);
|
|
73
|
+
transition.transitionProperty && (style.transitionProperty = transition.transitionProperty);
|
|
74
|
+
transition.transitionDuration && (style.transitionDuration = transition.transitionDuration);
|
|
75
|
+
transition.transitionDelay && (style.transitionDelay = transition.transitionDelay);
|
|
76
|
+
transition.transitionTimingFunction && (style.transitionTimingFunction = transition.transitionTimingFunction);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function useStyle() {
|
|
81
|
+
function build(options, isFlex) {
|
|
82
|
+
const style2 = Object.create(null);
|
|
83
|
+
if (options) {
|
|
84
|
+
buildAlign(style2, options, isFlex);
|
|
85
|
+
buildSize(style2, options.width, "width", isFlex);
|
|
86
|
+
buildSize(style2, options.height, "height", isFlex);
|
|
87
|
+
buildMargin(style2, options);
|
|
88
|
+
buildBorder(style2, options);
|
|
89
|
+
buildPadding(style2, options);
|
|
90
|
+
buildTransition(style2, options);
|
|
91
|
+
}
|
|
92
|
+
return style2;
|
|
93
|
+
}
|
|
94
|
+
function getStyle(target) {
|
|
95
|
+
snail_core.throwIfFalse(target instanceof HTMLElement, "getStyle: target must be an HTMLElement.");
|
|
96
|
+
const ret = Object.create(null);
|
|
97
|
+
for (var _len = arguments.length, keys = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
98
|
+
keys[_key - 1] = arguments[_key];
|
|
99
|
+
}
|
|
100
|
+
keys.forEach(key => ret[key] = target.style[key]);
|
|
101
|
+
return Object.freeze(ret);
|
|
102
|
+
}
|
|
103
|
+
function setStyle(target, options) {
|
|
104
|
+
snail_core.throwIfFalse(target instanceof HTMLElement, "setStyle: target must be an HTMLElement.");
|
|
105
|
+
const style2 = build(options);
|
|
106
|
+
Object.assign(target.style, style2);
|
|
107
|
+
}
|
|
108
|
+
return Object.freeze({
|
|
109
|
+
build,
|
|
110
|
+
getStyle,
|
|
111
|
+
setStyle
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
const style = useStyle();
|
|
115
|
+
|
|
116
|
+
const ERROR_SAMEVALUE = "value cannot be the same";
|
|
117
|
+
function checkTransition(scope, target, options) {
|
|
118
|
+
snail_core.checkScope(scope, "checkTransition: scope destroyed.");
|
|
119
|
+
snail_core.throwIfFalse(target instanceof HTMLElement, "checkTransition: target must be an HTMLElement.");
|
|
120
|
+
snail_core.throwIfNullOrUndefined(options, "checkTransition: options must be an Object.");
|
|
121
|
+
snail_core.throwIfTrue(options.start == options.target, `checkTransition: options.start and end ${ERROR_SAMEVALUE}. value: ${options.start}`);
|
|
122
|
+
options.time = options.time > 0 ? options.time : 200;
|
|
123
|
+
options.start = options.start || "";
|
|
124
|
+
options.target = options.target || "";
|
|
125
|
+
}
|
|
126
|
+
function startTransition(target, init, styleName, options) {
|
|
127
|
+
const backStyle = style.getStyle(target, ...Object.keys(init), styleName);
|
|
128
|
+
const scope = snail_core.useScope();
|
|
129
|
+
const setTarget = () => target.style[styleName] = options.target;
|
|
130
|
+
Object.assign(target.style, init, {
|
|
131
|
+
[styleName]: options.start
|
|
132
|
+
});
|
|
133
|
+
setTimeout(setTarget, 1);
|
|
134
|
+
setTimeout(scope.destroy, options.time);
|
|
135
|
+
return scope.onDestroy(() => {
|
|
136
|
+
Object.assign(target.style, backStyle);
|
|
137
|
+
options.clear != true && setTarget();
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function useAnimation() {
|
|
142
|
+
const scopes = snail_core.useScopes();
|
|
143
|
+
function roll(target, direction, options) {
|
|
144
|
+
checkTransition(manager, target, options);
|
|
145
|
+
const styleName = direction === "horizontal" ? "width" : "height";
|
|
146
|
+
const scope = startTransition(target, {
|
|
147
|
+
overflow: "hidden !important",
|
|
148
|
+
transition: `${styleName} ${options.time || 200}ms ease !important`
|
|
149
|
+
}, styleName, options);
|
|
150
|
+
return scopes.add(scope);
|
|
151
|
+
}
|
|
152
|
+
const manager = snail_core.mountScope({
|
|
153
|
+
roll
|
|
154
|
+
});
|
|
155
|
+
manager.onDestroy(scopes.destroy);
|
|
156
|
+
return Object.freeze(manager);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const LINK_CONFIG = {
|
|
160
|
+
theme: void 0,
|
|
161
|
+
container: void 0,
|
|
162
|
+
origin: void 0,
|
|
163
|
+
version: void 0
|
|
164
|
+
};
|
|
165
|
+
const EVENT_ChangeTheme = "Snail.ChangeTheme";
|
|
166
|
+
const LINK_CONTAINER_ID = "snail_link_container";
|
|
167
|
+
function checkLinkOptions(options) {
|
|
168
|
+
options = snail_core.extract(Object.keys(LINK_CONFIG), options);
|
|
169
|
+
snail_core.hasOwnProperty(options, "theme") && (options.theme = snail_core.tidyString(options.theme));
|
|
170
|
+
snail_core.hasOwnProperty(options, "origin") && (options.origin = snail_core.tidyString(options.origin));
|
|
171
|
+
return options;
|
|
172
|
+
}
|
|
173
|
+
function getLinkDefaultContainer() {
|
|
174
|
+
var container = document.getElementById(LINK_CONTAINER_ID);
|
|
175
|
+
if (!container) {
|
|
176
|
+
container = document.createElement("div");
|
|
177
|
+
container.id = LINK_CONTAINER_ID;
|
|
178
|
+
container.style.display = "none !important";
|
|
179
|
+
container.style.height = "0px";
|
|
180
|
+
container.style.width = "0px";
|
|
181
|
+
document.body.appendChild(container);
|
|
182
|
+
}
|
|
183
|
+
return container;
|
|
184
|
+
}
|
|
185
|
+
function setlinkByTheme(links, code, options) {
|
|
186
|
+
let hasMatchTheme = false;
|
|
187
|
+
links.forEach(link => {
|
|
188
|
+
code && link.theme == code && (hasMatchTheme = true);
|
|
189
|
+
link.element.disabled = link.ref == 0 || link.theme != void 0 && link.theme != code;
|
|
190
|
+
});
|
|
191
|
+
let defaultTheme = hasMatchTheme ? void 0 : options.theme || LINK_CONFIG.theme;
|
|
192
|
+
defaultTheme && links.forEach(link => {
|
|
193
|
+
link.theme == defaultTheme && (link.element.disabled = link.ref == 0);
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
function destroylink(links, isDel) {
|
|
197
|
+
links.forEach(link => {
|
|
198
|
+
link.ref = isDel ? 0 : Math.max(0, link.ref - 1);
|
|
199
|
+
link.element.setAttribute("data-ref", link.ref.toString());
|
|
200
|
+
link.element.disabled = link.ref == 0;
|
|
201
|
+
if (isDel == true) {
|
|
202
|
+
link.element.parentNode && link.element.parentNode.removeChild(link.element);
|
|
203
|
+
link.element = void 0;
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
links.splice(0);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function useLink(options) {
|
|
210
|
+
options = Object.freeze(checkLinkOptions(options));
|
|
211
|
+
var scopeTheme = void 0;
|
|
212
|
+
const scopeLinks = [];
|
|
213
|
+
function register() {
|
|
214
|
+
const funclinks = [];
|
|
215
|
+
for (var _len = arguments.length, files = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
216
|
+
files[_key] = arguments[_key];
|
|
217
|
+
}
|
|
218
|
+
snail_core.isArrayNotEmpty(files) && files.forEach(file => {
|
|
219
|
+
const link2 = typeof file == "string" ? {
|
|
220
|
+
file,
|
|
221
|
+
theme: void 0
|
|
222
|
+
} : file;
|
|
223
|
+
let href = linkMap.get(link2.file);
|
|
224
|
+
href && console.log(`map to new link file. link: ${link2.file}, new link: ${href}`);
|
|
225
|
+
href = href || link2.file;
|
|
226
|
+
snail_core.mustString(href, "href");
|
|
227
|
+
let tmpStr = options.origin || LINK_CONFIG.origin;
|
|
228
|
+
snail_core.isStringNotEmpty(tmpStr) && (href = new URL(href, tmpStr).toString());
|
|
229
|
+
tmpStr = href.toLowerCase();
|
|
230
|
+
let linkEle = scopeLinks.find(s => s.theme == link2.theme && s.file.toLowerCase() == tmpStr);
|
|
231
|
+
if (!linkEle) {
|
|
232
|
+
linkEle = {
|
|
233
|
+
file: href,
|
|
234
|
+
theme: link2.theme,
|
|
235
|
+
ref: 0
|
|
236
|
+
};
|
|
237
|
+
scopeLinks.push(linkEle);
|
|
238
|
+
}
|
|
239
|
+
linkEle.ref += 1;
|
|
240
|
+
funclinks.push(linkEle);
|
|
241
|
+
if (!linkEle.element) {
|
|
242
|
+
linkEle.element = document.createElement("link");
|
|
243
|
+
linkEle.element.href = (options.version || LINK_CONFIG.version || snail_core.version).formart(linkEle.file);
|
|
244
|
+
linkEle.element.rel = "stylesheet";
|
|
245
|
+
linkEle.element.disabled = true;
|
|
246
|
+
link2.theme && linkEle.element.setAttribute("data-theme", link2.theme);
|
|
247
|
+
const container = options.container || LINK_CONFIG.container || getLinkDefaultContainer();
|
|
248
|
+
container.appendChild(linkEle.element);
|
|
249
|
+
}
|
|
250
|
+
linkEle.element.setAttribute("data-ref", linkEle.ref.toString());
|
|
251
|
+
});
|
|
252
|
+
funclinks.length > 0 && setlinkByTheme(funclinks, scopeTheme, options);
|
|
253
|
+
return snail_core.useScope().onDestroy(() => destroylink(funclinks, false));
|
|
254
|
+
}
|
|
255
|
+
function theme(code) {
|
|
256
|
+
snail_core.mustString(code, "code");
|
|
257
|
+
if (scopeTheme != code) {
|
|
258
|
+
setlinkByTheme(scopeLinks, scopeTheme = code, options);
|
|
259
|
+
manager === link && snail_core.event.trigger(EVENT_ChangeTheme, code, true);
|
|
260
|
+
}
|
|
261
|
+
return manager;
|
|
262
|
+
}
|
|
263
|
+
const manager = snail_core.mountScope({
|
|
264
|
+
register,
|
|
265
|
+
theme
|
|
266
|
+
});
|
|
267
|
+
{
|
|
268
|
+
manager.onDestroy(() => {
|
|
269
|
+
snail_core.event.off(EVENT_ChangeTheme, theme);
|
|
270
|
+
destroylink(scopeLinks, true);
|
|
271
|
+
});
|
|
272
|
+
snail_core.event.on(EVENT_ChangeTheme, theme);
|
|
273
|
+
}
|
|
274
|
+
return Object.freeze(manager);
|
|
275
|
+
}
|
|
276
|
+
const linkMap = new Map();
|
|
277
|
+
const link = useLink();
|
|
278
|
+
snail_core.event.off(EVENT_ChangeTheme, link.theme);
|
|
279
|
+
function configLink(options) {
|
|
280
|
+
options = checkLinkOptions(options);
|
|
281
|
+
Object.assign(LINK_CONFIG, options);
|
|
282
|
+
return link;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function useObserver() {
|
|
286
|
+
const scopes = snail_core.useScopes();
|
|
287
|
+
function onEvent(target, name, fn) {
|
|
288
|
+
snail_core.checkScope(manager, "onEvent: observer destroyed.");
|
|
289
|
+
snail_core.throwIfFalse(target instanceof Element || target === window, "onEvent: target must be a Element or Window");
|
|
290
|
+
snail_core.mustString(name, "onEvent: name");
|
|
291
|
+
snail_core.mustFunction(fn, "onEvent: fn");
|
|
292
|
+
target.addEventListener(name, fn);
|
|
293
|
+
return scopes.get().onDestroy(() => target.removeEventListener(name, fn));
|
|
294
|
+
}
|
|
295
|
+
function onSize(el, fn) {
|
|
296
|
+
snail_core.checkScope(manager, "onSize: observer destroyed.");
|
|
297
|
+
snail_core.throwIfFalse(el instanceof Element, "onSize: el must be a Element.");
|
|
298
|
+
const scope = scopes.get();
|
|
299
|
+
var preSize = void 0;
|
|
300
|
+
function calcSize() {
|
|
301
|
+
if (scope.destroyed == false) {
|
|
302
|
+
const rect = el.getBoundingClientRect();
|
|
303
|
+
const isChange = preSize == void 0 || preSize.width != rect.width || preSize.height != rect.height;
|
|
304
|
+
if (isChange == true) {
|
|
305
|
+
preSize = Object.freeze({
|
|
306
|
+
width: rect.width,
|
|
307
|
+
height: rect.height
|
|
308
|
+
});
|
|
309
|
+
snail_core.run(fn, preSize);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
const resizeObserver = "ResizeObserver" in window ? new ResizeObserver(calcSize) : void 0;
|
|
314
|
+
const timer = resizeObserver ? resizeObserver.observe(el) : setInterval(calcSize, 100);
|
|
315
|
+
setTimeout(calcSize);
|
|
316
|
+
return scope.onDestroy(() => {
|
|
317
|
+
resizeObserver && resizeObserver.disconnect();
|
|
318
|
+
timer && clearInterval(timer);
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
function onClient(el, fn) {
|
|
322
|
+
snail_core.checkScope(manager, "onClient: observer destroyed.");
|
|
323
|
+
snail_core.throwIfFalse(el instanceof Element, "onClient: el must be a Element.");
|
|
324
|
+
const scope = scopes.get();
|
|
325
|
+
var preRect = void 0;
|
|
326
|
+
const timer = setInterval(function () {
|
|
327
|
+
if (scope.destroyed == false) {
|
|
328
|
+
const rect = el.getBoundingClientRect();
|
|
329
|
+
const isChange = preRect == void 0 || rect.x != preRect.x || rect.y != preRect.y || rect.width != preRect.width || rect.height != preRect.height;
|
|
330
|
+
if (isChange == true) {
|
|
331
|
+
preRect = DOMRectReadOnly.fromRect(rect);
|
|
332
|
+
snail_core.run(fn, preRect);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}, 100);
|
|
336
|
+
return scope.onDestroy(() => clearInterval(timer));
|
|
337
|
+
}
|
|
338
|
+
const manager = snail_core.mountScope({
|
|
339
|
+
onEvent,
|
|
340
|
+
onSize,
|
|
341
|
+
onClient
|
|
342
|
+
});
|
|
343
|
+
manager.onDestroy(scopes.destroy);
|
|
344
|
+
return Object.freeze(manager);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
exports.configLink = configLink;
|
|
348
|
+
exports.link = link;
|
|
349
|
+
exports.linkMap = linkMap;
|
|
350
|
+
exports.style = style;
|
|
351
|
+
exports.useAnimation = useAnimation;
|
|
352
|
+
exports.useLink = useLink;
|
|
353
|
+
exports.useObserver = useObserver;
|
|
354
|
+
|
|
355
|
+
}));
|
package/package.json
CHANGED