@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/jsx.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export { F as Fragment, h } from './jsx-runtime-pFUwL2Dz.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* JSX 入口点
|
|
5
|
+
* 专门为 jsxImportSource 机制提供 JSX 工厂函数
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
declare global {
|
|
9
|
+
namespace JSX {
|
|
10
|
+
interface IntrinsicElements {
|
|
11
|
+
div: HTMLAttributes<HTMLDivElement>;
|
|
12
|
+
button: HTMLAttributes<HTMLButtonElement>;
|
|
13
|
+
a: HTMLAttributes<HTMLAnchorElement>;
|
|
14
|
+
span: HTMLAttributes<HTMLSpanElement>;
|
|
15
|
+
input: HTMLAttributes<HTMLInputElement>;
|
|
16
|
+
p: HTMLAttributes<HTMLParagraphElement>;
|
|
17
|
+
h1: HTMLAttributes<HTMLHeadingElement>;
|
|
18
|
+
h2: HTMLAttributes<HTMLHeadingElement>;
|
|
19
|
+
h3: HTMLAttributes<HTMLHeadingElement>;
|
|
20
|
+
ul: HTMLAttributes<HTMLUListElement>;
|
|
21
|
+
li: HTMLAttributes<HTMLLIElement>;
|
|
22
|
+
section: HTMLAttributes<HTMLElement>;
|
|
23
|
+
slot: HTMLAttributes<HTMLSlotElement>;
|
|
24
|
+
}
|
|
25
|
+
interface HTMLAttributes<T extends HTMLElement = HTMLElement> {
|
|
26
|
+
className?: string;
|
|
27
|
+
class?: string;
|
|
28
|
+
id?: string;
|
|
29
|
+
style?: string;
|
|
30
|
+
disabled?: boolean;
|
|
31
|
+
title?: string;
|
|
32
|
+
type?: string;
|
|
33
|
+
value?: string;
|
|
34
|
+
placeholder?: string;
|
|
35
|
+
src?: string;
|
|
36
|
+
alt?: string;
|
|
37
|
+
href?: string | null;
|
|
38
|
+
target?: string;
|
|
39
|
+
rel?: string;
|
|
40
|
+
download?: string;
|
|
41
|
+
ref?: (element: T) => void;
|
|
42
|
+
[dataAttr: `data-${string}`]: string;
|
|
43
|
+
onClick?: (event: Event) => void;
|
|
44
|
+
onInput?: (event: Event) => void;
|
|
45
|
+
onChange?: (event: Event) => void;
|
|
46
|
+
onMouseOver?: (event: Event) => void;
|
|
47
|
+
onMouseOut?: (event: Event) => void;
|
|
48
|
+
onFocus?: (event: Event) => void;
|
|
49
|
+
onBlur?: (event: Event) => void;
|
|
50
|
+
onMouseDown?: (event: MouseEvent) => void;
|
|
51
|
+
onKeyDown?: (event: KeyboardEvent) => void;
|
|
52
|
+
[key: string]: unknown;
|
|
53
|
+
}
|
|
54
|
+
type Element = HTMLElement;
|
|
55
|
+
interface ElementClass {
|
|
56
|
+
render(): Element;
|
|
57
|
+
}
|
|
58
|
+
interface ElementAttributesProperty {
|
|
59
|
+
props: object;
|
|
60
|
+
}
|
|
61
|
+
interface ElementChildrenAttribute {
|
|
62
|
+
children: object;
|
|
63
|
+
}
|
|
64
|
+
type LibraryManagedAttributes<_C, P> = P;
|
|
65
|
+
}
|
|
66
|
+
}
|
package/dist/jsx.js
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
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/jsx.ts
|
|
21
|
+
var jsx_exports = {};
|
|
22
|
+
__export(jsx_exports, {
|
|
23
|
+
Fragment: () => Fragment,
|
|
24
|
+
h: () => h
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(jsx_exports);
|
|
27
|
+
|
|
28
|
+
// src/utils/svg-utils.ts
|
|
29
|
+
var SVG_NAMESPACE = "http://www.w3.org/2000/svg";
|
|
30
|
+
var SVG_ONLY_ELEMENTS = /* @__PURE__ */ new Set([
|
|
31
|
+
// 结构元素 (Structural elements)
|
|
32
|
+
"svg",
|
|
33
|
+
"defs",
|
|
34
|
+
"g",
|
|
35
|
+
"symbol",
|
|
36
|
+
"use",
|
|
37
|
+
// 图形元素 (Graphics elements)
|
|
38
|
+
"circle",
|
|
39
|
+
"ellipse",
|
|
40
|
+
"line",
|
|
41
|
+
"path",
|
|
42
|
+
"polygon",
|
|
43
|
+
"polyline",
|
|
44
|
+
"rect",
|
|
45
|
+
// 文本元素 (Text elements)
|
|
46
|
+
"textPath",
|
|
47
|
+
"tspan",
|
|
48
|
+
// 渐变和模式 (Gradients and patterns)
|
|
49
|
+
"linearGradient",
|
|
50
|
+
"radialGradient",
|
|
51
|
+
"stop",
|
|
52
|
+
"pattern",
|
|
53
|
+
// 滤镜 (Filter elements)
|
|
54
|
+
"filter",
|
|
55
|
+
"feBlend",
|
|
56
|
+
"feColorMatrix",
|
|
57
|
+
"feComponentTransfer",
|
|
58
|
+
"feComposite",
|
|
59
|
+
"feConvolveMatrix",
|
|
60
|
+
"feDiffuseLighting",
|
|
61
|
+
"feDisplacementMap",
|
|
62
|
+
"feDistantLight",
|
|
63
|
+
"feDropShadow",
|
|
64
|
+
"feFlood",
|
|
65
|
+
"feFuncA",
|
|
66
|
+
"feFuncB",
|
|
67
|
+
"feFuncG",
|
|
68
|
+
"feFuncR",
|
|
69
|
+
"feGaussianBlur",
|
|
70
|
+
"feImage",
|
|
71
|
+
"feMerge",
|
|
72
|
+
"feMergeNode",
|
|
73
|
+
"feMorphology",
|
|
74
|
+
"feOffset",
|
|
75
|
+
"fePointLight",
|
|
76
|
+
"feSpecularLighting",
|
|
77
|
+
"feSpotLight",
|
|
78
|
+
"feTile",
|
|
79
|
+
"feTurbulence",
|
|
80
|
+
// 动画元素 (Animation elements)
|
|
81
|
+
"animate",
|
|
82
|
+
"animateMotion",
|
|
83
|
+
"animateTransform",
|
|
84
|
+
"set",
|
|
85
|
+
// 其他元素 (Other elements)
|
|
86
|
+
"clipPath",
|
|
87
|
+
"foreignObject",
|
|
88
|
+
"marker",
|
|
89
|
+
"mask",
|
|
90
|
+
"metadata",
|
|
91
|
+
"switch",
|
|
92
|
+
"desc"
|
|
93
|
+
]);
|
|
94
|
+
var DUAL_ELEMENTS = /* @__PURE__ */ new Set(["image", "style", "title", "text"]);
|
|
95
|
+
var FORCE_HTML_ELEMENTS = /* @__PURE__ */ new Set(["a"]);
|
|
96
|
+
var SVG_ELEMENTS = /* @__PURE__ */ new Set([
|
|
97
|
+
...SVG_ONLY_ELEMENTS,
|
|
98
|
+
...DUAL_ELEMENTS,
|
|
99
|
+
...FORCE_HTML_ELEMENTS
|
|
100
|
+
]);
|
|
101
|
+
var svgContext = false;
|
|
102
|
+
function isSVGOnlyElement(tagName) {
|
|
103
|
+
return SVG_ONLY_ELEMENTS.has(tagName);
|
|
104
|
+
}
|
|
105
|
+
function isDualElement(tagName) {
|
|
106
|
+
return DUAL_ELEMENTS.has(tagName);
|
|
107
|
+
}
|
|
108
|
+
function isForceHTMLElement(tagName) {
|
|
109
|
+
return FORCE_HTML_ELEMENTS.has(tagName);
|
|
110
|
+
}
|
|
111
|
+
function setSVGContext(inSVG) {
|
|
112
|
+
svgContext = inSVG;
|
|
113
|
+
}
|
|
114
|
+
function createElement(tagName) {
|
|
115
|
+
if (isForceHTMLElement(tagName)) {
|
|
116
|
+
return document.createElement(tagName);
|
|
117
|
+
}
|
|
118
|
+
if (isSVGOnlyElement(tagName)) {
|
|
119
|
+
setSVGContext(true);
|
|
120
|
+
return document.createElementNS(SVG_NAMESPACE, tagName);
|
|
121
|
+
}
|
|
122
|
+
if (isDualElement(tagName)) {
|
|
123
|
+
if (svgContext) {
|
|
124
|
+
return document.createElementNS(SVG_NAMESPACE, tagName);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return document.createElement(tagName);
|
|
128
|
+
}
|
|
129
|
+
function shouldUseSVGNamespace(tagName) {
|
|
130
|
+
return isSVGOnlyElement(tagName) || isDualElement(tagName) && svgContext;
|
|
131
|
+
}
|
|
132
|
+
var SVG_ATTRIBUTE_MAP = /* @__PURE__ */ new Map([
|
|
133
|
+
["className", "class"],
|
|
134
|
+
["htmlFor", "for"]
|
|
135
|
+
]);
|
|
136
|
+
function getSVGAttributeName(attributeName) {
|
|
137
|
+
return SVG_ATTRIBUTE_MAP.get(attributeName) || attributeName;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// src/jsx-factory.ts
|
|
141
|
+
function h(tag, props = {}, ...children) {
|
|
142
|
+
if (typeof tag === "function") {
|
|
143
|
+
return tag(props, children);
|
|
144
|
+
}
|
|
145
|
+
const element = createElement(tag);
|
|
146
|
+
if (props) {
|
|
147
|
+
const isSVG = shouldUseSVGNamespace(tag);
|
|
148
|
+
Object.entries(props).forEach(([key, value]) => {
|
|
149
|
+
if (value === null || value === void 0 || value === false) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (key === "ref" && typeof value === "function") {
|
|
153
|
+
value(element);
|
|
154
|
+
} else if (key === "className" || key === "class") {
|
|
155
|
+
if (isSVG) {
|
|
156
|
+
element.setAttribute("class", value);
|
|
157
|
+
} else {
|
|
158
|
+
element.className = value;
|
|
159
|
+
}
|
|
160
|
+
} else if (key === "style" && typeof value === "string") {
|
|
161
|
+
element.setAttribute("style", value);
|
|
162
|
+
} else if (key.startsWith("on") && typeof value === "function") {
|
|
163
|
+
const eventName = key.slice(2).toLowerCase();
|
|
164
|
+
element.addEventListener(eventName, value);
|
|
165
|
+
} else if (typeof value === "boolean") {
|
|
166
|
+
if (value) {
|
|
167
|
+
element.setAttribute(key, "");
|
|
168
|
+
}
|
|
169
|
+
} else {
|
|
170
|
+
const attributeName = isSVG ? getSVGAttributeName(key) : key;
|
|
171
|
+
element.setAttribute(attributeName, String(value));
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
const flatChildren = flattenChildren(children);
|
|
176
|
+
flatChildren.forEach((child) => {
|
|
177
|
+
if (child === null || child === void 0 || child === false) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (typeof child === "string" || typeof child === "number") {
|
|
181
|
+
element.appendChild(document.createTextNode(String(child)));
|
|
182
|
+
} else if (child instanceof HTMLElement || child instanceof SVGElement) {
|
|
183
|
+
element.appendChild(child);
|
|
184
|
+
} else if (child instanceof DocumentFragment) {
|
|
185
|
+
element.appendChild(child);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
return element;
|
|
189
|
+
}
|
|
190
|
+
function flattenChildren(children) {
|
|
191
|
+
const result = [];
|
|
192
|
+
for (const child of children) {
|
|
193
|
+
if (child === null || child === void 0 || child === false) {
|
|
194
|
+
continue;
|
|
195
|
+
} else if (Array.isArray(child)) {
|
|
196
|
+
result.push(...flattenChildren(child));
|
|
197
|
+
} else {
|
|
198
|
+
result.push(child);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return result;
|
|
202
|
+
}
|
|
203
|
+
function Fragment(_props, children) {
|
|
204
|
+
const fragment = document.createDocumentFragment();
|
|
205
|
+
const flatChildren = flattenChildren(children);
|
|
206
|
+
flatChildren.forEach((child) => {
|
|
207
|
+
if (child === null || child === void 0 || child === false) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
if (typeof child === "string" || typeof child === "number") {
|
|
211
|
+
fragment.appendChild(document.createTextNode(String(child)));
|
|
212
|
+
} else if (child instanceof HTMLElement || child instanceof SVGElement) {
|
|
213
|
+
fragment.appendChild(child);
|
|
214
|
+
} else if (child instanceof DocumentFragment) {
|
|
215
|
+
fragment.appendChild(child);
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
return fragment;
|
|
219
|
+
}
|
|
220
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
221
|
+
0 && (module.exports = {
|
|
222
|
+
Fragment,
|
|
223
|
+
h
|
|
224
|
+
});
|
package/dist/jsx.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/jsx.ts","../src/utils/svg-utils.ts","../src/jsx-factory.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-namespace */\n/**\n * JSX 入口点\n * 专门为 jsxImportSource 机制提供 JSX 工厂函数\n */\n\n// 导入 JSX 工厂函数\nimport { h, Fragment } from \"./jsx-factory\";\n\n// 全局 JSX 命名空间声明 - 这是 TypeScript jsxImportSource 机制的关键\ndeclare global {\n namespace JSX {\n interface IntrinsicElements {\n // 标准HTML元素\n div: HTMLAttributes<HTMLDivElement>;\n button: HTMLAttributes<HTMLButtonElement>;\n a: HTMLAttributes<HTMLAnchorElement>;\n span: HTMLAttributes<HTMLSpanElement>;\n input: HTMLAttributes<HTMLInputElement>;\n p: HTMLAttributes<HTMLParagraphElement>;\n h1: HTMLAttributes<HTMLHeadingElement>;\n h2: HTMLAttributes<HTMLHeadingElement>;\n h3: HTMLAttributes<HTMLHeadingElement>;\n ul: HTMLAttributes<HTMLUListElement>;\n li: HTMLAttributes<HTMLLIElement>;\n section: HTMLAttributes<HTMLElement>;\n // Web Components 元素\n slot: HTMLAttributes<HTMLSlotElement>;\n }\n\n interface HTMLAttributes<T extends HTMLElement = HTMLElement> {\n // 基础属性\n className?: string;\n class?: string;\n id?: string;\n style?: string;\n disabled?: boolean;\n title?: string;\n type?: string;\n value?: string;\n placeholder?: string;\n src?: string;\n alt?: string;\n href?: string | null;\n target?: string;\n rel?: string;\n download?: string;\n\n // Ref callback with proper typing\n ref?: (element: T) => void;\n\n // Data attributes\n [dataAttr: `data-${string}`]: string;\n\n // Event handlers\n onClick?: (event: Event) => void;\n onInput?: (event: Event) => void;\n onChange?: (event: Event) => void;\n onMouseOver?: (event: Event) => void;\n onMouseOut?: (event: Event) => void;\n onFocus?: (event: Event) => void;\n onBlur?: (event: Event) => void;\n onMouseDown?: (event: MouseEvent) => void;\n onKeyDown?: (event: KeyboardEvent) => void;\n\n // 允许任意属性\n [key: string]: unknown;\n }\n\n // 核心 JSX 接口\n type Element = HTMLElement;\n\n interface ElementClass {\n render(): Element;\n }\n\n interface ElementAttributesProperty {\n props: object;\n }\n\n interface ElementChildrenAttribute {\n children: object;\n }\n\n type LibraryManagedAttributes<_C, P> = P;\n }\n}\n\n// 导出 JSX 工厂函数\nexport { h, Fragment };\n","/**\n * SVG utilities for namespace-aware element creation\n */\n\n// SVG namespace URI\nexport const SVG_NAMESPACE = \"http://www.w3.org/2000/svg\";\n\n// SVG专用元素 - 只存在于SVG中的元素\nexport const SVG_ONLY_ELEMENTS = new Set([\n // 结构元素 (Structural elements)\n \"svg\",\n \"defs\",\n \"g\",\n \"symbol\",\n \"use\",\n\n // 图形元素 (Graphics elements)\n \"circle\",\n \"ellipse\",\n \"line\",\n \"path\",\n \"polygon\",\n \"polyline\",\n \"rect\",\n\n // 文本元素 (Text elements)\n \"textPath\",\n \"tspan\",\n\n // 渐变和模式 (Gradients and patterns)\n \"linearGradient\",\n \"radialGradient\",\n \"stop\",\n \"pattern\",\n\n // 滤镜 (Filter elements)\n \"filter\",\n \"feBlend\",\n \"feColorMatrix\",\n \"feComponentTransfer\",\n \"feComposite\",\n \"feConvolveMatrix\",\n \"feDiffuseLighting\",\n \"feDisplacementMap\",\n \"feDistantLight\",\n \"feDropShadow\",\n \"feFlood\",\n \"feFuncA\",\n \"feFuncB\",\n \"feFuncG\",\n \"feFuncR\",\n \"feGaussianBlur\",\n \"feImage\",\n \"feMerge\",\n \"feMergeNode\",\n \"feMorphology\",\n \"feOffset\",\n \"fePointLight\",\n \"feSpecularLighting\",\n \"feSpotLight\",\n \"feTile\",\n \"feTurbulence\",\n\n // 动画元素 (Animation elements)\n \"animate\",\n \"animateMotion\",\n \"animateTransform\",\n \"set\",\n\n // 其他元素 (Other elements)\n \"clipPath\",\n \"foreignObject\",\n \"marker\",\n \"mask\",\n \"metadata\",\n \"switch\",\n \"desc\",\n]);\n\n// 既存在于HTML又存在于SVG的元素 - 默认使用HTML版本\nexport const DUAL_ELEMENTS = new Set([\"image\", \"style\", \"title\", \"text\"]);\n\n// 强制使用HTML版本的元素(即使在SVG上下文中)\nexport const FORCE_HTML_ELEMENTS = new Set([\"a\"]);\n\n// 所有SVG元素的集合\nexport const SVG_ELEMENTS = new Set([\n ...SVG_ONLY_ELEMENTS,\n ...DUAL_ELEMENTS,\n ...FORCE_HTML_ELEMENTS,\n]);\n\n// SVG上下文追踪\nlet svgContext = false;\n\n/**\n * 检查标签名是否为SVG专用元素\n */\nexport function isSVGOnlyElement(tagName: string): boolean {\n return SVG_ONLY_ELEMENTS.has(tagName);\n}\n\n/**\n * 检查标签名是否为双重元素(HTML和SVG都有)\n */\nexport function isDualElement(tagName: string): boolean {\n return DUAL_ELEMENTS.has(tagName);\n}\n\n/**\n * 检查标签名是否为强制HTML元素\n */\nexport function isForceHTMLElement(tagName: string): boolean {\n return FORCE_HTML_ELEMENTS.has(tagName);\n}\n\n/**\n * 检查标签名是否为SVG元素(保持向后兼容)\n */\nexport function isSVGElement(tagName: string): boolean {\n return SVG_ELEMENTS.has(tagName);\n}\n\n/**\n * 设置SVG上下文状态\n */\nexport function setSVGContext(inSVG: boolean): void {\n svgContext = inSVG;\n}\n\n/**\n * 获取当前SVG上下文状态\n */\nexport function getSVGContext(): boolean {\n return svgContext;\n}\n\n/**\n * 创建元素 - 基于上下文和元素类型智能选择命名空间\n */\nexport function createElement(tagName: string): HTMLElement | SVGElement {\n // 强制HTML元素始终使用HTML版本\n if (isForceHTMLElement(tagName)) {\n return document.createElement(tagName) as HTMLElement;\n }\n\n // SVG专用元素始终使用SVG命名空间\n if (isSVGOnlyElement(tagName)) {\n setSVGContext(true); // 进入SVG上下文\n return document.createElementNS(SVG_NAMESPACE, tagName) as SVGElement;\n }\n\n // 双重元素根据上下文决定\n if (isDualElement(tagName)) {\n if (svgContext) {\n return document.createElementNS(SVG_NAMESPACE, tagName) as SVGElement;\n }\n }\n\n // 默认创建HTML元素\n return document.createElement(tagName) as HTMLElement;\n}\n\n/**\n * 检测元素是否需要在SVG上下文中处理\n */\nexport function shouldUseSVGNamespace(tagName: string): boolean {\n return isSVGOnlyElement(tagName) || (isDualElement(tagName) && svgContext);\n}\n\n/**\n * SVG特殊属性映射 - 处理SVG和HTML属性差异\n */\nexport const SVG_ATTRIBUTE_MAP = new Map([\n [\"className\", \"class\"],\n [\"htmlFor\", \"for\"],\n]);\n\n/**\n * 获取SVG元素的正确属性名\n */\nexport function getSVGAttributeName(attributeName: string): string {\n return SVG_ATTRIBUTE_MAP.get(attributeName) || attributeName;\n}\n","/**\n * 纯原生JSX工厂 - 零依赖的EditorJS Web Component支持\n *\n * 特点:\n * - 完全独立,不依赖React或任何框架\n * - 支持标准JSX语法\n * - 原生DOM操作,性能优异\n * - 完全通用,适用于任何Web Components\n * - TypeScript类型安全\n */\n\n// JSX 类型声明已移至 types/wsx-types.d.ts\n\nimport { createElement, shouldUseSVGNamespace, getSVGAttributeName } from \"./utils/svg-utils\";\n\n// JSX子元素类型\nexport type JSXChildren =\n | string\n | number\n | HTMLElement\n | SVGElement\n | DocumentFragment\n | JSXChildren[]\n | null\n | undefined\n | boolean;\n\n/**\n * 纯原生JSX工厂函数\n *\n * @param tag - HTML标签名或组件函数\n * @param props - 属性对象\n * @param children - 子元素\n * @returns DOM元素\n */\nexport function h(\n tag:\n | string\n | ((\n props: Record<string, unknown> | null,\n children: JSXChildren[]\n ) => HTMLElement | SVGElement),\n props: Record<string, unknown> | null = {},\n ...children: JSXChildren[]\n): HTMLElement | SVGElement {\n // 处理组件函数\n if (typeof tag === \"function\") {\n return tag(props, children);\n }\n\n // 创建DOM元素 - 自动检测SVG命名空间\n const element = createElement(tag);\n\n // 处理属性\n if (props) {\n const isSVG = shouldUseSVGNamespace(tag);\n\n Object.entries(props).forEach(([key, value]) => {\n if (value === null || value === undefined || value === false) {\n return;\n }\n\n // 处理ref回调\n if (key === \"ref\" && typeof value === \"function\") {\n value(element);\n }\n // 处理className和class\n else if (key === \"className\" || key === \"class\") {\n if (isSVG) {\n // SVG元素使用class属性\n element.setAttribute(\"class\", value as string);\n } else {\n // HTML元素可以使用className\n (element as HTMLElement).className = value as string;\n }\n }\n // 处理style\n else if (key === \"style\" && typeof value === \"string\") {\n element.setAttribute(\"style\", value);\n }\n // 处理事件监听器\n else if (key.startsWith(\"on\") && typeof value === \"function\") {\n const eventName = key.slice(2).toLowerCase();\n element.addEventListener(eventName, value as EventListener);\n }\n // 处理布尔属性\n else if (typeof value === \"boolean\") {\n if (value) {\n element.setAttribute(key, \"\");\n }\n }\n // 处理其他属性\n else {\n // 对SVG元素使用正确的属性名\n const attributeName = isSVG ? getSVGAttributeName(key) : key;\n element.setAttribute(attributeName, String(value));\n }\n });\n }\n\n // 处理子元素\n const flatChildren = flattenChildren(children);\n flatChildren.forEach((child) => {\n if (child === null || child === undefined || child === false) {\n return;\n }\n\n if (typeof child === \"string\" || typeof child === \"number\") {\n element.appendChild(document.createTextNode(String(child)));\n } else if (child instanceof HTMLElement || child instanceof SVGElement) {\n element.appendChild(child);\n } else if (child instanceof DocumentFragment) {\n element.appendChild(child);\n }\n });\n\n return element;\n}\n\n/**\n * 扁平化子元素数组\n */\nfunction flattenChildren(\n children: JSXChildren[]\n): (string | number | HTMLElement | SVGElement | DocumentFragment | boolean | null | undefined)[] {\n const result: (\n | string\n | number\n | HTMLElement\n | SVGElement\n | DocumentFragment\n | boolean\n | null\n | undefined\n )[] = [];\n\n for (const child of children) {\n if (child === null || child === undefined || child === false) {\n continue;\n } else if (Array.isArray(child)) {\n result.push(...flattenChildren(child));\n } else {\n result.push(child);\n }\n }\n\n return result;\n}\n\n/**\n * JSX Fragment支持 - 用于包装多个子元素\n */\nexport function Fragment(_props: unknown, children: JSXChildren[]): DocumentFragment {\n const fragment = document.createDocumentFragment();\n const flatChildren = flattenChildren(children);\n\n flatChildren.forEach((child) => {\n if (child === null || child === undefined || child === false) {\n return;\n }\n\n if (typeof child === \"string\" || typeof child === \"number\") {\n fragment.appendChild(document.createTextNode(String(child)));\n } else if (child instanceof HTMLElement || child instanceof SVGElement) {\n fragment.appendChild(child);\n } else if (child instanceof DocumentFragment) {\n fragment.appendChild(child);\n }\n });\n\n return fragment;\n}\n\n/**\n * JSX function for React's new JSX transform\n * Handles the new format: jsx(tag, { children: child, ...props })\n */\nexport function jsx(\n tag:\n | string\n | ((\n props: Record<string, unknown> | null,\n children: JSXChildren[]\n ) => HTMLElement | SVGElement),\n props: Record<string, unknown> | null\n): HTMLElement | SVGElement {\n if (!props) {\n return h(tag, null);\n }\n\n const { children, ...restProps } = props;\n if (\n (children !== undefined && children !== null && typeof children !== \"object\") ||\n Array.isArray(children) ||\n typeof children === \"string\" ||\n typeof children === \"number\" ||\n typeof children === \"boolean\" ||\n children instanceof HTMLElement ||\n children instanceof SVGElement ||\n children instanceof DocumentFragment\n ) {\n return h(tag, restProps, children as JSXChildren);\n }\n return h(tag, restProps);\n}\n\n/**\n * JSX function for multiple children in React's new JSX transform\n * Handles the new format: jsxs(tag, { children: [child1, child2], ...props })\n */\nexport function jsxs(\n tag:\n | string\n | ((\n props: Record<string, unknown> | null,\n children: JSXChildren[]\n ) => HTMLElement | SVGElement),\n props: Record<string, unknown> | null\n): HTMLElement | SVGElement {\n if (!props) {\n return h(tag, null);\n }\n\n const { children, ...restProps } = props;\n if (Array.isArray(children)) {\n return h(tag, restProps, ...children);\n } else if (\n children !== undefined &&\n children !== null &&\n (typeof children !== \"object\" ||\n children instanceof HTMLElement ||\n children instanceof SVGElement ||\n children instanceof DocumentFragment)\n ) {\n return h(tag, restProps, children as JSXChildren);\n }\n return h(tag, restProps);\n}\n"],"mappings":"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","names":[]}
|
package/dist/jsx.mjs
ADDED
package/dist/jsx.mjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wsxjs/wsx-core",
|
|
3
|
+
"version": "0.0.5",
|
|
4
|
+
"description": "Core WSX Framework - Web Components with JSX syntax",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./types/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./types/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./jsx-runtime": {
|
|
15
|
+
"types": "./types/jsx-runtime.d.ts",
|
|
16
|
+
"import": "./dist/jsx-runtime.mjs",
|
|
17
|
+
"require": "./dist/jsx-runtime.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"src",
|
|
23
|
+
"types",
|
|
24
|
+
"!**/__tests__",
|
|
25
|
+
"!**/test"
|
|
26
|
+
],
|
|
27
|
+
"keywords": [
|
|
28
|
+
"web-components",
|
|
29
|
+
"jsx",
|
|
30
|
+
"typescript",
|
|
31
|
+
"custom-elements"
|
|
32
|
+
],
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"tsup": "^8.0.0",
|
|
35
|
+
"typescript": "^5.0.0",
|
|
36
|
+
"@types/node": "^20.0.0"
|
|
37
|
+
},
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"typescript": ">=4.7.0"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsup src/index.ts src/jsx.ts src/jsx-runtime.ts --format cjs,esm",
|
|
43
|
+
"build:dev": "NODE_ENV=development tsup src/index.ts src/jsx.ts src/jsx-runtime.ts --format cjs,esm --sourcemap",
|
|
44
|
+
"dev": "NODE_ENV=development tsup src/index.ts src/jsx.ts src/jsx-runtime.ts --format cjs,esm --watch --sourcemap",
|
|
45
|
+
"test": "jest",
|
|
46
|
+
"typecheck": "tsc --noEmit",
|
|
47
|
+
"clean": "rm -rf dist"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-registration decorator and utilities for web components
|
|
3
|
+
*
|
|
4
|
+
* Provides decorator-based auto-registration for web components
|
|
5
|
+
* to eliminate manual customElements.define() calls.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Auto-registration options for web components
|
|
10
|
+
*/
|
|
11
|
+
export interface AutoRegistrationOptions {
|
|
12
|
+
tagName?: string; // Custom tag name, if not provided, derives from class name
|
|
13
|
+
prefix?: string; // Prefix for tag name (e.g., "my-" -> "my-component")
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Auto-register decorator for web components
|
|
18
|
+
* Usage: @autoRegister() or @autoRegister({ tagName: "custom-name" })
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* @autoRegister()
|
|
23
|
+
* class MyButton extends WebComponent {
|
|
24
|
+
* // Will be registered as "my-button-component"
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* @autoRegister({ tagName: "custom-button" })
|
|
28
|
+
* class MyButton extends WebComponent {
|
|
29
|
+
* // Will be registered as "custom-button"
|
|
30
|
+
* }
|
|
31
|
+
*
|
|
32
|
+
* @autoRegister({ prefix: "ui-" })
|
|
33
|
+
* class MyButton extends WebComponent {
|
|
34
|
+
* // Will be registered as "ui-my-button-component"
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export function autoRegister(options: AutoRegistrationOptions = {}) {
|
|
39
|
+
return function <T extends CustomElementConstructor>(constructor: T): T {
|
|
40
|
+
const tagName = options.tagName || deriveTagName(constructor.name, options.prefix);
|
|
41
|
+
|
|
42
|
+
if (!customElements.get(tagName)) {
|
|
43
|
+
customElements.define(tagName, constructor);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return constructor;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Static method to auto-register a web component class
|
|
52
|
+
* Usage: registerComponent(MyComponent) or registerComponent(MyComponent, { tagName: "custom-name" })
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* class MyButton extends WebComponent {
|
|
57
|
+
* // ...
|
|
58
|
+
* }
|
|
59
|
+
*
|
|
60
|
+
* registerComponent(MyButton); // Registers as "my-button-component"
|
|
61
|
+
* registerComponent(MyButton, { tagName: "custom-button" }); // Registers as "custom-button"
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export function registerComponent<T extends CustomElementConstructor>(
|
|
65
|
+
constructor: T,
|
|
66
|
+
options: AutoRegistrationOptions = {}
|
|
67
|
+
): void {
|
|
68
|
+
const tagName = options.tagName || deriveTagName(constructor.name, options.prefix);
|
|
69
|
+
|
|
70
|
+
if (!customElements.get(tagName)) {
|
|
71
|
+
customElements.define(tagName, constructor);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Derive tag name from class name
|
|
77
|
+
* Converts PascalCase to kebab-case and adds optional prefix
|
|
78
|
+
* Ensures valid custom element name (must contain hyphen)
|
|
79
|
+
*
|
|
80
|
+
* @param className - The class name to convert
|
|
81
|
+
* @param prefix - Optional prefix to add
|
|
82
|
+
* @returns Valid custom element tag name
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```typescript
|
|
86
|
+
* deriveTagName("MyButton") // "my-button-component"
|
|
87
|
+
* deriveTagName("HTMLEditor") // "htmleditor-component"
|
|
88
|
+
* deriveTagName("Button") // "button-component"
|
|
89
|
+
* deriveTagName("MyButton", "ui-") // "ui-my-button-component"
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
function deriveTagName(className: string, prefix?: string): string {
|
|
93
|
+
// Convert PascalCase to kebab-case
|
|
94
|
+
let kebabCase = className.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
95
|
+
|
|
96
|
+
// Ensure the tag name contains at least one hyphen (custom element requirement)
|
|
97
|
+
if (!kebabCase.includes("-")) {
|
|
98
|
+
kebabCase = `${kebabCase}-component`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return prefix ? `${prefix}${kebabCase}` : kebabCase;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Register all components in a module
|
|
106
|
+
* Useful for bulk registration of multiple components
|
|
107
|
+
*
|
|
108
|
+
* @param components - Object containing component classes
|
|
109
|
+
* @param options - Default options to apply to all components
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```typescript
|
|
113
|
+
* import * as Components from './components';
|
|
114
|
+
*
|
|
115
|
+
* registerAll(Components, { prefix: "ui-" });
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
export function registerAll(
|
|
119
|
+
components: Record<string, CustomElementConstructor>,
|
|
120
|
+
options: AutoRegistrationOptions = {}
|
|
121
|
+
): void {
|
|
122
|
+
Object.values(components).forEach((component) => {
|
|
123
|
+
if (typeof component === "function" && component.prototype instanceof HTMLElement) {
|
|
124
|
+
registerComponent(component, options);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Check if a component is already registered
|
|
131
|
+
*
|
|
132
|
+
* @param tagName - The tag name to check
|
|
133
|
+
* @returns True if the component is registered
|
|
134
|
+
*/
|
|
135
|
+
export function isRegistered(tagName: string): boolean {
|
|
136
|
+
return !!customElements.get(tagName);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Get the tag name that would be generated for a class
|
|
141
|
+
* Useful for testing or debugging
|
|
142
|
+
*
|
|
143
|
+
* @param className - The class name
|
|
144
|
+
* @param options - Registration options
|
|
145
|
+
* @returns The generated tag name
|
|
146
|
+
*/
|
|
147
|
+
export function getTagName(className: string, options: AutoRegistrationOptions = {}): string {
|
|
148
|
+
return options.tagName || deriveTagName(className, options.prefix);
|
|
149
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Core exports
|
|
2
|
+
export { WebComponent } from "./web-component";
|
|
3
|
+
export { autoRegister, registerComponent } from "./auto-register";
|
|
4
|
+
export { h, h as jsx, h as jsxs, Fragment } from "./jsx-factory";
|
|
5
|
+
export { StyleManager } from "./styles/style-manager";
|
|
6
|
+
export { WSXLogger, logger, createLogger } from "./utils/logger";
|
|
7
|
+
|
|
8
|
+
// Reactive exports
|
|
9
|
+
export { reactive, createState, ReactiveDebug } from "./utils/reactive";
|
|
10
|
+
export { ReactiveWebComponent, makeReactive, createReactiveComponent } from "./reactive-component";
|
|
11
|
+
|
|
12
|
+
// Type exports
|
|
13
|
+
export type { WebComponentConfig } from "./web-component";
|
|
14
|
+
export type { JSXChildren } from "./jsx-factory";
|
|
15
|
+
export type { Logger, LogLevel } from "./utils/logger";
|
|
16
|
+
export type { ReactiveCallback } from "./utils/reactive";
|
|
17
|
+
export type { ReactiveWebComponentConfig } from "./reactive-component";
|