j20 0.0.0 → 0.0.1
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 +1 -1
- package/dist/index.d.mts +3486 -0
- package/dist/index.mjs +883 -0
- package/dist/jsx-runtime.d.mts +10 -0
- package/dist/jsx-runtime.mjs +23 -0
- package/package.json +31 -11
- package/.vscode/settings.json +0 -4
- package/example/index.html +0 -12
- package/example/index.ts +0 -74
- package/example/item.ts +0 -31
- package/jsx.d.ts +0 -1361
- package/src/api.ts +0 -14
- package/src/component.ts +0 -76
- package/src/control.ts +0 -120
- package/src/tags.ts +0 -64
- package/src/utils.ts +0 -7
- package/tsconfig.json +0 -110
- package/vite.config.js +0 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,883 @@
|
|
|
1
|
+
//#region ../signal/dist/index.mjs
|
|
2
|
+
let currentReaction = null;
|
|
3
|
+
const depMap = /* @__PURE__ */ new WeakMap();
|
|
4
|
+
/**
|
|
5
|
+
* Signal类 - 用于存储响应式数据
|
|
6
|
+
*/
|
|
7
|
+
var Signal = class {
|
|
8
|
+
_value;
|
|
9
|
+
_version = 0;
|
|
10
|
+
_deps = /* @__PURE__ */ new Set();
|
|
11
|
+
constructor(value) {
|
|
12
|
+
this._value = value;
|
|
13
|
+
}
|
|
14
|
+
get value() {
|
|
15
|
+
if (currentReaction) this.track(currentReaction);
|
|
16
|
+
return this._value;
|
|
17
|
+
}
|
|
18
|
+
set value(newValue) {
|
|
19
|
+
if (Object.is(this._value, newValue)) return;
|
|
20
|
+
this._value = newValue;
|
|
21
|
+
this._version++;
|
|
22
|
+
this._deps.forEach((reaction) => {
|
|
23
|
+
if (reaction instanceof Computed) reaction.markDirty();
|
|
24
|
+
else if (reaction.isActive()) {
|
|
25
|
+
if (reaction._depVersions.has(this) || reaction.hasDepsChanged()) reaction.execute();
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
get version() {
|
|
30
|
+
return this._version;
|
|
31
|
+
}
|
|
32
|
+
track(reaction) {
|
|
33
|
+
if (!this._deps.has(reaction)) {
|
|
34
|
+
this._deps.add(reaction);
|
|
35
|
+
let reactions = depMap.get(this);
|
|
36
|
+
if (!reactions) {
|
|
37
|
+
reactions = /* @__PURE__ */ new Set();
|
|
38
|
+
depMap.set(this, reactions);
|
|
39
|
+
}
|
|
40
|
+
reactions.add(reaction);
|
|
41
|
+
reaction.track(this);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Computed类 - 用于计算派生值
|
|
47
|
+
*/
|
|
48
|
+
var Computed = class Computed$1 {
|
|
49
|
+
computeFn;
|
|
50
|
+
_value;
|
|
51
|
+
_version = 0;
|
|
52
|
+
dirty = true;
|
|
53
|
+
disposed = false;
|
|
54
|
+
_deps = /* @__PURE__ */ new Set();
|
|
55
|
+
sources = /* @__PURE__ */ new Set();
|
|
56
|
+
constructor(computeFn) {
|
|
57
|
+
this.computeFn = computeFn;
|
|
58
|
+
this._value = void 0;
|
|
59
|
+
}
|
|
60
|
+
get value() {
|
|
61
|
+
if (this.disposed) throw new Error("Cannot access value of disposed computed");
|
|
62
|
+
if (this.dirty) this.compute();
|
|
63
|
+
if (currentReaction) {
|
|
64
|
+
if (!this._deps.has(currentReaction)) {
|
|
65
|
+
this._deps.add(currentReaction);
|
|
66
|
+
currentReaction.track(this);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return this._value;
|
|
70
|
+
}
|
|
71
|
+
get version() {
|
|
72
|
+
return this._version;
|
|
73
|
+
}
|
|
74
|
+
compute() {
|
|
75
|
+
if (this.disposed) throw new Error("Cannot compute disposed computed");
|
|
76
|
+
if (computationStack.includes(this)) throw new Error("Circular dependency detected in computed values");
|
|
77
|
+
this.dirty = false;
|
|
78
|
+
const prevReaction = currentReaction;
|
|
79
|
+
const prevSources = this.sources;
|
|
80
|
+
this.sources = /* @__PURE__ */ new Set();
|
|
81
|
+
computationStack.push(this);
|
|
82
|
+
currentReaction = this;
|
|
83
|
+
try {
|
|
84
|
+
this._value = this.computeFn();
|
|
85
|
+
this._version++;
|
|
86
|
+
} catch (e) {
|
|
87
|
+
this.dirty = true;
|
|
88
|
+
throw e;
|
|
89
|
+
} finally {
|
|
90
|
+
const index = computationStack.indexOf(this);
|
|
91
|
+
if (index !== -1) computationStack.splice(index, 1);
|
|
92
|
+
currentReaction = prevReaction;
|
|
93
|
+
prevSources.forEach((source) => {
|
|
94
|
+
if (!this.sources.has(source)) {
|
|
95
|
+
const reactions = depMap.get(source);
|
|
96
|
+
if (reactions) reactions.delete(this);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
markDirty() {
|
|
102
|
+
if (this.disposed || this.dirty) return;
|
|
103
|
+
this.dirty = true;
|
|
104
|
+
this._deps.forEach((reaction) => {
|
|
105
|
+
if (reaction instanceof Computed$1) reaction.markDirty();
|
|
106
|
+
else if (reaction.isActive()) reaction.execute();
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
track(source) {
|
|
110
|
+
if (this.disposed) return;
|
|
111
|
+
if (!this.sources.has(source)) {
|
|
112
|
+
this.sources.add(source);
|
|
113
|
+
let reactions = depMap.get(source);
|
|
114
|
+
if (!reactions) {
|
|
115
|
+
reactions = /* @__PURE__ */ new Set();
|
|
116
|
+
depMap.set(source, reactions);
|
|
117
|
+
}
|
|
118
|
+
reactions.add(this);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
dispose() {
|
|
122
|
+
if (this.disposed) return;
|
|
123
|
+
this.disposed = true;
|
|
124
|
+
this.sources.forEach((source) => {
|
|
125
|
+
const reactions = depMap.get(source);
|
|
126
|
+
if (reactions) reactions.delete(this);
|
|
127
|
+
});
|
|
128
|
+
this.sources.clear();
|
|
129
|
+
this._deps.clear();
|
|
130
|
+
this._value = void 0;
|
|
131
|
+
this.computeFn = void 0;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
const computationStack = [];
|
|
135
|
+
/**
|
|
136
|
+
* Effect类 - 用于执行副作用
|
|
137
|
+
*/
|
|
138
|
+
var Effect = class {
|
|
139
|
+
effectFn;
|
|
140
|
+
cleanupFn = null;
|
|
141
|
+
disposed = false;
|
|
142
|
+
_deps = /* @__PURE__ */ new Set();
|
|
143
|
+
_depVersions = /* @__PURE__ */ new Map();
|
|
144
|
+
constructor(effectFn) {
|
|
145
|
+
this.effectFn = effectFn;
|
|
146
|
+
}
|
|
147
|
+
execute() {
|
|
148
|
+
if (this.disposed) return;
|
|
149
|
+
if (this.cleanupFn) {
|
|
150
|
+
try {
|
|
151
|
+
this.cleanupFn();
|
|
152
|
+
} catch (e) {
|
|
153
|
+
console.warn("Error in effect cleanup function:", e);
|
|
154
|
+
}
|
|
155
|
+
this.cleanupFn = null;
|
|
156
|
+
}
|
|
157
|
+
const prevReaction = currentReaction;
|
|
158
|
+
currentReaction = this;
|
|
159
|
+
try {
|
|
160
|
+
const result = this.effectFn();
|
|
161
|
+
if (typeof result === "function") this.cleanupFn = result;
|
|
162
|
+
} finally {
|
|
163
|
+
currentReaction = prevReaction;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
dispose() {
|
|
167
|
+
if (this.disposed) return;
|
|
168
|
+
this.disposed = true;
|
|
169
|
+
this._deps.forEach((dep) => {
|
|
170
|
+
const reactions = depMap.get(dep);
|
|
171
|
+
if (reactions) reactions.delete(this);
|
|
172
|
+
});
|
|
173
|
+
this._deps.clear();
|
|
174
|
+
this._depVersions.clear();
|
|
175
|
+
if (this.cleanupFn) {
|
|
176
|
+
try {
|
|
177
|
+
this.cleanupFn();
|
|
178
|
+
} catch (e) {
|
|
179
|
+
console.warn("Error in effect cleanup function:", e);
|
|
180
|
+
}
|
|
181
|
+
this.cleanupFn = null;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
isActive() {
|
|
185
|
+
return !this.disposed;
|
|
186
|
+
}
|
|
187
|
+
track(source) {
|
|
188
|
+
if (this.disposed) return;
|
|
189
|
+
if (!this._deps.has(source)) {
|
|
190
|
+
this._deps.add(source);
|
|
191
|
+
if ("version" in source) this._depVersions.set(source, source.version);
|
|
192
|
+
let reactions = depMap.get(source);
|
|
193
|
+
if (!reactions) {
|
|
194
|
+
reactions = /* @__PURE__ */ new Set();
|
|
195
|
+
depMap.set(source, reactions);
|
|
196
|
+
}
|
|
197
|
+
reactions.add(this);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
hasDepsChanged() {
|
|
201
|
+
for (const [dep, version] of this._depVersions) if ("version" in dep && dep.version !== version) return true;
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
function signal(initialValue) {
|
|
206
|
+
return new Signal(initialValue);
|
|
207
|
+
}
|
|
208
|
+
function computed(computeFn) {
|
|
209
|
+
return new Computed(computeFn);
|
|
210
|
+
}
|
|
211
|
+
function effect$1(effectFn) {
|
|
212
|
+
const effectInstance = new Effect(effectFn);
|
|
213
|
+
effectInstance.execute();
|
|
214
|
+
return effectInstance;
|
|
215
|
+
}
|
|
216
|
+
function untrack(fn) {
|
|
217
|
+
const prevReaction = currentReaction;
|
|
218
|
+
currentReaction = null;
|
|
219
|
+
try {
|
|
220
|
+
return fn();
|
|
221
|
+
} finally {
|
|
222
|
+
currentReaction = prevReaction;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
//#endregion
|
|
227
|
+
//#region src/h/utils.ts
|
|
228
|
+
const isEvent = (eventName) => {
|
|
229
|
+
return eventName.startsWith("on");
|
|
230
|
+
};
|
|
231
|
+
const getEventName = (eventName) => {
|
|
232
|
+
return eventName.slice(2).toLocaleLowerCase();
|
|
233
|
+
};
|
|
234
|
+
const getChildren = (propChildren) => {
|
|
235
|
+
const arr = [];
|
|
236
|
+
for (let i = 0; i < propChildren.length; i++) {
|
|
237
|
+
const child = propChildren[i];
|
|
238
|
+
if (typeof child === "function") {
|
|
239
|
+
const el = child();
|
|
240
|
+
if (typeof el === "number" || typeof el === "string") {
|
|
241
|
+
let textNode = document.createTextNode("");
|
|
242
|
+
effect(() => {
|
|
243
|
+
textNode.nodeValue = child();
|
|
244
|
+
});
|
|
245
|
+
arr.push(textNode);
|
|
246
|
+
} else arr.push(el);
|
|
247
|
+
} else if (child != void 0) arr.push(child);
|
|
248
|
+
}
|
|
249
|
+
return arr;
|
|
250
|
+
};
|
|
251
|
+
let overflow = "";
|
|
252
|
+
let count = 0;
|
|
253
|
+
const generateId = () => {
|
|
254
|
+
if (count === Number.MAX_SAFE_INTEGER) {
|
|
255
|
+
overflow += count.toString(32);
|
|
256
|
+
count = 0;
|
|
257
|
+
}
|
|
258
|
+
return `${overflow}${(count++).toString(32)}`;
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
//#endregion
|
|
262
|
+
//#region src/h/createDom.ts
|
|
263
|
+
const update = (node, key, oldValue, newValue) => {
|
|
264
|
+
if (isEvent(key)) {
|
|
265
|
+
node.removeEventListener(getEventName(key), oldValue);
|
|
266
|
+
node.addEventListener(getEventName(key), newValue);
|
|
267
|
+
} else if (newValue === false || newValue == null) node.removeAttribute(key);
|
|
268
|
+
else node.setAttribute(key, newValue === true ? "" : newValue);
|
|
269
|
+
};
|
|
270
|
+
const unset = (node, key, oldValue) => {
|
|
271
|
+
if (isEvent(key)) node.removeEventListener(getEventName(key), oldValue);
|
|
272
|
+
else if (key === "ref") oldValue.current = null;
|
|
273
|
+
else node.removeAttribute(key);
|
|
274
|
+
};
|
|
275
|
+
const add = (node, key, newValue) => {
|
|
276
|
+
if (isEvent(key)) node.addEventListener(getEventName(key), newValue);
|
|
277
|
+
else if (key === "ref") {
|
|
278
|
+
getCurrentInstance()?.disposes.push(() => {
|
|
279
|
+
newValue.current = null;
|
|
280
|
+
});
|
|
281
|
+
newValue.current = node;
|
|
282
|
+
} else newValue !== false && newValue != null && node.setAttribute(key, newValue === true ? "" : newValue);
|
|
283
|
+
};
|
|
284
|
+
const createDom = (tag, props, children) => {
|
|
285
|
+
const node = tag;
|
|
286
|
+
let oldProps = {};
|
|
287
|
+
props && effect(() => {
|
|
288
|
+
const newProps = { ...props() };
|
|
289
|
+
const newKeys = Object.keys(newProps);
|
|
290
|
+
const oldKeys = Object.keys(oldProps);
|
|
291
|
+
const allKeys = new Set([...newKeys, ...oldKeys]);
|
|
292
|
+
for (const key of allKeys) oldKeys.includes(key) ? newKeys.includes(key) ? Object.is(oldProps[key], newProps[key]) || update(node, key, oldProps[key], newProps[key]) : unset(node, key, oldProps[key]) : add(node, key, newProps[key]);
|
|
293
|
+
oldProps = newProps;
|
|
294
|
+
});
|
|
295
|
+
node.lazyInit?.();
|
|
296
|
+
if (children && (node.lazyInit ? !node.shadowRoot ? false : true : true)) node.append(...getChildren([].concat(children())));
|
|
297
|
+
return node;
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
//#endregion
|
|
301
|
+
//#region src/h/instance.ts
|
|
302
|
+
const stack = [];
|
|
303
|
+
const getCurrentInstance = () => stack.at(-1);
|
|
304
|
+
const instanceInit = (parent) => {
|
|
305
|
+
const id = generateId();
|
|
306
|
+
const parentInstance = parent ?? getCurrentInstance();
|
|
307
|
+
const instance = {
|
|
308
|
+
parent: parentInstance,
|
|
309
|
+
id,
|
|
310
|
+
range: [document.createTextNode(""), document.createTextNode("")],
|
|
311
|
+
disposes: []
|
|
312
|
+
};
|
|
313
|
+
if (parentInstance) if (parentInstance.children) parentInstance.children.push(instance);
|
|
314
|
+
else parentInstance.children = [instance];
|
|
315
|
+
return instance;
|
|
316
|
+
};
|
|
317
|
+
const instanceCreateElement = (instance, runner) => {
|
|
318
|
+
stack.push(instance);
|
|
319
|
+
const fragment = createDom(document.createDocumentFragment(), void 0, () => runner());
|
|
320
|
+
fragment.prepend(instance.range[0]);
|
|
321
|
+
fragment.append(instance.range[1]);
|
|
322
|
+
stack.pop();
|
|
323
|
+
return fragment;
|
|
324
|
+
};
|
|
325
|
+
const instanceCreate = (runner, parent) => {
|
|
326
|
+
const instance = instanceInit(parent);
|
|
327
|
+
return [instance, instanceCreateElement(instance, runner)];
|
|
328
|
+
};
|
|
329
|
+
const instanceGetElements = (instance) => {
|
|
330
|
+
const [start, end] = instance.range;
|
|
331
|
+
const els = [start];
|
|
332
|
+
let index = start;
|
|
333
|
+
while (index = index.nextSibling) {
|
|
334
|
+
els.push(index);
|
|
335
|
+
if (index === end) break;
|
|
336
|
+
}
|
|
337
|
+
return els;
|
|
338
|
+
};
|
|
339
|
+
const instanceDestroy = (parent, instance) => {
|
|
340
|
+
const stack$1 = [instance];
|
|
341
|
+
while (stack$1.length) {
|
|
342
|
+
const instance$1 = stack$1.pop();
|
|
343
|
+
instance$1.disposes.forEach((dispose) => dispose());
|
|
344
|
+
if (instance$1.children) stack$1.push(...instance$1.children);
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
//#endregion
|
|
349
|
+
//#region src/api/effect.ts
|
|
350
|
+
const effect = (effectFn) => {
|
|
351
|
+
const effectInstance = effect$1(effectFn);
|
|
352
|
+
getCurrentInstance()?.disposes?.push(() => effectInstance.dispose());
|
|
353
|
+
return effectInstance;
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
//#endregion
|
|
357
|
+
//#region src/api/ref.ts
|
|
358
|
+
function ref(init) {
|
|
359
|
+
return { current: init ?? null };
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
//#endregion
|
|
363
|
+
//#region src/brand.ts
|
|
364
|
+
const BRAND = "j20";
|
|
365
|
+
|
|
366
|
+
//#endregion
|
|
367
|
+
//#region src/web-components.ts
|
|
368
|
+
let host;
|
|
369
|
+
const setHost = (h) => host = h;
|
|
370
|
+
const getHost = () => host;
|
|
371
|
+
const registerWebComponent = (Comp) => {
|
|
372
|
+
if (!Comp.customElement) throw new Error("Custom element options is not provided");
|
|
373
|
+
if (customElements.get(Comp.customElement.tag)) throw new Error("Custom element tag is already defined");
|
|
374
|
+
const NewClass = buildClass(Comp);
|
|
375
|
+
customElements.define(Comp.customElement.tag, NewClass);
|
|
376
|
+
};
|
|
377
|
+
const buildClass = (Comp) => {
|
|
378
|
+
const { customElement } = Comp;
|
|
379
|
+
const { a2p, a2v } = buildMap(customElement);
|
|
380
|
+
return class NewElementClass extends HTMLElement {
|
|
381
|
+
static get observedAttributes() {
|
|
382
|
+
return Object.entries(customElement.props ?? {}).map(([, value]) => value.attribute).filter((i) => i != void 0);
|
|
383
|
+
}
|
|
384
|
+
#shadow;
|
|
385
|
+
#props = {};
|
|
386
|
+
brand = BRAND;
|
|
387
|
+
customElement = customElement;
|
|
388
|
+
lazy;
|
|
389
|
+
constructor(lazy) {
|
|
390
|
+
super();
|
|
391
|
+
this.lazy = lazy;
|
|
392
|
+
if (customElement.tag && customElement.shadow) this.#shadow = this.attachShadow({ mode: customElement.shadow });
|
|
393
|
+
this.#props = Object.entries(customElement.props ?? {}).reduce((acc, [key, value]) => {
|
|
394
|
+
acc[key] = signal(value.attribute ? a2v[value.attribute](this.getAttribute(value.attribute)) : void 0);
|
|
395
|
+
return acc;
|
|
396
|
+
}, {});
|
|
397
|
+
}
|
|
398
|
+
lazyInit() {
|
|
399
|
+
setHost(this);
|
|
400
|
+
const host$1 = this;
|
|
401
|
+
const [, fragment] = instanceCreate(() => {
|
|
402
|
+
return Comp(computed(() => {
|
|
403
|
+
return new Proxy(this.#props, { get(target, p, receiver) {
|
|
404
|
+
if (typeof p === "string" && p.startsWith("on")) return (detail) => host$1.dispatchEvent(new CustomEvent(p.slice(2).toLocaleLowerCase(), { detail }));
|
|
405
|
+
else return Reflect.get(target, p, receiver)?.value;
|
|
406
|
+
} });
|
|
407
|
+
}));
|
|
408
|
+
}, getCurrentInstance());
|
|
409
|
+
setHost(void 0);
|
|
410
|
+
if (this.#shadow) this.#shadow.appendChild(fragment);
|
|
411
|
+
else this.appendChild(fragment);
|
|
412
|
+
}
|
|
413
|
+
appendToShadowDom(elements) {
|
|
414
|
+
if (this.#shadow && elements.length > 0) this.#shadow.append(...elements);
|
|
415
|
+
}
|
|
416
|
+
appendToLightDom(elements) {
|
|
417
|
+
if (this.#shadow && elements.length > 0) this.append(...elements);
|
|
418
|
+
}
|
|
419
|
+
appendToBody(elements) {
|
|
420
|
+
if (elements.length > 0) this.append(...elements);
|
|
421
|
+
}
|
|
422
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
423
|
+
if (this.lazy) return;
|
|
424
|
+
const attrs = NewElementClass.observedAttributes;
|
|
425
|
+
const propSignal = this.#props[a2p[name]];
|
|
426
|
+
if (propSignal && attrs.includes(name)) propSignal.value = a2v[name](newValue);
|
|
427
|
+
}
|
|
428
|
+
#connectedCallbackArray = [];
|
|
429
|
+
addConnectedCallback(callback) {
|
|
430
|
+
this.#connectedCallbackArray.push(callback);
|
|
431
|
+
}
|
|
432
|
+
connectedCallback() {
|
|
433
|
+
this.#connectedCallbackArray.forEach((fn) => fn());
|
|
434
|
+
}
|
|
435
|
+
#disconnectedCallbackArray = [];
|
|
436
|
+
addDisconnectedCallback(callback) {
|
|
437
|
+
this.#disconnectedCallbackArray.push(callback);
|
|
438
|
+
}
|
|
439
|
+
disconnectedCallback() {
|
|
440
|
+
this.#disconnectedCallbackArray.forEach((fn) => fn());
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
};
|
|
444
|
+
const buildMap = (customElement) => {
|
|
445
|
+
const a2p = {};
|
|
446
|
+
const p2a = {};
|
|
447
|
+
const a2v = {};
|
|
448
|
+
Object.entries(customElement.props ?? {}).map(([key, value]) => [
|
|
449
|
+
value.attribute,
|
|
450
|
+
key,
|
|
451
|
+
value.type
|
|
452
|
+
]).filter(([attr]) => attr != void 0).forEach((i) => {
|
|
453
|
+
a2p[i[0]] = i[1];
|
|
454
|
+
p2a[i[1]] = i[0];
|
|
455
|
+
a2v[i[0]] = {
|
|
456
|
+
string: (v) => v ?? void 0,
|
|
457
|
+
number: (v) => v ? Number(v) : void 0,
|
|
458
|
+
boolean: (v) => v == null ? false : true
|
|
459
|
+
}[i[2]];
|
|
460
|
+
});
|
|
461
|
+
return {
|
|
462
|
+
a2p,
|
|
463
|
+
p2a,
|
|
464
|
+
a2v
|
|
465
|
+
};
|
|
466
|
+
};
|
|
467
|
+
|
|
468
|
+
//#endregion
|
|
469
|
+
//#region src/api/wc.ts
|
|
470
|
+
const wc = () => {
|
|
471
|
+
const host$1 = getHost();
|
|
472
|
+
if (!host$1) throw new Error("host not found, please use `wc` in web component");
|
|
473
|
+
const emit = (name, detail) => {
|
|
474
|
+
host$1.dispatchEvent(new CustomEvent(name, { detail }));
|
|
475
|
+
};
|
|
476
|
+
const onConnectedCallback = (callback) => {
|
|
477
|
+
host$1.addConnectedCallback(callback);
|
|
478
|
+
};
|
|
479
|
+
const onDisconnectedCallback = (callback) => {
|
|
480
|
+
host$1.addDisconnectedCallback(callback);
|
|
481
|
+
};
|
|
482
|
+
return {
|
|
483
|
+
host: host$1,
|
|
484
|
+
emit,
|
|
485
|
+
onConnectedCallback,
|
|
486
|
+
onDisconnectedCallback
|
|
487
|
+
};
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
//#endregion
|
|
491
|
+
//#region src/api/dollar.ts
|
|
492
|
+
const $ = (val) => val;
|
|
493
|
+
|
|
494
|
+
//#endregion
|
|
495
|
+
//#region src/api/utils.ts
|
|
496
|
+
const isSignal = (a) => a?.brand === Symbol.for("preact-signals");
|
|
497
|
+
|
|
498
|
+
//#endregion
|
|
499
|
+
//#region src/api/context.ts
|
|
500
|
+
const contextWeakMap = /* @__PURE__ */ new WeakMap();
|
|
501
|
+
const context = (Context) => {
|
|
502
|
+
let index = getCurrentInstance()?.parent;
|
|
503
|
+
while (index) if (contextWeakMap.has(index)) {
|
|
504
|
+
const { ctx, value } = contextWeakMap.get(index);
|
|
505
|
+
if (ctx === Context) return value;
|
|
506
|
+
} else index = index.parent;
|
|
507
|
+
return Context.defaultValue;
|
|
508
|
+
};
|
|
509
|
+
const createContext = (defaultValue) => {
|
|
510
|
+
const Context = (p) => {
|
|
511
|
+
const props = p;
|
|
512
|
+
const instance = instanceInit(getCurrentInstance());
|
|
513
|
+
contextWeakMap.set(instance, {
|
|
514
|
+
ctx: Context,
|
|
515
|
+
value: { get value() {
|
|
516
|
+
return props.value.value;
|
|
517
|
+
} }
|
|
518
|
+
});
|
|
519
|
+
return instanceCreateElement(instance, () => props.value.children);
|
|
520
|
+
};
|
|
521
|
+
Context.isLogic = true;
|
|
522
|
+
const Consumer = (p) => {
|
|
523
|
+
const props = p;
|
|
524
|
+
const data = context(Context);
|
|
525
|
+
if (data) return props.value.children(data);
|
|
526
|
+
return props.value.children(isSignal(defaultValue) ? defaultValue : { get value() {
|
|
527
|
+
return defaultValue;
|
|
528
|
+
} });
|
|
529
|
+
};
|
|
530
|
+
Consumer.isLogic = true;
|
|
531
|
+
Context.Consumer = Consumer;
|
|
532
|
+
Context.defaultValue = defaultValue;
|
|
533
|
+
return Context;
|
|
534
|
+
};
|
|
535
|
+
const $useContext = (c) => context(c.value);
|
|
536
|
+
|
|
537
|
+
//#endregion
|
|
538
|
+
//#region src/control/For.ts
|
|
539
|
+
function insertAfter(parentNode, newNode, targetNode) {
|
|
540
|
+
parentNode?.insertBefore(newNode, targetNode.nextSibling);
|
|
541
|
+
}
|
|
542
|
+
const isSame = (a, b, trait) => {
|
|
543
|
+
return Object.is(trait(a), trait(b));
|
|
544
|
+
};
|
|
545
|
+
const defaultTrait = (a) => a;
|
|
546
|
+
const For = (p) => {
|
|
547
|
+
let initialized = false;
|
|
548
|
+
const currentInstance = getCurrentInstance();
|
|
549
|
+
let oldList = [];
|
|
550
|
+
let oldListItems = [];
|
|
551
|
+
let initElements = [];
|
|
552
|
+
effect(() => {
|
|
553
|
+
const props = p.value;
|
|
554
|
+
const trait = props.trait ?? defaultTrait;
|
|
555
|
+
const newList = props.of;
|
|
556
|
+
if (import.meta.env.DEV) {
|
|
557
|
+
const traitMap = /* @__PURE__ */ new Map();
|
|
558
|
+
const duplicates = [];
|
|
559
|
+
for (const item of newList) {
|
|
560
|
+
const traitValue = trait(item);
|
|
561
|
+
if (!traitMap.has(traitValue)) traitMap.set(traitValue, []);
|
|
562
|
+
traitMap.get(traitValue).push(item);
|
|
563
|
+
if (traitMap.get(traitValue).length === 2) duplicates.push(...traitMap.get(traitValue));
|
|
564
|
+
}
|
|
565
|
+
if (duplicates.length > 0) console.warn("[j20 For] Duplicate trait values detected in list. Each item should have a unique trait value for optimal performance. Duplicates found:", duplicates);
|
|
566
|
+
}
|
|
567
|
+
const newListItems = new Array(newList.length);
|
|
568
|
+
let i = 0;
|
|
569
|
+
const l2 = newList.length;
|
|
570
|
+
let e1 = oldList.length - 1;
|
|
571
|
+
let e2 = l2 - 1;
|
|
572
|
+
while (i <= e1 && i <= e2) if (isSame(oldList[i], newList[i], trait)) {
|
|
573
|
+
newListItems[i] = oldListItems[i];
|
|
574
|
+
i++;
|
|
575
|
+
} else break;
|
|
576
|
+
while (i <= e1 && i <= e2) if (isSame(oldList[e1], newList[e2], trait)) {
|
|
577
|
+
newListItems[e2] = oldListItems[e1];
|
|
578
|
+
e1--;
|
|
579
|
+
e2--;
|
|
580
|
+
} else break;
|
|
581
|
+
if (i > e1) {
|
|
582
|
+
if (i <= e2) for (; i <= e2; i++) {
|
|
583
|
+
const newIndex = signal(i);
|
|
584
|
+
const [newInstance, newInstanceFragment] = instanceCreate(() => {
|
|
585
|
+
return untrack(() => props.children)(newList[i], newIndex);
|
|
586
|
+
}, currentInstance);
|
|
587
|
+
if (!initialized) initElements.push(newInstanceFragment);
|
|
588
|
+
else if (i > 0) {
|
|
589
|
+
const prevEl = (newListItems[i - 1]?.instance)?.range[1] ?? currentInstance.range[0];
|
|
590
|
+
insertAfter(prevEl.parentNode, newInstanceFragment, prevEl);
|
|
591
|
+
} else currentInstance.range[0].parentNode?.insertBefore(newInstanceFragment, currentInstance.range[0]);
|
|
592
|
+
newListItems[i] = {
|
|
593
|
+
index: newIndex,
|
|
594
|
+
item: newList[i],
|
|
595
|
+
instance: newInstance
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
} else if (i > e2) while (i <= e1) {
|
|
599
|
+
instanceGetElements(oldListItems[i].instance).forEach((el) => {
|
|
600
|
+
el.parentNode?.removeChild(el);
|
|
601
|
+
});
|
|
602
|
+
instanceDestroy(currentInstance, oldListItems[i].instance);
|
|
603
|
+
i++;
|
|
604
|
+
}
|
|
605
|
+
else {
|
|
606
|
+
const s1 = i;
|
|
607
|
+
const s2 = i;
|
|
608
|
+
const keyToNewIndexMap = /* @__PURE__ */ new Map();
|
|
609
|
+
for (let i$1 = s2; i$1 <= e2; i$1++) keyToNewIndexMap.set(trait(newList[i$1]), i$1);
|
|
610
|
+
const toBePatched = e2 - s2 + 1;
|
|
611
|
+
const newIndexToOldIndexMap = new Array(toBePatched);
|
|
612
|
+
for (let i$1 = 0; i$1 < toBePatched; i$1++) newIndexToOldIndexMap[i$1] = 0;
|
|
613
|
+
let patched = 0;
|
|
614
|
+
let moved = false;
|
|
615
|
+
let maxNewIndexSoFar = 0;
|
|
616
|
+
for (let i$1 = s1; i$1 <= e1; i$1++) {
|
|
617
|
+
if (patched >= toBePatched) {
|
|
618
|
+
instanceGetElements(oldListItems[i$1].instance).forEach((el) => {
|
|
619
|
+
el.parentNode?.removeChild(el);
|
|
620
|
+
});
|
|
621
|
+
instanceDestroy(currentInstance, oldListItems[i$1].instance);
|
|
622
|
+
continue;
|
|
623
|
+
}
|
|
624
|
+
const oldItem = oldList[i$1];
|
|
625
|
+
const oldKey = trait(oldItem);
|
|
626
|
+
const newIndex = keyToNewIndexMap.get(oldKey);
|
|
627
|
+
if (newIndex === void 0) {
|
|
628
|
+
instanceGetElements(oldListItems[i$1].instance).forEach((el) => {
|
|
629
|
+
el.parentNode?.removeChild(el);
|
|
630
|
+
});
|
|
631
|
+
instanceDestroy(currentInstance, oldListItems[i$1].instance);
|
|
632
|
+
} else {
|
|
633
|
+
newIndexToOldIndexMap[newIndex - s2] = i$1 + 1;
|
|
634
|
+
if (newIndex >= maxNewIndexSoFar) maxNewIndexSoFar = newIndex;
|
|
635
|
+
else moved = true;
|
|
636
|
+
newListItems[newIndex] = oldListItems[i$1];
|
|
637
|
+
patched++;
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
const increasingNewIndexSequence = moved ? getSequence(newIndexToOldIndexMap) : [];
|
|
641
|
+
let j = increasingNewIndexSequence.length - 1;
|
|
642
|
+
for (let i$1 = toBePatched - 1; i$1 >= 0; i$1--) {
|
|
643
|
+
const newIndex = s2 + i$1;
|
|
644
|
+
const newItem = newList[newIndex];
|
|
645
|
+
const anchor = newIndex + 1 < l2 ? newListItems[newIndex + 1].instance.range[0] : currentInstance.range[1];
|
|
646
|
+
if (newIndexToOldIndexMap[i$1] === 0) {
|
|
647
|
+
const newIdx = signal(newIndex);
|
|
648
|
+
const [newInstance, newInstanceFragment] = instanceCreate(() => {
|
|
649
|
+
return untrack(() => props.children)(newItem, newIdx);
|
|
650
|
+
}, currentInstance);
|
|
651
|
+
anchor.parentNode?.insertBefore(newInstanceFragment, anchor);
|
|
652
|
+
newListItems[newIndex] = {
|
|
653
|
+
index: newIdx,
|
|
654
|
+
item: newItem,
|
|
655
|
+
instance: newInstance
|
|
656
|
+
};
|
|
657
|
+
} else if (moved) if (j < 0 || i$1 !== increasingNewIndexSequence[j]) {
|
|
658
|
+
const nodeToMove = newListItems[newIndex];
|
|
659
|
+
instanceGetElements(nodeToMove.instance).forEach((el) => {
|
|
660
|
+
anchor.parentNode?.insertBefore(el, anchor);
|
|
661
|
+
});
|
|
662
|
+
} else j--;
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
oldList = newList;
|
|
666
|
+
oldListItems = newListItems;
|
|
667
|
+
currentInstance.children = newListItems.map((item, index) => {
|
|
668
|
+
item.index.value = index;
|
|
669
|
+
return item.instance;
|
|
670
|
+
});
|
|
671
|
+
});
|
|
672
|
+
initialized = true;
|
|
673
|
+
return initElements.splice(0, initElements.length);
|
|
674
|
+
};
|
|
675
|
+
function getSequence(arr) {
|
|
676
|
+
const p = arr.slice();
|
|
677
|
+
const result = [0];
|
|
678
|
+
let i, j, u, v, c;
|
|
679
|
+
const len = arr.length;
|
|
680
|
+
for (i = 0; i < len; i++) {
|
|
681
|
+
const arrI = arr[i];
|
|
682
|
+
if (arrI !== 0) {
|
|
683
|
+
j = result[result.length - 1];
|
|
684
|
+
if (arr[j] < arrI) {
|
|
685
|
+
p[i] = j;
|
|
686
|
+
result.push(i);
|
|
687
|
+
continue;
|
|
688
|
+
}
|
|
689
|
+
u = 0;
|
|
690
|
+
v = result.length - 1;
|
|
691
|
+
while (u < v) {
|
|
692
|
+
c = u + v >> 1;
|
|
693
|
+
if (arr[result[c]] < arrI) u = c + 1;
|
|
694
|
+
else v = c;
|
|
695
|
+
}
|
|
696
|
+
if (arrI < arr[result[u]]) {
|
|
697
|
+
if (u > 0) p[i] = result[u - 1];
|
|
698
|
+
result[u] = i;
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
u = result.length;
|
|
703
|
+
v = result[u - 1];
|
|
704
|
+
while (u-- > 0) {
|
|
705
|
+
result[u] = v;
|
|
706
|
+
v = p[v];
|
|
707
|
+
}
|
|
708
|
+
return result;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
//#endregion
|
|
712
|
+
//#region src/h/createComponent.ts
|
|
713
|
+
const createComponent = (tag, props) => {
|
|
714
|
+
const runner = () => tag(computed(() => props ? props() : {}));
|
|
715
|
+
let [, fragment] = instanceCreate(runner);
|
|
716
|
+
return fragment;
|
|
717
|
+
};
|
|
718
|
+
|
|
719
|
+
//#endregion
|
|
720
|
+
//#region src/control/If.ts
|
|
721
|
+
const If = (p) => {
|
|
722
|
+
const props = p;
|
|
723
|
+
const arr = computed(() => !props.value.of ? [0] : [1]);
|
|
724
|
+
return createComponent(For, () => ({
|
|
725
|
+
get of() {
|
|
726
|
+
return arr.value;
|
|
727
|
+
},
|
|
728
|
+
get children() {
|
|
729
|
+
return (bool) => {
|
|
730
|
+
if (bool) {
|
|
731
|
+
const children = props.value.children;
|
|
732
|
+
if (typeof children === "function") return children(true);
|
|
733
|
+
else return children;
|
|
734
|
+
} else {
|
|
735
|
+
const elseCondition = props.value.else;
|
|
736
|
+
if (typeof elseCondition === "function") return elseCondition(false);
|
|
737
|
+
else return elseCondition;
|
|
738
|
+
}
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
}));
|
|
742
|
+
};
|
|
743
|
+
If.isLogic = true;
|
|
744
|
+
|
|
745
|
+
//#endregion
|
|
746
|
+
//#region src/control/Dynamic.ts
|
|
747
|
+
const Dynamic = (p) => {
|
|
748
|
+
const props = p;
|
|
749
|
+
let count$1 = 0;
|
|
750
|
+
const list = computed(() => {
|
|
751
|
+
props.value.of;
|
|
752
|
+
return [count$1 = (count$1 + 1) % 2];
|
|
753
|
+
});
|
|
754
|
+
return createComponent(For, () => ({
|
|
755
|
+
of: list.value,
|
|
756
|
+
get children() {
|
|
757
|
+
return (item) => {
|
|
758
|
+
const children = props.value.children;
|
|
759
|
+
return typeof children === "function" ? children(item) : children;
|
|
760
|
+
};
|
|
761
|
+
}
|
|
762
|
+
}));
|
|
763
|
+
};
|
|
764
|
+
Dynamic.isLogic = true;
|
|
765
|
+
|
|
766
|
+
//#endregion
|
|
767
|
+
//#region src/control/Switch.ts
|
|
768
|
+
const Switch = (p) => {
|
|
769
|
+
const children = p.value.children;
|
|
770
|
+
const res = computed(() => children.filter((i) => i.valid)[0]);
|
|
771
|
+
return createComponent(For, () => ({
|
|
772
|
+
of: res.value ? [res.value] : [],
|
|
773
|
+
trait: (item) => item.id,
|
|
774
|
+
get children() {
|
|
775
|
+
return (item) => item.children;
|
|
776
|
+
}
|
|
777
|
+
}));
|
|
778
|
+
};
|
|
779
|
+
Switch.isLogic = true;
|
|
780
|
+
const Case = (p) => {
|
|
781
|
+
const props = p;
|
|
782
|
+
return {
|
|
783
|
+
id: generateId(),
|
|
784
|
+
get valid() {
|
|
785
|
+
return props.value.of;
|
|
786
|
+
},
|
|
787
|
+
get children() {
|
|
788
|
+
return props.value.children;
|
|
789
|
+
}
|
|
790
|
+
};
|
|
791
|
+
};
|
|
792
|
+
Case.isLogic = true;
|
|
793
|
+
const Default = (p) => {
|
|
794
|
+
const props = p;
|
|
795
|
+
return {
|
|
796
|
+
id: generateId(),
|
|
797
|
+
get valid() {
|
|
798
|
+
return true;
|
|
799
|
+
},
|
|
800
|
+
get children() {
|
|
801
|
+
return props.value.children;
|
|
802
|
+
}
|
|
803
|
+
};
|
|
804
|
+
};
|
|
805
|
+
Default.isLogic = true;
|
|
806
|
+
|
|
807
|
+
//#endregion
|
|
808
|
+
//#region src/h/createLogicComponent.ts
|
|
809
|
+
const createLogicComponent = (tag, props) => {
|
|
810
|
+
return tag(computed(() => props ? props() : {}));
|
|
811
|
+
};
|
|
812
|
+
|
|
813
|
+
//#endregion
|
|
814
|
+
//#region src/h/createWebComponent.ts
|
|
815
|
+
const createWebComponent = (tag, props) => {
|
|
816
|
+
const runner = () => {
|
|
817
|
+
const customElement = tag.customElement;
|
|
818
|
+
const Exist = customElements.get(customElement.tag);
|
|
819
|
+
let el;
|
|
820
|
+
if (Exist) if (Exist.brand !== BRAND) throw new Error(`Custom element [${customElement.tag}] is already registered`);
|
|
821
|
+
else el = new Exist(true);
|
|
822
|
+
else {
|
|
823
|
+
const NewClass = buildClass(tag);
|
|
824
|
+
customElements.define(customElement.tag, NewClass);
|
|
825
|
+
el = new NewClass(true);
|
|
826
|
+
}
|
|
827
|
+
let childrenGetter = () => untrack(() => props ? props().children : void 0);
|
|
828
|
+
setHost(el);
|
|
829
|
+
const ret = tag(computed(() => {
|
|
830
|
+
const retProps = props ? props() : {};
|
|
831
|
+
childrenGetter = Object.getOwnPropertyDescriptor(retProps, "children")?.get ?? (() => void 0);
|
|
832
|
+
delete retProps.children;
|
|
833
|
+
return retProps;
|
|
834
|
+
}));
|
|
835
|
+
setHost(void 0);
|
|
836
|
+
if (el.customElement.shadow) {
|
|
837
|
+
el.appendToShadowDom(getChildren([].concat(ret)));
|
|
838
|
+
childrenGetter && el.appendToLightDom(getChildren([].concat(childrenGetter())));
|
|
839
|
+
} else el.appendToBody(getChildren([].concat(ret)));
|
|
840
|
+
return el;
|
|
841
|
+
};
|
|
842
|
+
let [, fragment] = instanceCreate(runner);
|
|
843
|
+
return fragment;
|
|
844
|
+
};
|
|
845
|
+
|
|
846
|
+
//#endregion
|
|
847
|
+
//#region src/h/createElement.ts
|
|
848
|
+
const createElement = (tag, props, children) => {
|
|
849
|
+
return tag instanceof Node ? createDom(tag, props, children) : "isLogic" in tag ? createLogicComponent(tag, props) : "customElement" in tag ? createWebComponent(tag, props) : createComponent(tag, props);
|
|
850
|
+
};
|
|
851
|
+
|
|
852
|
+
//#endregion
|
|
853
|
+
//#region src/h/createRoot.ts
|
|
854
|
+
const creatRoot = (boot) => {
|
|
855
|
+
let [instance, fragment] = instanceCreate(() => boot());
|
|
856
|
+
return {
|
|
857
|
+
element: fragment,
|
|
858
|
+
instance
|
|
859
|
+
};
|
|
860
|
+
};
|
|
861
|
+
|
|
862
|
+
//#endregion
|
|
863
|
+
//#region src/jsx-runtime.ts
|
|
864
|
+
const h2 = (tag, props, children) => {
|
|
865
|
+
return createElement(tag, props, children);
|
|
866
|
+
};
|
|
867
|
+
const jsx = h2;
|
|
868
|
+
const jsxs = h2;
|
|
869
|
+
const Fragment = (props) => props.value.children;
|
|
870
|
+
const template = (template$1) => {
|
|
871
|
+
let dom;
|
|
872
|
+
return (isSvg) => {
|
|
873
|
+
if (!dom) {
|
|
874
|
+
const templateEl = isSvg ? document.createElementNS("http://www.w3.org/2000/svg", "svg") : document.createElement("div");
|
|
875
|
+
templateEl.innerHTML = template$1;
|
|
876
|
+
dom = templateEl.firstChild;
|
|
877
|
+
return dom.cloneNode();
|
|
878
|
+
} else return dom.cloneNode();
|
|
879
|
+
};
|
|
880
|
+
};
|
|
881
|
+
|
|
882
|
+
//#endregion
|
|
883
|
+
export { $, $useContext, Case, Computed, Default, Dynamic, Effect, For, Fragment, If, Signal, Switch, computed, creatRoot, createComponent, createContext, createDom, createElement, createLogicComponent, effect, getCurrentInstance, h2, instanceCreate, instanceCreateElement, instanceDestroy, instanceGetElements, instanceInit, jsx, jsxs, ref, registerWebComponent, signal, template, wc };
|