@lytjs/web 6.4.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/README.md +179 -0
- package/dist/index.cjs +481 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +435 -0
- package/dist/index.d.ts +435 -0
- package/dist/index.js +465 -0
- package/dist/index.js.map +1 -0
- package/package.json +60 -0
package/README.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# @lytjs/web
|
|
2
|
+
|
|
3
|
+
> Web 平台工具包,提供 CSS 变量管理、ResizeObserver、Web Components 等 Web 特定功能
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @lytjs/web
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 核心功能
|
|
12
|
+
|
|
13
|
+
### CSS 变量管理
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { setCssVar, getCssVar, removeCssVar, setCssVars, watchCssVar } from '@lytjs/web';
|
|
17
|
+
|
|
18
|
+
// 设置 CSS 变量
|
|
19
|
+
setCssVar('--primary-color', '#1890ff');
|
|
20
|
+
setCssVar('--font-size', '14px', document.documentElement);
|
|
21
|
+
|
|
22
|
+
// 获取 CSS 变量
|
|
23
|
+
const color = getCssVar('--primary-color');
|
|
24
|
+
|
|
25
|
+
// 移除 CSS 变量
|
|
26
|
+
removeCssVar('--primary-color');
|
|
27
|
+
|
|
28
|
+
// 批量设置
|
|
29
|
+
setCssVars({
|
|
30
|
+
'--primary-color': '#1890ff',
|
|
31
|
+
'--secondary-color': '#52c41a',
|
|
32
|
+
'--font-size': '14px',
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// 监听 CSS 变量变化
|
|
36
|
+
const unwatch = watchCssVar('--primary-color', (newVal, oldVal) => {
|
|
37
|
+
console.log('CSS 变量变化:', oldVal, '->', newVal);
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### ResizeObserver
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { useResizeObserver, createResizeObserver, type ResizeObserverEntry } from '@lytjs/web';
|
|
45
|
+
|
|
46
|
+
// 使用 ResizeObserver
|
|
47
|
+
const cleanup = useResizeObserver(
|
|
48
|
+
document.getElementById('container'),
|
|
49
|
+
(entries: ResizeObserverEntry[]) => {
|
|
50
|
+
for (const entry of entries) {
|
|
51
|
+
console.log('尺寸变化:', entry.contentRect);
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
// 停止监听
|
|
57
|
+
cleanup();
|
|
58
|
+
|
|
59
|
+
// 创建可复用的 ResizeObserver
|
|
60
|
+
const observer = createResizeObserver((entries) => {
|
|
61
|
+
// 处理尺寸变化
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
observer.observe(element1);
|
|
65
|
+
observer.observe(element2);
|
|
66
|
+
observer.disconnect();
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Web Components
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
import {
|
|
73
|
+
defineLytElement,
|
|
74
|
+
useShadowRoot,
|
|
75
|
+
useHost,
|
|
76
|
+
useWebComponentSlots,
|
|
77
|
+
injectChildStyles,
|
|
78
|
+
} from '@lytjs/web';
|
|
79
|
+
|
|
80
|
+
// 定义 Web Component
|
|
81
|
+
const MyElement = defineLytElement({
|
|
82
|
+
name: 'my-element',
|
|
83
|
+
props: {
|
|
84
|
+
title: String,
|
|
85
|
+
count: Number,
|
|
86
|
+
},
|
|
87
|
+
setup(props) {
|
|
88
|
+
const shadowRoot = useShadowRoot();
|
|
89
|
+
const host = useHost();
|
|
90
|
+
const slots = useWebComponentSlots();
|
|
91
|
+
|
|
92
|
+
return () => h('div', [h('h1', props.title), h('p', `Count: ${props.count}`), h('slot')]);
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// 注册自定义元素
|
|
97
|
+
customElements.define('my-element', MyElement);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### 媒体查询
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { useMediaQuery, usePreferredColorScheme, usePreferredReducedMotion } from '@lytjs/web';
|
|
104
|
+
|
|
105
|
+
// 响应式断点
|
|
106
|
+
const isMobile = useMediaQuery('(max-width: 768px)');
|
|
107
|
+
const isTablet = useMediaQuery('(min-width: 769px) and (max-width: 1024px)');
|
|
108
|
+
const isDesktop = useMediaQuery('(min-width: 1025px)');
|
|
109
|
+
|
|
110
|
+
// 系统主题偏好
|
|
111
|
+
const colorScheme = usePreferredColorScheme(); // 'light' | 'dark'
|
|
112
|
+
const reducedMotion = usePreferredReducedMotion(); // boolean
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 网络状态
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
import { useOnline, useNetworkStatus } from '@lytjs/web';
|
|
119
|
+
|
|
120
|
+
// 在线状态
|
|
121
|
+
const isOnline = useOnline();
|
|
122
|
+
|
|
123
|
+
// 详细网络状态
|
|
124
|
+
const network = useNetworkStatus();
|
|
125
|
+
// {
|
|
126
|
+
// online: boolean,
|
|
127
|
+
// type: 'wifi' | '4g' | '3g' | '2g' | 'slow-2g',
|
|
128
|
+
// downlink: number,
|
|
129
|
+
// rtt: number,
|
|
130
|
+
// }
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### 页面可见性
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
import { usePageVisibility } from '@lytjs/web';
|
|
137
|
+
|
|
138
|
+
const isVisible = usePageVisibility();
|
|
139
|
+
|
|
140
|
+
// 页面可见性变化时
|
|
141
|
+
if (isVisible) {
|
|
142
|
+
// 恢复动画、轮询等
|
|
143
|
+
} else {
|
|
144
|
+
// 暂停动画、轮询等
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### 鼠标/触摸位置
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
import { useMousePosition, useMouseInElement, useWindowScroll } from '@lytjs/web';
|
|
152
|
+
|
|
153
|
+
// 鼠标位置
|
|
154
|
+
const { x, y } = useMousePosition();
|
|
155
|
+
|
|
156
|
+
// 元素内相对位置
|
|
157
|
+
const { x: elX, y: elY, isOutside } = useMouseInElement(elementRef);
|
|
158
|
+
|
|
159
|
+
// 窗口滚动
|
|
160
|
+
const { x: scrollX, y: scrollY } = useWindowScroll();
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## 类型定义
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
import type {
|
|
167
|
+
ResizeObserverEntry,
|
|
168
|
+
ResizeObserverCallback,
|
|
169
|
+
LytElementOptions,
|
|
170
|
+
LytElementConstructor,
|
|
171
|
+
NetworkStatus,
|
|
172
|
+
} from '@lytjs/web';
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## 相关包
|
|
176
|
+
|
|
177
|
+
- [@lytjs/core](../core) - 框架核心
|
|
178
|
+
- [@lytjs/adapter-web](../adapter-web) - Web 平台适配器
|
|
179
|
+
- [@lytjs/common-dom](../common/packages/dom) - DOM 工具
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/css-vars.ts
|
|
4
|
+
function normalizeVarName(name) {
|
|
5
|
+
return name.startsWith("--") ? name : `--${name}`;
|
|
6
|
+
}
|
|
7
|
+
function stripVarPrefix(name) {
|
|
8
|
+
return name.startsWith("--") ? name.slice(2) : name;
|
|
9
|
+
}
|
|
10
|
+
function setCSSVar(paramsOrElement, name, value, options) {
|
|
11
|
+
let element;
|
|
12
|
+
let varName;
|
|
13
|
+
let varValue;
|
|
14
|
+
let opts;
|
|
15
|
+
if (paramsOrElement instanceof HTMLElement) {
|
|
16
|
+
element = paramsOrElement;
|
|
17
|
+
varName = normalizeVarName(name);
|
|
18
|
+
varValue = value;
|
|
19
|
+
opts = options;
|
|
20
|
+
} else if ("element" in paramsOrElement) {
|
|
21
|
+
element = paramsOrElement.element;
|
|
22
|
+
varName = normalizeVarName(paramsOrElement.name);
|
|
23
|
+
varValue = paramsOrElement.value;
|
|
24
|
+
opts = paramsOrElement.options;
|
|
25
|
+
} else {
|
|
26
|
+
element = document.documentElement;
|
|
27
|
+
varName = normalizeVarName(paramsOrElement.name);
|
|
28
|
+
varValue = paramsOrElement.value;
|
|
29
|
+
opts = paramsOrElement.options;
|
|
30
|
+
}
|
|
31
|
+
if (!element) return;
|
|
32
|
+
if (varValue === null || varValue === void 0) {
|
|
33
|
+
element.style.removeProperty(varName);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
let finalValue;
|
|
37
|
+
if (typeof varValue === "number") {
|
|
38
|
+
finalValue = opts?.unit ? `${varValue}${opts.unit}` : String(varValue);
|
|
39
|
+
} else {
|
|
40
|
+
finalValue = varValue;
|
|
41
|
+
}
|
|
42
|
+
element.style.setProperty(varName, finalValue);
|
|
43
|
+
}
|
|
44
|
+
function getCSSVar(elementOrName, nameOrFallback, fallback) {
|
|
45
|
+
let element;
|
|
46
|
+
let varName;
|
|
47
|
+
let defaultValue;
|
|
48
|
+
if (typeof elementOrName === "string") {
|
|
49
|
+
element = document.documentElement;
|
|
50
|
+
varName = normalizeVarName(elementOrName);
|
|
51
|
+
defaultValue = nameOrFallback;
|
|
52
|
+
} else {
|
|
53
|
+
element = elementOrName;
|
|
54
|
+
varName = normalizeVarName(nameOrFallback);
|
|
55
|
+
defaultValue = fallback;
|
|
56
|
+
}
|
|
57
|
+
if (!element) return defaultValue ?? null;
|
|
58
|
+
const inlineValue = element.style.getPropertyValue(varName);
|
|
59
|
+
if (inlineValue) return inlineValue;
|
|
60
|
+
const computedStyle = window.getComputedStyle(element);
|
|
61
|
+
const value = computedStyle.getPropertyValue(varName).trim();
|
|
62
|
+
return value || defaultValue || null;
|
|
63
|
+
}
|
|
64
|
+
function setCSSVars(elementOrVars, vars) {
|
|
65
|
+
let element;
|
|
66
|
+
let variables;
|
|
67
|
+
if (elementOrVars instanceof HTMLElement) {
|
|
68
|
+
element = elementOrVars;
|
|
69
|
+
variables = vars ?? {};
|
|
70
|
+
} else {
|
|
71
|
+
element = document.documentElement;
|
|
72
|
+
variables = elementOrVars;
|
|
73
|
+
}
|
|
74
|
+
if (!element) return;
|
|
75
|
+
Object.entries(variables).forEach(([name, value]) => {
|
|
76
|
+
setCSSVar(element, name, value);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
function getCSSVars(elementOrNames, names) {
|
|
80
|
+
let element;
|
|
81
|
+
let varNames;
|
|
82
|
+
if (elementOrNames instanceof HTMLElement) {
|
|
83
|
+
element = elementOrNames;
|
|
84
|
+
varNames = names ?? [];
|
|
85
|
+
} else {
|
|
86
|
+
element = document.documentElement;
|
|
87
|
+
varNames = elementOrNames;
|
|
88
|
+
}
|
|
89
|
+
const result = {};
|
|
90
|
+
varNames.forEach((name) => {
|
|
91
|
+
result[name] = getCSSVar(element, name);
|
|
92
|
+
});
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
function removeCSSVar(elementOrName, name) {
|
|
96
|
+
let element;
|
|
97
|
+
let varName;
|
|
98
|
+
if (typeof elementOrName === "string") {
|
|
99
|
+
element = document.documentElement;
|
|
100
|
+
varName = normalizeVarName(elementOrName);
|
|
101
|
+
} else {
|
|
102
|
+
element = elementOrName;
|
|
103
|
+
varName = normalizeVarName(name);
|
|
104
|
+
}
|
|
105
|
+
if (!element) return;
|
|
106
|
+
element.style.removeProperty(varName);
|
|
107
|
+
}
|
|
108
|
+
function removeCSSVars(elementOrNames, names) {
|
|
109
|
+
let element;
|
|
110
|
+
let varNames;
|
|
111
|
+
if (elementOrNames instanceof HTMLElement) {
|
|
112
|
+
element = elementOrNames;
|
|
113
|
+
varNames = names ?? [];
|
|
114
|
+
} else {
|
|
115
|
+
element = document.documentElement;
|
|
116
|
+
varNames = elementOrNames;
|
|
117
|
+
}
|
|
118
|
+
if (!element) return;
|
|
119
|
+
varNames.forEach((name) => {
|
|
120
|
+
element.style.removeProperty(normalizeVarName(name));
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
function hasCSSVar(elementOrName, name) {
|
|
124
|
+
let element;
|
|
125
|
+
let varName;
|
|
126
|
+
if (typeof elementOrName === "string") {
|
|
127
|
+
element = document.documentElement;
|
|
128
|
+
varName = normalizeVarName(elementOrName);
|
|
129
|
+
} else {
|
|
130
|
+
element = elementOrName;
|
|
131
|
+
varName = normalizeVarName(name);
|
|
132
|
+
}
|
|
133
|
+
if (!element) return false;
|
|
134
|
+
if (element.style.getPropertyValue(varName)) return true;
|
|
135
|
+
const computedStyle = window.getComputedStyle(element);
|
|
136
|
+
return !!computedStyle.getPropertyValue(varName).trim();
|
|
137
|
+
}
|
|
138
|
+
function getAllCSSVars(element) {
|
|
139
|
+
const el = element ?? document.documentElement;
|
|
140
|
+
if (!el) return {};
|
|
141
|
+
const result = {};
|
|
142
|
+
const computedStyle = window.getComputedStyle(el);
|
|
143
|
+
for (let i = 0; i < computedStyle.length; i++) {
|
|
144
|
+
const prop = computedStyle[i];
|
|
145
|
+
if (prop.startsWith("--")) {
|
|
146
|
+
const value = computedStyle.getPropertyValue(prop).trim();
|
|
147
|
+
if (value) {
|
|
148
|
+
result[prop] = value;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
154
|
+
function toggleCSSVar(elementOrName, nameOrValue1, value1OrValue2, value2) {
|
|
155
|
+
let element;
|
|
156
|
+
let varName;
|
|
157
|
+
let val1;
|
|
158
|
+
let val2;
|
|
159
|
+
if (typeof elementOrName === "string") {
|
|
160
|
+
element = document.documentElement;
|
|
161
|
+
varName = normalizeVarName(elementOrName);
|
|
162
|
+
val1 = nameOrValue1;
|
|
163
|
+
val2 = value1OrValue2;
|
|
164
|
+
} else {
|
|
165
|
+
element = elementOrName;
|
|
166
|
+
varName = normalizeVarName(nameOrValue1);
|
|
167
|
+
val1 = value1OrValue2;
|
|
168
|
+
val2 = value2;
|
|
169
|
+
}
|
|
170
|
+
const currentValue = getCSSVar(element, varName);
|
|
171
|
+
const newValue = currentValue === val1 ? val2 : val1;
|
|
172
|
+
setCSSVar(element, varName, newValue);
|
|
173
|
+
return newValue;
|
|
174
|
+
}
|
|
175
|
+
var _CSSVarObserver = class _CSSVarObserver {
|
|
176
|
+
constructor(element) {
|
|
177
|
+
this.observer = null;
|
|
178
|
+
this.callbacks = /* @__PURE__ */ new Map();
|
|
179
|
+
/**
|
|
180
|
+
* 检查变量变化
|
|
181
|
+
* FIX: P2-v11-37 添加最大条目限制,防止 lastValues Map 无限增长
|
|
182
|
+
*/
|
|
183
|
+
this.lastValues = /* @__PURE__ */ new Map();
|
|
184
|
+
this.element = element ?? document.documentElement;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* 开始观察 CSS 变量变化
|
|
188
|
+
*
|
|
189
|
+
* @param names - 要观察的变量名数组(可选,不指定则观察所有)
|
|
190
|
+
*/
|
|
191
|
+
observe(names) {
|
|
192
|
+
if (this.observer) return;
|
|
193
|
+
const targetNames = names?.map(normalizeVarName);
|
|
194
|
+
this.observer = new MutationObserver((mutations) => {
|
|
195
|
+
mutations.forEach((mutation) => {
|
|
196
|
+
if (mutation.type === "attributes" && mutation.attributeName === "style") {
|
|
197
|
+
this.checkChanges(targetNames);
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
this.observer.observe(this.element, {
|
|
202
|
+
attributes: true,
|
|
203
|
+
attributeFilter: ["style"]
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* 停止观察
|
|
208
|
+
*/
|
|
209
|
+
disconnect() {
|
|
210
|
+
this.observer?.disconnect();
|
|
211
|
+
this.observer = null;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* 订阅变量变化
|
|
215
|
+
*
|
|
216
|
+
* @param name - 变量名
|
|
217
|
+
* @param callback - 变化回调
|
|
218
|
+
* @returns 取消订阅函数
|
|
219
|
+
*/
|
|
220
|
+
subscribe(name, callback) {
|
|
221
|
+
const varName = normalizeVarName(name);
|
|
222
|
+
if (!this.callbacks.has(varName)) {
|
|
223
|
+
this.callbacks.set(varName, /* @__PURE__ */ new Set());
|
|
224
|
+
}
|
|
225
|
+
this.callbacks.get(varName).add(callback);
|
|
226
|
+
return () => {
|
|
227
|
+
this.callbacks.get(varName)?.delete(callback);
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
checkChanges(targetNames) {
|
|
231
|
+
const namesToCheck = targetNames ?? Array.from(this.callbacks.keys());
|
|
232
|
+
if (this.lastValues.size > _CSSVarObserver.MAX_LAST_VALUES_SIZE) {
|
|
233
|
+
const activeNames = new Set(this.callbacks.keys());
|
|
234
|
+
for (const key of this.lastValues.keys()) {
|
|
235
|
+
if (!activeNames.has(key)) {
|
|
236
|
+
this.lastValues.delete(key);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
namesToCheck.forEach((name) => {
|
|
241
|
+
const currentValue = getCSSVar(this.element, name);
|
|
242
|
+
const lastValue = this.lastValues.get(name);
|
|
243
|
+
if (currentValue !== lastValue) {
|
|
244
|
+
this.lastValues.set(name, currentValue);
|
|
245
|
+
const callbacks = this.callbacks.get(name);
|
|
246
|
+
if (callbacks) {
|
|
247
|
+
callbacks.forEach((cb) => cb(currentValue, lastValue ?? null, name));
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
/** lastValues 最大条目数 */
|
|
254
|
+
_CSSVarObserver.MAX_LAST_VALUES_SIZE = 500;
|
|
255
|
+
var CSSVarObserver = _CSSVarObserver;
|
|
256
|
+
var ThemeManager = class {
|
|
257
|
+
constructor(element) {
|
|
258
|
+
this.themes = /* @__PURE__ */ new Map();
|
|
259
|
+
this.currentTheme = null;
|
|
260
|
+
this.element = element ?? document.documentElement;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* 注册主题
|
|
264
|
+
*
|
|
265
|
+
* @param name - 主题名称
|
|
266
|
+
* @param config - 主题配置(CSS 变量键值对)
|
|
267
|
+
*/
|
|
268
|
+
register(name, config) {
|
|
269
|
+
this.themes.set(name, config);
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* 应用主题
|
|
273
|
+
*
|
|
274
|
+
* @param name - 主题名称
|
|
275
|
+
*/
|
|
276
|
+
apply(name) {
|
|
277
|
+
const theme = this.themes.get(name);
|
|
278
|
+
if (!theme) return false;
|
|
279
|
+
setCSSVars(this.element, theme);
|
|
280
|
+
this.currentTheme = name;
|
|
281
|
+
this.element.setAttribute("data-theme", name);
|
|
282
|
+
return true;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* 获取当前主题名称
|
|
286
|
+
*/
|
|
287
|
+
getCurrentTheme() {
|
|
288
|
+
return this.currentTheme;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* 获取已注册的主题列表
|
|
292
|
+
*/
|
|
293
|
+
getRegisteredThemes() {
|
|
294
|
+
return Array.from(this.themes.keys());
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* 检查主题是否存在
|
|
298
|
+
*/
|
|
299
|
+
hasTheme(name) {
|
|
300
|
+
return this.themes.has(name);
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* 获取主题配置
|
|
304
|
+
*/
|
|
305
|
+
getThemeConfig(name) {
|
|
306
|
+
return this.themes.get(name);
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
// src/resize-observer.ts
|
|
311
|
+
exports.ResizeObserverManager = class ResizeObserverManager {
|
|
312
|
+
constructor(callback) {
|
|
313
|
+
this.observer = null;
|
|
314
|
+
this.observedElements = /* @__PURE__ */ new Set();
|
|
315
|
+
this.isConnected = false;
|
|
316
|
+
this.callback = callback;
|
|
317
|
+
if (typeof ResizeObserver === "undefined") {
|
|
318
|
+
if (__DEV__) {
|
|
319
|
+
console.warn(
|
|
320
|
+
"[lytjs/resize-observer] ResizeObserver is not supported in this environment."
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
this.observer = new ResizeObserver((entries) => {
|
|
326
|
+
const activeEntries = entries.filter((entry) => this.observedElements.has(entry.target));
|
|
327
|
+
if (activeEntries.length > 0) {
|
|
328
|
+
this.callback(activeEntries);
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* 开始观察元素
|
|
334
|
+
*
|
|
335
|
+
* @param target - 要观察的目标元素
|
|
336
|
+
* @param options - 观察选项
|
|
337
|
+
* @returns 是否成功开始观察
|
|
338
|
+
*/
|
|
339
|
+
observe(target, options) {
|
|
340
|
+
if (!this.observer) {
|
|
341
|
+
if (__DEV__) {
|
|
342
|
+
console.warn("[lytjs/resize-observer] Cannot observe: ResizeObserver is not available.");
|
|
343
|
+
}
|
|
344
|
+
return false;
|
|
345
|
+
}
|
|
346
|
+
if (this.observedElements.has(target)) {
|
|
347
|
+
if (__DEV__) {
|
|
348
|
+
console.warn("[lytjs/resize-observer] Element is already being observed.");
|
|
349
|
+
}
|
|
350
|
+
return false;
|
|
351
|
+
}
|
|
352
|
+
try {
|
|
353
|
+
this.observer.observe(target, options);
|
|
354
|
+
this.observedElements.add(target);
|
|
355
|
+
this.isConnected = true;
|
|
356
|
+
return true;
|
|
357
|
+
} catch (err) {
|
|
358
|
+
if (__DEV__) {
|
|
359
|
+
console.error("[lytjs/resize-observer] Error observing element:", err);
|
|
360
|
+
}
|
|
361
|
+
return false;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* 停止观察指定元素
|
|
366
|
+
*
|
|
367
|
+
* @param target - 要停止观察的目标元素
|
|
368
|
+
* @returns 是否成功停止观察
|
|
369
|
+
*/
|
|
370
|
+
unobserve(target) {
|
|
371
|
+
if (!this.observer) {
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
if (!this.observedElements.has(target)) {
|
|
375
|
+
return false;
|
|
376
|
+
}
|
|
377
|
+
try {
|
|
378
|
+
this.observer.unobserve(target);
|
|
379
|
+
this.observedElements.delete(target);
|
|
380
|
+
if (this.observedElements.size === 0) {
|
|
381
|
+
this.isConnected = false;
|
|
382
|
+
}
|
|
383
|
+
return true;
|
|
384
|
+
} catch (err) {
|
|
385
|
+
if (__DEV__) {
|
|
386
|
+
console.error("[lytjs/resize-observer] Error unobserving element:", err);
|
|
387
|
+
}
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* 停止观察所有元素并断开连接
|
|
393
|
+
*
|
|
394
|
+
* FIX: P2-5 这是关键方法,确保在组件卸载时调用此方法
|
|
395
|
+
*/
|
|
396
|
+
disconnect() {
|
|
397
|
+
if (!this.observer) {
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
try {
|
|
401
|
+
this.observer.disconnect();
|
|
402
|
+
this.observedElements.clear();
|
|
403
|
+
this.isConnected = false;
|
|
404
|
+
} catch (err) {
|
|
405
|
+
if (__DEV__) {
|
|
406
|
+
console.error("[lytjs/resize-observer] Error disconnecting observer:", err);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* 检查是否正在观察指定元素
|
|
412
|
+
*
|
|
413
|
+
* @param target - 要检查的目标元素
|
|
414
|
+
* @returns 是否正在观察
|
|
415
|
+
*/
|
|
416
|
+
isObserving(target) {
|
|
417
|
+
return this.observedElements.has(target);
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* 获取当前观察的元素数量
|
|
421
|
+
*/
|
|
422
|
+
get observedCount() {
|
|
423
|
+
return this.observedElements.size;
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* 检查观察者是否已连接(正在观察至少一个元素)
|
|
427
|
+
*/
|
|
428
|
+
get connected() {
|
|
429
|
+
return this.isConnected;
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* 检查 ResizeObserver 是否可用
|
|
433
|
+
*/
|
|
434
|
+
get isAvailable() {
|
|
435
|
+
return this.observer !== null;
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
function useResizeObserver(target, callback, options) {
|
|
439
|
+
const manager = new exports.ResizeObserverManager(callback);
|
|
440
|
+
manager.observe(target, options);
|
|
441
|
+
return () => {
|
|
442
|
+
manager.disconnect();
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
function supportsResizeObserver() {
|
|
446
|
+
return typeof ResizeObserver !== "undefined";
|
|
447
|
+
}
|
|
448
|
+
if (__DEV__) {
|
|
449
|
+
const managerRegistry = /* @__PURE__ */ new WeakSet();
|
|
450
|
+
const OriginalManager = exports.ResizeObserverManager;
|
|
451
|
+
exports.ResizeObserverManager = class extends OriginalManager {
|
|
452
|
+
constructor(callback) {
|
|
453
|
+
super(callback);
|
|
454
|
+
managerRegistry.add(this);
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
globalThis.__getResizeObserverStats = () => {
|
|
458
|
+
return {
|
|
459
|
+
activeManagers: 0,
|
|
460
|
+
totalObservedElements: 0
|
|
461
|
+
};
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
exports.CSSVarObserver = CSSVarObserver;
|
|
466
|
+
exports.ThemeManager = ThemeManager;
|
|
467
|
+
exports.getAllCSSVars = getAllCSSVars;
|
|
468
|
+
exports.getCSSVar = getCSSVar;
|
|
469
|
+
exports.getCSSVars = getCSSVars;
|
|
470
|
+
exports.hasCSSVar = hasCSSVar;
|
|
471
|
+
exports.normalizeVarName = normalizeVarName;
|
|
472
|
+
exports.removeCSSVar = removeCSSVar;
|
|
473
|
+
exports.removeCSSVars = removeCSSVars;
|
|
474
|
+
exports.setCSSVar = setCSSVar;
|
|
475
|
+
exports.setCSSVars = setCSSVars;
|
|
476
|
+
exports.stripVarPrefix = stripVarPrefix;
|
|
477
|
+
exports.supportsResizeObserver = supportsResizeObserver;
|
|
478
|
+
exports.toggleCSSVar = toggleCSSVar;
|
|
479
|
+
exports.useResizeObserver = useResizeObserver;
|
|
480
|
+
//# sourceMappingURL=index.cjs.map
|
|
481
|
+
//# sourceMappingURL=index.cjs.map
|