@wsxjs/wsx-core 0.0.5
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 -0
- package/dist/chunk-3CJEWYVF.mjs +197 -0
- package/dist/chunk-5JVEHB6H.mjs +197 -0
- package/dist/chunk-7E7KJQSW.mjs +210 -0
- package/dist/chunk-A5GYVTI3.mjs +222 -0
- package/dist/chunk-A5GYVTI3.mjs.map +1 -0
- package/dist/chunk-BV2V6BVN.mjs +221 -0
- package/dist/chunk-K6N3JDTI.mjs +216 -0
- package/dist/chunk-RVGKV4GP.mjs +79 -0
- package/dist/chunk-S3O776FY.mjs +173 -0
- package/dist/chunk-VNK4B3FW.mjs +217 -0
- package/dist/chunk-YNUVFDKT.mjs +222 -0
- package/dist/chunk-YNUVFDKT.mjs.map +1 -0
- package/dist/index.d.mts +235 -0
- package/dist/index.d.ts +235 -0
- package/dist/index.js +755 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +524 -0
- package/dist/index.mjs.map +1 -0
- package/dist/jsx-factory-pFUwL2Dz.d.mts +26 -0
- package/dist/jsx-factory-pFUwL2Dz.d.ts +26 -0
- package/dist/jsx-pFUwL2Dz.d.mts +26 -0
- package/dist/jsx-pFUwL2Dz.d.ts +26 -0
- package/dist/jsx-runtime-pFUwL2Dz.d.mts +26 -0
- package/dist/jsx-runtime-pFUwL2Dz.d.ts +26 -0
- package/dist/jsx-runtime.d.mts +1 -0
- package/dist/jsx-runtime.d.ts +1 -0
- package/dist/jsx-runtime.js +248 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/jsx-runtime.mjs +10 -0
- package/dist/jsx-runtime.mjs.map +1 -0
- package/dist/jsx.d.mts +66 -0
- package/dist/jsx.d.ts +66 -0
- package/dist/jsx.js +224 -0
- package/dist/jsx.js.map +1 -0
- package/dist/jsx.mjs +8 -0
- package/dist/jsx.mjs.map +1 -0
- package/package.json +49 -0
- package/src/auto-register.ts +149 -0
- package/src/index.ts +17 -0
- package/src/jsx-factory.ts +222 -0
- package/src/jsx-runtime.ts +6 -0
- package/src/jsx.ts +90 -0
- package/src/reactive-component.ts +171 -0
- package/src/styles/style-manager.ts +54 -0
- package/src/utils/logger.ts +69 -0
- package/src/utils/reactive.ts +214 -0
- package/src/utils/svg-utils.ts +184 -0
- package/src/web-component.ts +250 -0
- package/types/css-inline.d.ts +4 -0
- package/types/index.d.ts +32 -0
- package/types/jsx-runtime.d.ts +2 -0
- package/types/jsx.d.ts +28 -0
- package/types/wsx-types.d.ts +43 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,755 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
Fragment: () => Fragment,
|
|
24
|
+
ReactiveDebug: () => ReactiveDebug,
|
|
25
|
+
ReactiveWebComponent: () => ReactiveWebComponent,
|
|
26
|
+
StyleManager: () => StyleManager,
|
|
27
|
+
WSXLogger: () => WSXLogger,
|
|
28
|
+
WebComponent: () => WebComponent,
|
|
29
|
+
autoRegister: () => autoRegister,
|
|
30
|
+
createLogger: () => createLogger,
|
|
31
|
+
createReactiveComponent: () => createReactiveComponent,
|
|
32
|
+
createState: () => createState,
|
|
33
|
+
h: () => h,
|
|
34
|
+
jsx: () => h,
|
|
35
|
+
jsxs: () => h,
|
|
36
|
+
logger: () => logger,
|
|
37
|
+
makeReactive: () => makeReactive,
|
|
38
|
+
reactive: () => reactive,
|
|
39
|
+
registerComponent: () => registerComponent
|
|
40
|
+
});
|
|
41
|
+
module.exports = __toCommonJS(index_exports);
|
|
42
|
+
|
|
43
|
+
// src/utils/svg-utils.ts
|
|
44
|
+
var SVG_NAMESPACE = "http://www.w3.org/2000/svg";
|
|
45
|
+
var SVG_ONLY_ELEMENTS = /* @__PURE__ */ new Set([
|
|
46
|
+
// 结构元素 (Structural elements)
|
|
47
|
+
"svg",
|
|
48
|
+
"defs",
|
|
49
|
+
"g",
|
|
50
|
+
"symbol",
|
|
51
|
+
"use",
|
|
52
|
+
// 图形元素 (Graphics elements)
|
|
53
|
+
"circle",
|
|
54
|
+
"ellipse",
|
|
55
|
+
"line",
|
|
56
|
+
"path",
|
|
57
|
+
"polygon",
|
|
58
|
+
"polyline",
|
|
59
|
+
"rect",
|
|
60
|
+
// 文本元素 (Text elements)
|
|
61
|
+
"textPath",
|
|
62
|
+
"tspan",
|
|
63
|
+
// 渐变和模式 (Gradients and patterns)
|
|
64
|
+
"linearGradient",
|
|
65
|
+
"radialGradient",
|
|
66
|
+
"stop",
|
|
67
|
+
"pattern",
|
|
68
|
+
// 滤镜 (Filter elements)
|
|
69
|
+
"filter",
|
|
70
|
+
"feBlend",
|
|
71
|
+
"feColorMatrix",
|
|
72
|
+
"feComponentTransfer",
|
|
73
|
+
"feComposite",
|
|
74
|
+
"feConvolveMatrix",
|
|
75
|
+
"feDiffuseLighting",
|
|
76
|
+
"feDisplacementMap",
|
|
77
|
+
"feDistantLight",
|
|
78
|
+
"feDropShadow",
|
|
79
|
+
"feFlood",
|
|
80
|
+
"feFuncA",
|
|
81
|
+
"feFuncB",
|
|
82
|
+
"feFuncG",
|
|
83
|
+
"feFuncR",
|
|
84
|
+
"feGaussianBlur",
|
|
85
|
+
"feImage",
|
|
86
|
+
"feMerge",
|
|
87
|
+
"feMergeNode",
|
|
88
|
+
"feMorphology",
|
|
89
|
+
"feOffset",
|
|
90
|
+
"fePointLight",
|
|
91
|
+
"feSpecularLighting",
|
|
92
|
+
"feSpotLight",
|
|
93
|
+
"feTile",
|
|
94
|
+
"feTurbulence",
|
|
95
|
+
// 动画元素 (Animation elements)
|
|
96
|
+
"animate",
|
|
97
|
+
"animateMotion",
|
|
98
|
+
"animateTransform",
|
|
99
|
+
"set",
|
|
100
|
+
// 其他元素 (Other elements)
|
|
101
|
+
"clipPath",
|
|
102
|
+
"foreignObject",
|
|
103
|
+
"marker",
|
|
104
|
+
"mask",
|
|
105
|
+
"metadata",
|
|
106
|
+
"switch",
|
|
107
|
+
"desc"
|
|
108
|
+
]);
|
|
109
|
+
var DUAL_ELEMENTS = /* @__PURE__ */ new Set(["image", "style", "title", "text"]);
|
|
110
|
+
var FORCE_HTML_ELEMENTS = /* @__PURE__ */ new Set(["a"]);
|
|
111
|
+
var SVG_ELEMENTS = /* @__PURE__ */ new Set([
|
|
112
|
+
...SVG_ONLY_ELEMENTS,
|
|
113
|
+
...DUAL_ELEMENTS,
|
|
114
|
+
...FORCE_HTML_ELEMENTS
|
|
115
|
+
]);
|
|
116
|
+
var svgContext = false;
|
|
117
|
+
function isSVGOnlyElement(tagName) {
|
|
118
|
+
return SVG_ONLY_ELEMENTS.has(tagName);
|
|
119
|
+
}
|
|
120
|
+
function isDualElement(tagName) {
|
|
121
|
+
return DUAL_ELEMENTS.has(tagName);
|
|
122
|
+
}
|
|
123
|
+
function isForceHTMLElement(tagName) {
|
|
124
|
+
return FORCE_HTML_ELEMENTS.has(tagName);
|
|
125
|
+
}
|
|
126
|
+
function setSVGContext(inSVG) {
|
|
127
|
+
svgContext = inSVG;
|
|
128
|
+
}
|
|
129
|
+
function createElement(tagName) {
|
|
130
|
+
if (isForceHTMLElement(tagName)) {
|
|
131
|
+
return document.createElement(tagName);
|
|
132
|
+
}
|
|
133
|
+
if (isSVGOnlyElement(tagName)) {
|
|
134
|
+
setSVGContext(true);
|
|
135
|
+
return document.createElementNS(SVG_NAMESPACE, tagName);
|
|
136
|
+
}
|
|
137
|
+
if (isDualElement(tagName)) {
|
|
138
|
+
if (svgContext) {
|
|
139
|
+
return document.createElementNS(SVG_NAMESPACE, tagName);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return document.createElement(tagName);
|
|
143
|
+
}
|
|
144
|
+
function shouldUseSVGNamespace(tagName) {
|
|
145
|
+
return isSVGOnlyElement(tagName) || isDualElement(tagName) && svgContext;
|
|
146
|
+
}
|
|
147
|
+
var SVG_ATTRIBUTE_MAP = /* @__PURE__ */ new Map([
|
|
148
|
+
["className", "class"],
|
|
149
|
+
["htmlFor", "for"]
|
|
150
|
+
]);
|
|
151
|
+
function getSVGAttributeName(attributeName) {
|
|
152
|
+
return SVG_ATTRIBUTE_MAP.get(attributeName) || attributeName;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// src/jsx-factory.ts
|
|
156
|
+
function h(tag, props = {}, ...children) {
|
|
157
|
+
if (typeof tag === "function") {
|
|
158
|
+
return tag(props, children);
|
|
159
|
+
}
|
|
160
|
+
const element = createElement(tag);
|
|
161
|
+
if (props) {
|
|
162
|
+
const isSVG = shouldUseSVGNamespace(tag);
|
|
163
|
+
Object.entries(props).forEach(([key, value]) => {
|
|
164
|
+
if (value === null || value === void 0 || value === false) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (key === "ref" && typeof value === "function") {
|
|
168
|
+
value(element);
|
|
169
|
+
} else if (key === "className" || key === "class") {
|
|
170
|
+
if (isSVG) {
|
|
171
|
+
element.setAttribute("class", value);
|
|
172
|
+
} else {
|
|
173
|
+
element.className = value;
|
|
174
|
+
}
|
|
175
|
+
} else if (key === "style" && typeof value === "string") {
|
|
176
|
+
element.setAttribute("style", value);
|
|
177
|
+
} else if (key.startsWith("on") && typeof value === "function") {
|
|
178
|
+
const eventName = key.slice(2).toLowerCase();
|
|
179
|
+
element.addEventListener(eventName, value);
|
|
180
|
+
} else if (typeof value === "boolean") {
|
|
181
|
+
if (value) {
|
|
182
|
+
element.setAttribute(key, "");
|
|
183
|
+
}
|
|
184
|
+
} else {
|
|
185
|
+
const attributeName = isSVG ? getSVGAttributeName(key) : key;
|
|
186
|
+
element.setAttribute(attributeName, String(value));
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
const flatChildren = flattenChildren(children);
|
|
191
|
+
flatChildren.forEach((child) => {
|
|
192
|
+
if (child === null || child === void 0 || child === false) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
if (typeof child === "string" || typeof child === "number") {
|
|
196
|
+
element.appendChild(document.createTextNode(String(child)));
|
|
197
|
+
} else if (child instanceof HTMLElement || child instanceof SVGElement) {
|
|
198
|
+
element.appendChild(child);
|
|
199
|
+
} else if (child instanceof DocumentFragment) {
|
|
200
|
+
element.appendChild(child);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
return element;
|
|
204
|
+
}
|
|
205
|
+
function flattenChildren(children) {
|
|
206
|
+
const result = [];
|
|
207
|
+
for (const child of children) {
|
|
208
|
+
if (child === null || child === void 0 || child === false) {
|
|
209
|
+
continue;
|
|
210
|
+
} else if (Array.isArray(child)) {
|
|
211
|
+
result.push(...flattenChildren(child));
|
|
212
|
+
} else {
|
|
213
|
+
result.push(child);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return result;
|
|
217
|
+
}
|
|
218
|
+
function Fragment(_props, children) {
|
|
219
|
+
const fragment = document.createDocumentFragment();
|
|
220
|
+
const flatChildren = flattenChildren(children);
|
|
221
|
+
flatChildren.forEach((child) => {
|
|
222
|
+
if (child === null || child === void 0 || child === false) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
if (typeof child === "string" || typeof child === "number") {
|
|
226
|
+
fragment.appendChild(document.createTextNode(String(child)));
|
|
227
|
+
} else if (child instanceof HTMLElement || child instanceof SVGElement) {
|
|
228
|
+
fragment.appendChild(child);
|
|
229
|
+
} else if (child instanceof DocumentFragment) {
|
|
230
|
+
fragment.appendChild(child);
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
return fragment;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// src/styles/style-manager.ts
|
|
237
|
+
var StyleManager = class {
|
|
238
|
+
/**
|
|
239
|
+
* Create or get a cached CSSStyleSheet for a component
|
|
240
|
+
*/
|
|
241
|
+
static getStyleSheet(componentName, cssText) {
|
|
242
|
+
if (this.styleSheets.has(componentName)) {
|
|
243
|
+
return this.styleSheets.get(componentName);
|
|
244
|
+
}
|
|
245
|
+
if ("adoptedStyleSheets" in Document.prototype && "CSSStyleSheet" in window) {
|
|
246
|
+
const styleSheet = new CSSStyleSheet();
|
|
247
|
+
styleSheet.replaceSync(cssText);
|
|
248
|
+
this.styleSheets.set(componentName, styleSheet);
|
|
249
|
+
return styleSheet;
|
|
250
|
+
} else {
|
|
251
|
+
throw new Error("Constructable StyleSheets not supported. Use fallback method.");
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Apply styles to a shadow root using constructable stylesheets
|
|
256
|
+
*/
|
|
257
|
+
static applyStyles(shadowRoot, componentName, cssText) {
|
|
258
|
+
try {
|
|
259
|
+
const styleSheet = this.getStyleSheet(componentName, cssText);
|
|
260
|
+
shadowRoot.adoptedStyleSheets = [styleSheet];
|
|
261
|
+
} catch {
|
|
262
|
+
this.applyStylesFallback(shadowRoot, cssText);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Fallback method for browsers that don't support constructable stylesheets
|
|
267
|
+
*/
|
|
268
|
+
static applyStylesFallback(shadowRoot, cssText) {
|
|
269
|
+
const style = document.createElement("style");
|
|
270
|
+
style.textContent = cssText;
|
|
271
|
+
shadowRoot.appendChild(style);
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
StyleManager.styleSheets = /* @__PURE__ */ new Map();
|
|
275
|
+
|
|
276
|
+
// src/web-component.ts
|
|
277
|
+
var WebComponent = class extends HTMLElement {
|
|
278
|
+
constructor(config = {}) {
|
|
279
|
+
super();
|
|
280
|
+
this.connected = false;
|
|
281
|
+
this.config = config;
|
|
282
|
+
this.attachShadow({ mode: "open" });
|
|
283
|
+
if (config.styles) {
|
|
284
|
+
const styleName = config.styleName || this.constructor.name;
|
|
285
|
+
StyleManager.applyStyles(this.shadowRoot, styleName, config.styles);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* 子类应该重写这个方法来定义观察的属性
|
|
290
|
+
* @returns 要观察的属性名数组
|
|
291
|
+
*/
|
|
292
|
+
static get observedAttributes() {
|
|
293
|
+
return [];
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Web Component生命周期:连接到DOM
|
|
297
|
+
*/
|
|
298
|
+
connectedCallback() {
|
|
299
|
+
this.connected = true;
|
|
300
|
+
try {
|
|
301
|
+
const content = this.render();
|
|
302
|
+
this.shadowRoot.appendChild(content);
|
|
303
|
+
this.onConnected?.();
|
|
304
|
+
} catch (error) {
|
|
305
|
+
console.error(`[${this.constructor.name}] Error in connectedCallback:`, error);
|
|
306
|
+
this.renderError(error);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Web Component生命周期:从DOM断开
|
|
311
|
+
*/
|
|
312
|
+
disconnectedCallback() {
|
|
313
|
+
this.onDisconnected?.();
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Web Component生命周期:属性变化
|
|
317
|
+
*/
|
|
318
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
319
|
+
this.onAttributeChanged?.(name, oldValue, newValue);
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* 查找Shadow DOM内的元素
|
|
323
|
+
*
|
|
324
|
+
* @param selector - CSS选择器
|
|
325
|
+
* @returns 元素或null
|
|
326
|
+
*/
|
|
327
|
+
querySelector(selector) {
|
|
328
|
+
return this.shadowRoot.querySelector(selector);
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* 查找Shadow DOM内的所有匹配元素
|
|
332
|
+
*
|
|
333
|
+
* @param selector - CSS选择器
|
|
334
|
+
* @returns 元素列表
|
|
335
|
+
*/
|
|
336
|
+
querySelectorAll(selector) {
|
|
337
|
+
return this.shadowRoot.querySelectorAll(selector);
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* 重新渲染组件
|
|
341
|
+
*/
|
|
342
|
+
rerender() {
|
|
343
|
+
if (!this.connected) {
|
|
344
|
+
console.warn(
|
|
345
|
+
`[${this.constructor.name}] Component is not connected, skipping rerender.`
|
|
346
|
+
);
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
const adoptedStyleSheets = this.shadowRoot.adoptedStyleSheets || [];
|
|
350
|
+
this.shadowRoot.innerHTML = "";
|
|
351
|
+
if (this.shadowRoot.adoptedStyleSheets) {
|
|
352
|
+
this.shadowRoot.adoptedStyleSheets = adoptedStyleSheets;
|
|
353
|
+
}
|
|
354
|
+
if (adoptedStyleSheets.length === 0 && this.config.styles) {
|
|
355
|
+
const styleName = this.config.styleName || this.constructor.name;
|
|
356
|
+
StyleManager.applyStyles(this.shadowRoot, styleName, this.config.styles);
|
|
357
|
+
}
|
|
358
|
+
try {
|
|
359
|
+
const content = this.render();
|
|
360
|
+
this.shadowRoot.appendChild(content);
|
|
361
|
+
} catch (error) {
|
|
362
|
+
console.error(`[${this.constructor.name}] Error in rerender:`, error);
|
|
363
|
+
this.renderError(error);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* 渲染错误信息
|
|
368
|
+
*
|
|
369
|
+
* @param error - 错误对象
|
|
370
|
+
*/
|
|
371
|
+
renderError(error) {
|
|
372
|
+
this.shadowRoot.innerHTML = "";
|
|
373
|
+
const errorElement = h(
|
|
374
|
+
"div",
|
|
375
|
+
{
|
|
376
|
+
style: "color: red; padding: 10px; border: 1px solid red; background: #ffe6e6; font-family: monospace;"
|
|
377
|
+
},
|
|
378
|
+
[
|
|
379
|
+
h("strong", {}, `[${this.constructor.name}] Component Error:`),
|
|
380
|
+
h("pre", { style: "margin: 10px 0; white-space: pre-wrap;" }, String(error))
|
|
381
|
+
]
|
|
382
|
+
);
|
|
383
|
+
this.shadowRoot.appendChild(errorElement);
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* 获取配置值
|
|
387
|
+
*
|
|
388
|
+
* @param key - 配置键
|
|
389
|
+
* @param defaultValue - 默认值
|
|
390
|
+
* @returns 配置值
|
|
391
|
+
*/
|
|
392
|
+
getConfig(key, defaultValue) {
|
|
393
|
+
return this.config[key] ?? defaultValue;
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* 设置配置值
|
|
397
|
+
*
|
|
398
|
+
* @param key - 配置键
|
|
399
|
+
* @param value - 配置值
|
|
400
|
+
*/
|
|
401
|
+
setConfig(key, value) {
|
|
402
|
+
this.config[key] = value;
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* 获取属性值
|
|
406
|
+
*
|
|
407
|
+
* @param name - 属性名
|
|
408
|
+
* @param defaultValue - 默认值
|
|
409
|
+
* @returns 属性值
|
|
410
|
+
*/
|
|
411
|
+
getAttr(name, defaultValue = "") {
|
|
412
|
+
return this.getAttribute(name) || defaultValue;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* 设置属性值
|
|
416
|
+
*
|
|
417
|
+
* @param name - 属性名
|
|
418
|
+
* @param value - 属性值
|
|
419
|
+
*/
|
|
420
|
+
setAttr(name, value) {
|
|
421
|
+
this.setAttribute(name, value);
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* 移除属性
|
|
425
|
+
*
|
|
426
|
+
* @param name - 属性名
|
|
427
|
+
*/
|
|
428
|
+
removeAttr(name) {
|
|
429
|
+
this.removeAttribute(name);
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* 检查是否有属性
|
|
433
|
+
*
|
|
434
|
+
* @param name - 属性名
|
|
435
|
+
* @returns 是否存在
|
|
436
|
+
*/
|
|
437
|
+
hasAttr(name) {
|
|
438
|
+
return this.hasAttribute(name);
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
// src/auto-register.ts
|
|
443
|
+
function autoRegister(options = {}) {
|
|
444
|
+
return function(constructor) {
|
|
445
|
+
const tagName = options.tagName || deriveTagName(constructor.name, options.prefix);
|
|
446
|
+
if (!customElements.get(tagName)) {
|
|
447
|
+
customElements.define(tagName, constructor);
|
|
448
|
+
}
|
|
449
|
+
return constructor;
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
function registerComponent(constructor, options = {}) {
|
|
453
|
+
const tagName = options.tagName || deriveTagName(constructor.name, options.prefix);
|
|
454
|
+
if (!customElements.get(tagName)) {
|
|
455
|
+
customElements.define(tagName, constructor);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
function deriveTagName(className, prefix) {
|
|
459
|
+
let kebabCase = className.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
460
|
+
if (!kebabCase.includes("-")) {
|
|
461
|
+
kebabCase = `${kebabCase}-component`;
|
|
462
|
+
}
|
|
463
|
+
return prefix ? `${prefix}${kebabCase}` : kebabCase;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// src/utils/logger.ts
|
|
467
|
+
var WSXLogger = class {
|
|
468
|
+
constructor(prefix = "[WSX]", enabled = true, level = "info") {
|
|
469
|
+
this.prefix = prefix;
|
|
470
|
+
this.enabled = enabled;
|
|
471
|
+
this.level = level;
|
|
472
|
+
}
|
|
473
|
+
shouldLog(level) {
|
|
474
|
+
if (!this.enabled) return false;
|
|
475
|
+
const levels = ["debug", "info", "warn", "error"];
|
|
476
|
+
const currentLevelIndex = levels.indexOf(this.level);
|
|
477
|
+
const messageLevelIndex = levels.indexOf(level);
|
|
478
|
+
return messageLevelIndex >= currentLevelIndex;
|
|
479
|
+
}
|
|
480
|
+
debug(message, ...args) {
|
|
481
|
+
if (this.shouldLog("debug")) {
|
|
482
|
+
console.debug(`${this.prefix} ${message}`, ...args);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
info(message, ...args) {
|
|
486
|
+
if (this.shouldLog("info")) {
|
|
487
|
+
console.info(`${this.prefix} ${message}`, ...args);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
warn(message, ...args) {
|
|
491
|
+
if (this.shouldLog("warn")) {
|
|
492
|
+
console.warn(`${this.prefix} ${message}`, ...args);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
error(message, ...args) {
|
|
496
|
+
if (this.shouldLog("error")) {
|
|
497
|
+
console.error(`${this.prefix} ${message}`, ...args);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
};
|
|
501
|
+
var logger = new WSXLogger();
|
|
502
|
+
function createLogger(componentName) {
|
|
503
|
+
return new WSXLogger(`[WSX:${componentName}]`);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// src/utils/reactive.ts
|
|
507
|
+
var logger2 = createLogger("ReactiveSystem");
|
|
508
|
+
var UpdateScheduler = class {
|
|
509
|
+
constructor() {
|
|
510
|
+
this.pendingCallbacks = /* @__PURE__ */ new Set();
|
|
511
|
+
this.isScheduled = false;
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* 调度一个更新回调
|
|
515
|
+
*/
|
|
516
|
+
schedule(callback) {
|
|
517
|
+
this.pendingCallbacks.add(callback);
|
|
518
|
+
if (!this.isScheduled) {
|
|
519
|
+
this.isScheduled = true;
|
|
520
|
+
queueMicrotask(() => {
|
|
521
|
+
this.flush();
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* 执行所有待处理的回调
|
|
527
|
+
*/
|
|
528
|
+
flush() {
|
|
529
|
+
const callbacks = Array.from(this.pendingCallbacks);
|
|
530
|
+
this.pendingCallbacks.clear();
|
|
531
|
+
this.isScheduled = false;
|
|
532
|
+
callbacks.forEach((callback) => {
|
|
533
|
+
try {
|
|
534
|
+
callback();
|
|
535
|
+
} catch (error) {
|
|
536
|
+
console.error("[WSX Reactive] Error in callback:", error);
|
|
537
|
+
}
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
};
|
|
541
|
+
var scheduler = new UpdateScheduler();
|
|
542
|
+
function reactive(obj, onChange) {
|
|
543
|
+
return new Proxy(obj, {
|
|
544
|
+
set(target, key, value) {
|
|
545
|
+
const oldValue = target[key];
|
|
546
|
+
if (oldValue !== value) {
|
|
547
|
+
target[key] = value;
|
|
548
|
+
scheduler.schedule(onChange);
|
|
549
|
+
}
|
|
550
|
+
return true;
|
|
551
|
+
},
|
|
552
|
+
get(target, key) {
|
|
553
|
+
return target[key];
|
|
554
|
+
},
|
|
555
|
+
has(target, key) {
|
|
556
|
+
return key in target;
|
|
557
|
+
},
|
|
558
|
+
ownKeys(target) {
|
|
559
|
+
return Reflect.ownKeys(target);
|
|
560
|
+
},
|
|
561
|
+
getOwnPropertyDescriptor(target, key) {
|
|
562
|
+
return Reflect.getOwnPropertyDescriptor(target, key);
|
|
563
|
+
}
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
function createState(initialValue, onChange) {
|
|
567
|
+
let currentValue = initialValue;
|
|
568
|
+
const getter = () => currentValue;
|
|
569
|
+
const setter = (value) => {
|
|
570
|
+
const newValue = typeof value === "function" ? value(currentValue) : value;
|
|
571
|
+
if (currentValue !== newValue) {
|
|
572
|
+
currentValue = newValue;
|
|
573
|
+
scheduler.schedule(onChange);
|
|
574
|
+
}
|
|
575
|
+
};
|
|
576
|
+
return [getter, setter];
|
|
577
|
+
}
|
|
578
|
+
var ReactiveDebug = {
|
|
579
|
+
/**
|
|
580
|
+
* 启用调试模式
|
|
581
|
+
*/
|
|
582
|
+
enable() {
|
|
583
|
+
if (typeof window !== "undefined") {
|
|
584
|
+
window.__WSX_REACTIVE_DEBUG__ = true;
|
|
585
|
+
}
|
|
586
|
+
},
|
|
587
|
+
/**
|
|
588
|
+
* 禁用调试模式
|
|
589
|
+
*/
|
|
590
|
+
disable() {
|
|
591
|
+
if (typeof window !== "undefined") {
|
|
592
|
+
window.__WSX_REACTIVE_DEBUG__ = false;
|
|
593
|
+
}
|
|
594
|
+
},
|
|
595
|
+
/**
|
|
596
|
+
* 检查是否启用调试模式
|
|
597
|
+
*/
|
|
598
|
+
isEnabled() {
|
|
599
|
+
return typeof window !== "undefined" && window.__WSX_REACTIVE_DEBUG__ === true;
|
|
600
|
+
},
|
|
601
|
+
/**
|
|
602
|
+
* 调试日志
|
|
603
|
+
*/
|
|
604
|
+
log(message, ...args) {
|
|
605
|
+
if (this.isEnabled()) {
|
|
606
|
+
logger2.info(`[WSX Reactive] ${message}`, ...args);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
};
|
|
610
|
+
function reactiveWithDebug(obj, onChange, debugName) {
|
|
611
|
+
const name = debugName || obj.constructor.name || "Unknown";
|
|
612
|
+
return new Proxy(obj, {
|
|
613
|
+
set(target, key, value) {
|
|
614
|
+
const oldValue = target[key];
|
|
615
|
+
if (oldValue !== value) {
|
|
616
|
+
ReactiveDebug.log(`State change in ${name}:`, {
|
|
617
|
+
key: String(key),
|
|
618
|
+
oldValue,
|
|
619
|
+
newValue: value
|
|
620
|
+
});
|
|
621
|
+
target[key] = value;
|
|
622
|
+
scheduler.schedule(onChange);
|
|
623
|
+
}
|
|
624
|
+
return true;
|
|
625
|
+
},
|
|
626
|
+
get(target, key) {
|
|
627
|
+
return target[key];
|
|
628
|
+
}
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// src/reactive-component.ts
|
|
633
|
+
var ReactiveWebComponent = class extends WebComponent {
|
|
634
|
+
constructor(config = {}) {
|
|
635
|
+
super(config);
|
|
636
|
+
this._isDebugEnabled = false;
|
|
637
|
+
this._reactiveStates = /* @__PURE__ */ new Map();
|
|
638
|
+
this._isDebugEnabled = config.debug ?? false;
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* 创建响应式对象
|
|
642
|
+
*
|
|
643
|
+
* @param obj 要变为响应式的对象
|
|
644
|
+
* @param debugName 调试名称(可选)
|
|
645
|
+
* @returns 响应式代理对象
|
|
646
|
+
*/
|
|
647
|
+
reactive(obj, debugName) {
|
|
648
|
+
const reactiveFn = this._isDebugEnabled ? reactiveWithDebug : reactive;
|
|
649
|
+
const name = debugName || `${this.constructor.name}.reactive`;
|
|
650
|
+
return this._isDebugEnabled ? reactiveFn(obj, () => this.scheduleRerender(), name) : reactiveFn(obj, () => this.scheduleRerender());
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* 创建响应式状态
|
|
654
|
+
*
|
|
655
|
+
* @param key 状态标识符
|
|
656
|
+
* @param initialValue 初始值
|
|
657
|
+
* @returns [getter, setter] 元组
|
|
658
|
+
*/
|
|
659
|
+
useState(key, initialValue) {
|
|
660
|
+
if (!this._reactiveStates.has(key)) {
|
|
661
|
+
const [getter, setter] = createState(initialValue, () => this.scheduleRerender());
|
|
662
|
+
this._reactiveStates.set(key, { getter, setter });
|
|
663
|
+
}
|
|
664
|
+
const state = this._reactiveStates.get(key);
|
|
665
|
+
return [state.getter, state.setter];
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* 调度重渲染
|
|
669
|
+
* 这个方法被响应式系统调用,开发者通常不需要直接调用
|
|
670
|
+
*/
|
|
671
|
+
scheduleRerender() {
|
|
672
|
+
if (this.connected) {
|
|
673
|
+
this.rerender();
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* 获取所有响应式状态的快照(用于调试)
|
|
678
|
+
*/
|
|
679
|
+
getStateSnapshot() {
|
|
680
|
+
const snapshot = {};
|
|
681
|
+
this._reactiveStates.forEach((state, key) => {
|
|
682
|
+
snapshot[key] = state.getter();
|
|
683
|
+
});
|
|
684
|
+
return snapshot;
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* 清理响应式状态(组件销毁时)
|
|
688
|
+
*/
|
|
689
|
+
cleanupReactiveStates() {
|
|
690
|
+
this._reactiveStates.clear();
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* 重写 disconnectedCallback 以清理状态
|
|
694
|
+
*/
|
|
695
|
+
disconnectedCallback() {
|
|
696
|
+
super.disconnectedCallback();
|
|
697
|
+
this.cleanupReactiveStates();
|
|
698
|
+
}
|
|
699
|
+
/**
|
|
700
|
+
* 启用调试模式
|
|
701
|
+
*/
|
|
702
|
+
enableDebug() {
|
|
703
|
+
this._isDebugEnabled = true;
|
|
704
|
+
}
|
|
705
|
+
/**
|
|
706
|
+
* 禁用调试模式
|
|
707
|
+
*/
|
|
708
|
+
disableDebug() {
|
|
709
|
+
this._isDebugEnabled = false;
|
|
710
|
+
}
|
|
711
|
+
};
|
|
712
|
+
function makeReactive(_debugMode = false) {
|
|
713
|
+
return function(constructor) {
|
|
714
|
+
return class ReactiveComponent extends constructor {
|
|
715
|
+
constructor(...args) {
|
|
716
|
+
super(...args);
|
|
717
|
+
if (!(this instanceof ReactiveWebComponent)) {
|
|
718
|
+
this.reactive = function(obj) {
|
|
719
|
+
return reactive(obj, () => this.rerender());
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
render() {
|
|
724
|
+
throw new Error("render() method must be implemented by subclass");
|
|
725
|
+
}
|
|
726
|
+
};
|
|
727
|
+
};
|
|
728
|
+
}
|
|
729
|
+
function createReactiveComponent(ComponentClass, config) {
|
|
730
|
+
if (ComponentClass.prototype instanceof ReactiveWebComponent) {
|
|
731
|
+
return new ComponentClass(config);
|
|
732
|
+
}
|
|
733
|
+
const ReactiveComponent = makeReactive(config?.debug)(ComponentClass);
|
|
734
|
+
return new ReactiveComponent(config);
|
|
735
|
+
}
|
|
736
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
737
|
+
0 && (module.exports = {
|
|
738
|
+
Fragment,
|
|
739
|
+
ReactiveDebug,
|
|
740
|
+
ReactiveWebComponent,
|
|
741
|
+
StyleManager,
|
|
742
|
+
WSXLogger,
|
|
743
|
+
WebComponent,
|
|
744
|
+
autoRegister,
|
|
745
|
+
createLogger,
|
|
746
|
+
createReactiveComponent,
|
|
747
|
+
createState,
|
|
748
|
+
h,
|
|
749
|
+
jsx,
|
|
750
|
+
jsxs,
|
|
751
|
+
logger,
|
|
752
|
+
makeReactive,
|
|
753
|
+
reactive,
|
|
754
|
+
registerComponent
|
|
755
|
+
});
|