jj 2.5.0 → 2.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -2
- package/SKILL.md +667 -0
- package/lib/bundle.cjs +2031 -0
- package/lib/bundle.cjs.map +1 -0
- package/lib/bundle.d.cts +1782 -0
- package/lib/bundle.d.ts +1782 -1
- package/lib/bundle.global.js +1953 -0
- package/lib/bundle.global.js.map +1 -0
- package/lib/bundle.js +232 -230
- package/lib/bundle.js.map +1 -7
- package/lib/bundle.min.cjs +2 -0
- package/lib/bundle.min.cjs.map +1 -0
- package/lib/bundle.min.d.cts +1782 -0
- package/lib/bundle.min.d.ts +1782 -1
- package/lib/bundle.min.global.js +2 -0
- package/lib/bundle.min.global.js.map +1 -0
- package/lib/bundle.min.js +2 -1
- package/lib/bundle.min.js.map +1 -0
- package/package.json +8 -17
- package/lib/JJD.d.ts +0 -87
- package/lib/JJD.js +0 -119
- package/lib/JJD.js.map +0 -1
- package/lib/JJDF.d.ts +0 -74
- package/lib/JJDF.js +0 -98
- package/lib/JJDF.js.map +0 -1
- package/lib/JJE.d.ts +0 -299
- package/lib/JJE.js +0 -401
- package/lib/JJE.js.map +0 -1
- package/lib/JJET.d.ts +0 -79
- package/lib/JJET.js +0 -114
- package/lib/JJET.js.map +0 -1
- package/lib/JJEx.d.ts +0 -63
- package/lib/JJEx.js +0 -83
- package/lib/JJEx.js.map +0 -1
- package/lib/JJHE.d.ts +0 -109
- package/lib/JJHE.js +0 -136
- package/lib/JJHE.js.map +0 -1
- package/lib/JJN-wrap.d.ts +0 -1
- package/lib/JJN-wrap.js +0 -46
- package/lib/JJN-wrap.js.map +0 -1
- package/lib/JJN.d.ts +0 -126
- package/lib/JJN.js +0 -166
- package/lib/JJN.js.map +0 -1
- package/lib/JJNx.d.ts +0 -126
- package/lib/JJNx.js +0 -157
- package/lib/JJNx.js.map +0 -1
- package/lib/JJSE.d.ts +0 -170
- package/lib/JJSE.js +0 -217
- package/lib/JJSE.js.map +0 -1
- package/lib/JJSR.d.ts +0 -71
- package/lib/JJSR.js +0 -90
- package/lib/JJSR.js.map +0 -1
- package/lib/JJT.d.ts +0 -92
- package/lib/JJT.js +0 -116
- package/lib/JJT.js.map +0 -1
- package/lib/case.d.ts +0 -60
- package/lib/case.js +0 -92
- package/lib/case.js.map +0 -1
- package/lib/components.d.ts +0 -147
- package/lib/components.js +0 -287
- package/lib/components.js.map +0 -1
- package/lib/helpers.d.ts +0 -159
- package/lib/helpers.js +0 -233
- package/lib/helpers.js.map +0 -1
- package/lib/index.d.ts +0 -33
- package/lib/index.js +0 -35
- package/lib/index.js.map +0 -1
- package/lib/internal.d.ts +0 -30
- package/lib/internal.js +0 -35
- package/lib/internal.js.map +0 -1
- package/lib/types.d.ts +0 -65
- package/lib/types.js +0 -2
- package/lib/types.js.map +0 -1
- package/lib/util.d.ts +0 -68
- package/lib/util.js +0 -90
- package/lib/util.js.map +0 -1
- package/llms.txt +0 -214
|
@@ -0,0 +1,1953 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
(() => {
|
|
3
|
+
var __typeError = (msg) => {
|
|
4
|
+
throw TypeError(msg);
|
|
5
|
+
};
|
|
6
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
7
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
8
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
9
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
10
|
+
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
11
|
+
|
|
12
|
+
// node_modules/jty/lib/misc.js
|
|
13
|
+
function isDef(x) {
|
|
14
|
+
return x !== void 0;
|
|
15
|
+
}
|
|
16
|
+
function isFn(x) {
|
|
17
|
+
return typeof x === "function";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// node_modules/jty/lib/number.js
|
|
21
|
+
var { isNaN, isFinite, isInteger } = Number;
|
|
22
|
+
function isNum(x) {
|
|
23
|
+
return typeof x === "number" && !isNaN(x);
|
|
24
|
+
}
|
|
25
|
+
function inRange(x, min, max) {
|
|
26
|
+
if (!isNum(x)) {
|
|
27
|
+
throw new TypeError(`inRange(): "x" must be a number. Got ${x} (${typeof x})`);
|
|
28
|
+
}
|
|
29
|
+
if (isDef(min)) {
|
|
30
|
+
if (!isNum(min)) {
|
|
31
|
+
throw new TypeError(`inRange(): "min" must be a number. Got ${min} (${typeof min})`);
|
|
32
|
+
}
|
|
33
|
+
if (isDef(max)) {
|
|
34
|
+
if (!isNum(max)) {
|
|
35
|
+
throw new TypeError(`inRange(): "max" must be a number. Got ${max} (${typeof max})`);
|
|
36
|
+
}
|
|
37
|
+
if (min > max) {
|
|
38
|
+
return max <= x && x <= min;
|
|
39
|
+
}
|
|
40
|
+
return min <= x && x <= max;
|
|
41
|
+
}
|
|
42
|
+
return x >= min;
|
|
43
|
+
} else if (isDef(max)) {
|
|
44
|
+
if (!isNum(max)) {
|
|
45
|
+
throw new TypeError(`inRange(): "max" must be a number. Got ${max} (${typeof max})`);
|
|
46
|
+
}
|
|
47
|
+
return x <= max;
|
|
48
|
+
}
|
|
49
|
+
throw new TypeError(`inRange(): expected at least min or max to be defined. Got min=${min} and max=${max}`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// node_modules/jty/lib/array.js
|
|
53
|
+
var { isArray } = Array;
|
|
54
|
+
function isArr(x, minLen = 0, maxLen) {
|
|
55
|
+
return isArray(x) && inRange(x.length, minLen, maxLen);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// node_modules/jty/lib/object.js
|
|
59
|
+
var { hasOwnProperty } = Object;
|
|
60
|
+
function isObj(x) {
|
|
61
|
+
return Boolean(x) && typeof x === "object";
|
|
62
|
+
}
|
|
63
|
+
function isA(x, classConstructor) {
|
|
64
|
+
if (!isFn(classConstructor)) {
|
|
65
|
+
throw new TypeError(`Expected a constructor function. Got ${classConstructor} (${typeof classConstructor})`);
|
|
66
|
+
}
|
|
67
|
+
return x instanceof classConstructor;
|
|
68
|
+
}
|
|
69
|
+
function hasProp(x, ...propNames) {
|
|
70
|
+
if (!isObj(x)) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
for (let propName of propNames) {
|
|
74
|
+
if (!(propName in x)) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// node_modules/jty/lib/string.js
|
|
82
|
+
function isStr(x) {
|
|
83
|
+
return typeof x === "string";
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// node_modules/jty/lib/same.js
|
|
87
|
+
var { hasOwnProperty: hasOwnProperty2 } = Object;
|
|
88
|
+
var { isArray: isArray2 } = Array;
|
|
89
|
+
|
|
90
|
+
// src/internal.ts
|
|
91
|
+
function errMsg(varName, expected, received) {
|
|
92
|
+
return `Expected '${varName}' to be ${expected}. Got ${received} (${typeof received})`;
|
|
93
|
+
}
|
|
94
|
+
function typeErr(varName, expected, received) {
|
|
95
|
+
return new TypeError(errMsg(varName, expected, received));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// src/util.ts
|
|
99
|
+
function fileExt(path) {
|
|
100
|
+
if (!isStr(path)) {
|
|
101
|
+
throw typeErr("path", "a string", path);
|
|
102
|
+
}
|
|
103
|
+
const lastDotIndex = path.lastIndexOf(".");
|
|
104
|
+
if (lastDotIndex === -1) {
|
|
105
|
+
return "";
|
|
106
|
+
}
|
|
107
|
+
const ext = path.slice(lastDotIndex + 1);
|
|
108
|
+
if (ext.indexOf("/") !== -1) {
|
|
109
|
+
return "";
|
|
110
|
+
}
|
|
111
|
+
return ext.toLowerCase().trim();
|
|
112
|
+
}
|
|
113
|
+
function nextAnimationFrame() {
|
|
114
|
+
return new Promise((resolve) => requestAnimationFrame(resolve));
|
|
115
|
+
}
|
|
116
|
+
function sleep(ms = 0) {
|
|
117
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
118
|
+
}
|
|
119
|
+
async function cssToStyle(css) {
|
|
120
|
+
const sheet = new CSSStyleSheet();
|
|
121
|
+
return await sheet.replace(css);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// src/case.ts
|
|
125
|
+
function pas2keb(str) {
|
|
126
|
+
if (!isStr(str)) {
|
|
127
|
+
throw typeErr("str", "a string", str);
|
|
128
|
+
}
|
|
129
|
+
if (/[^a-zA-Z0-9_]/.test(str)) {
|
|
130
|
+
throw new SyntaxError(errMsg("str", "alphanumeric characters and underscores", str));
|
|
131
|
+
}
|
|
132
|
+
return str.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/([A-Z])([A-Z][a-z])/g, "$1-$2").replace(/_/g, "-").toLowerCase();
|
|
133
|
+
}
|
|
134
|
+
function keb2pas(str) {
|
|
135
|
+
if (!isStr(str)) {
|
|
136
|
+
throw typeErr("str", "a string", str);
|
|
137
|
+
}
|
|
138
|
+
return str.split("-").filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("") || // Handle strings that were not kebab-case to begin with (e.g. 'single', 'camelCase')
|
|
139
|
+
(str.length > 0 ? str.charAt(0).toUpperCase() + str.slice(1) : "");
|
|
140
|
+
}
|
|
141
|
+
function keb2cam(str) {
|
|
142
|
+
if (!isStr(str)) {
|
|
143
|
+
throw typeErr("str", "a string", str);
|
|
144
|
+
}
|
|
145
|
+
return str.replace(/^-+|-+$/g, "").replace(/-+([a-z])/g, (g, c) => c.toUpperCase());
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// src/wrappers/JJET.ts
|
|
149
|
+
var _ref, _boundHandlers, _JJET_instances, getBoundHandler_fn;
|
|
150
|
+
var _JJET = class _JJET {
|
|
151
|
+
/**
|
|
152
|
+
* Creates a JJET instance.
|
|
153
|
+
*
|
|
154
|
+
* @param ref - The EventTarget to wrap.
|
|
155
|
+
* @throws {TypeError} If `ref` is not an EventTarget.
|
|
156
|
+
*/
|
|
157
|
+
constructor(ref) {
|
|
158
|
+
__privateAdd(this, _JJET_instances);
|
|
159
|
+
__privateAdd(this, _ref);
|
|
160
|
+
__privateAdd(this, _boundHandlers, /* @__PURE__ */ new WeakMap());
|
|
161
|
+
if (!isA(ref, EventTarget)) {
|
|
162
|
+
throw new TypeError(`JJET expects an EventTarget instance. Got ${ref} (${typeof ref}). `);
|
|
163
|
+
}
|
|
164
|
+
__privateSet(this, _ref, ref);
|
|
165
|
+
}
|
|
166
|
+
static from(ref) {
|
|
167
|
+
return new _JJET(ref);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Gets the underlying DOM object.
|
|
171
|
+
*/
|
|
172
|
+
get ref() {
|
|
173
|
+
return __privateGet(this, _ref);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Adds an event listener.
|
|
177
|
+
*
|
|
178
|
+
* @remarks
|
|
179
|
+
* The handler is automatically bound to this JJET instance, so `this` inside the handler
|
|
180
|
+
* refers to the JJET instance, not the DOM element. To access the DOM element, use `this.ref`.
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```ts
|
|
184
|
+
* JJET.from(window).on('resize', function() {
|
|
185
|
+
* console.log(this) // JJET instance
|
|
186
|
+
* console.log(this.ref) // window object
|
|
187
|
+
* })
|
|
188
|
+
* ```
|
|
189
|
+
* @param eventName - The name of the event.
|
|
190
|
+
* @param handler - The event handler.
|
|
191
|
+
* @param options - Optional event listener options.
|
|
192
|
+
* @returns This instance for chaining.
|
|
193
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener | EventTarget.addEventListener}
|
|
194
|
+
*/
|
|
195
|
+
on(eventName, handler, options) {
|
|
196
|
+
const boundHandler = __privateMethod(this, _JJET_instances, getBoundHandler_fn).call(this, handler);
|
|
197
|
+
this.ref.addEventListener(eventName, boundHandler, options);
|
|
198
|
+
return this;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Removes an event listener.
|
|
202
|
+
*
|
|
203
|
+
* @remarks
|
|
204
|
+
* Pass the same handler reference that was used in `on()` to properly remove the listener.
|
|
205
|
+
*
|
|
206
|
+
* @example
|
|
207
|
+
* ```ts
|
|
208
|
+
* const handler = function() { console.log(this) }
|
|
209
|
+
* JJET.from(window).on('resize', handler)
|
|
210
|
+
* JJET.from(window).off('resize', handler)
|
|
211
|
+
* ```
|
|
212
|
+
* @param eventName - The name of the event.
|
|
213
|
+
* @param handler - The event handler.
|
|
214
|
+
* @param options - Optional event listener options or boolean.
|
|
215
|
+
* @returns This instance for chaining.
|
|
216
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener | EventTarget.removeEventListener}
|
|
217
|
+
*/
|
|
218
|
+
off(eventName, handler, options) {
|
|
219
|
+
const boundHandler = __privateMethod(this, _JJET_instances, getBoundHandler_fn).call(this, handler);
|
|
220
|
+
this.ref.removeEventListener(eventName, boundHandler, options);
|
|
221
|
+
return this;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Dispatches an Event at the specified EventTarget.
|
|
225
|
+
*
|
|
226
|
+
* @param event - The Event object to dispatch.
|
|
227
|
+
* @returns This instance for chaining.
|
|
228
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent | EventTarget.dispatchEvent}
|
|
229
|
+
*/
|
|
230
|
+
trigger(event) {
|
|
231
|
+
this.ref.dispatchEvent(event);
|
|
232
|
+
return this;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Runs a function in the context of this JJET instance.
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* ```ts
|
|
239
|
+
* node.run(function() {
|
|
240
|
+
* console.log(this.ref)
|
|
241
|
+
* })
|
|
242
|
+
* ```
|
|
243
|
+
* @remarks
|
|
244
|
+
* If you want to access the current JJ* instance using `this` keyword, you SHOULD use a `function` not an arrow function.
|
|
245
|
+
* If the function throws, `run()` doesn't swallow the exception.
|
|
246
|
+
* So if you're expecting an error, make sure to wrap it in a `try..catch` block and handle the exception.
|
|
247
|
+
* If the function returns a promise, you can `await` on the response.
|
|
248
|
+
*
|
|
249
|
+
* @param fn - The function to run. `this` inside the function will refer to this JJET instance.
|
|
250
|
+
* @param args - Arguments to pass to the function.
|
|
251
|
+
* @returns The return value of the function.
|
|
252
|
+
*/
|
|
253
|
+
run(fn, ...args) {
|
|
254
|
+
return fn.call(this, ...args);
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
_ref = new WeakMap();
|
|
258
|
+
_boundHandlers = new WeakMap();
|
|
259
|
+
_JJET_instances = new WeakSet();
|
|
260
|
+
/**
|
|
261
|
+
* Gets or creates a bound version of the handler.
|
|
262
|
+
*
|
|
263
|
+
* @remarks
|
|
264
|
+
* Bound handlers are cached in a WeakMap to ensure `off()` can properly remove listeners.
|
|
265
|
+
* When the original handler is garbage collected, the bound version is automatically removed.
|
|
266
|
+
*
|
|
267
|
+
* @param handler - The event handler to bind.
|
|
268
|
+
* @returns The bound handler, or null if the input is null.
|
|
269
|
+
*/
|
|
270
|
+
getBoundHandler_fn = function(handler) {
|
|
271
|
+
if (handler === null) return null;
|
|
272
|
+
let bound = __privateGet(this, _boundHandlers).get(handler);
|
|
273
|
+
if (!bound) {
|
|
274
|
+
if (typeof handler === "function") {
|
|
275
|
+
bound = handler.bind(this);
|
|
276
|
+
} else {
|
|
277
|
+
bound = { handleEvent: handler.handleEvent.bind(this) };
|
|
278
|
+
}
|
|
279
|
+
__privateGet(this, _boundHandlers).set(handler, bound);
|
|
280
|
+
}
|
|
281
|
+
return bound;
|
|
282
|
+
};
|
|
283
|
+
var JJET = _JJET;
|
|
284
|
+
|
|
285
|
+
// src/wrappers/JJN-raw.ts
|
|
286
|
+
var JJN = class _JJN extends JJET {
|
|
287
|
+
/**
|
|
288
|
+
* Creates a JJN instance from a Node reference.
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* ```ts
|
|
292
|
+
* const node = JJN.from(document.createTextNode('hello'))
|
|
293
|
+
* ```
|
|
294
|
+
*
|
|
295
|
+
* @param node - The Node instance.
|
|
296
|
+
* @returns A new JJN instance.
|
|
297
|
+
*/
|
|
298
|
+
static from(node) {
|
|
299
|
+
return new _JJN(node);
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Checks if a value can be passed to the `wrap()` or `unwrap()` function.
|
|
303
|
+
*
|
|
304
|
+
* @remarks
|
|
305
|
+
* This is useful for filtering the array that is passed to `append()`, `prepend()` or `setChildren()`
|
|
306
|
+
*
|
|
307
|
+
* @param x an unknown value
|
|
308
|
+
* @returns true if `x` is a string, Node (or its descendents), JJN (or its descendents)
|
|
309
|
+
*/
|
|
310
|
+
static isWrapable(x) {
|
|
311
|
+
return isStr(x) || isA(x, Node) || isA(x, _JJN);
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Wraps a native DOM node or string into the most specific JJ wrapper available.
|
|
315
|
+
*
|
|
316
|
+
* @remarks
|
|
317
|
+
* This function acts as a factory, inspecting the input type and returning the appropriate
|
|
318
|
+
* subclass of `JJN` (e.g., `JJHE` for `HTMLElement`, `JJT` for `Text`).
|
|
319
|
+
*
|
|
320
|
+
* @example
|
|
321
|
+
* ```ts
|
|
322
|
+
* const bodyWrapper = JJN.wrap(document.body) // Returns JJHE
|
|
323
|
+
* const textWrapper = JJN.wrap('Hello') // Returns JJT wrapping a new Text node
|
|
324
|
+
* ```
|
|
325
|
+
*
|
|
326
|
+
* @param raw - The object to wrap. If it's already Wrapped, it'll be returned without any change. We don't double-wrap or clone it.
|
|
327
|
+
* @returns The most granular Wrapped subclass instance. If the input is already wrapped, it'll be returned as is without cloning.
|
|
328
|
+
* @throws {TypeError} If the input is not a Node, string, or JJ wrapper.
|
|
329
|
+
*/
|
|
330
|
+
static wrap(raw) {
|
|
331
|
+
throw new ReferenceError(`The mixin is supposed to override this method.`);
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Extracts the underlying native DOM node from a wrapper.
|
|
335
|
+
*
|
|
336
|
+
* @remarks
|
|
337
|
+
* If the input is already a native Node, it is returned as is.
|
|
338
|
+
* If the input is a string, a new Text node is created and returned.
|
|
339
|
+
*
|
|
340
|
+
* @example
|
|
341
|
+
* ```ts
|
|
342
|
+
* const rawElement = JJN.unwrap(myJJHE) // Returns HTMLElement
|
|
343
|
+
* ```
|
|
344
|
+
*
|
|
345
|
+
* @param obj - The object to unwrap.
|
|
346
|
+
* @returns The underlying DOM node.
|
|
347
|
+
* @throws {TypeError} If the input cannot be unwrapped.
|
|
348
|
+
*/
|
|
349
|
+
static unwrap(obj) {
|
|
350
|
+
if (isStr(obj)) {
|
|
351
|
+
return document.createTextNode(obj);
|
|
352
|
+
}
|
|
353
|
+
if (!isObj(obj)) {
|
|
354
|
+
throw new TypeError(`JJN.unwrap() expects a string, DOM Node, or JJ wrapper. Got ${obj} (${typeof obj}). `);
|
|
355
|
+
}
|
|
356
|
+
if (isA(obj, Node)) {
|
|
357
|
+
return obj;
|
|
358
|
+
}
|
|
359
|
+
if (isA(obj, _JJN)) {
|
|
360
|
+
return obj.ref;
|
|
361
|
+
}
|
|
362
|
+
throw new TypeError(
|
|
363
|
+
`Could not unwrap ${obj} (${typeof obj}). Expected a string, Node, or JJ wrapper. Make sure you're passing a valid DOM element or JJ wrapper.`
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Wraps an iterable object (e.g. an array of wrapped or DOM elements).
|
|
368
|
+
*
|
|
369
|
+
* @example
|
|
370
|
+
* ```ts
|
|
371
|
+
* const wrappedList = JJN.wrapAll(document.querySelectorAll('div'))
|
|
372
|
+
* ```
|
|
373
|
+
*
|
|
374
|
+
* @param iterable - The iterable to wrap.
|
|
375
|
+
* @returns An array of wrapped instances.
|
|
376
|
+
*/
|
|
377
|
+
static wrapAll(iterable) {
|
|
378
|
+
return Array.from(iterable, _JJN.wrap);
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Unwraps an iterable object (e.g. an array or HTMLCollection).
|
|
382
|
+
*
|
|
383
|
+
* @example
|
|
384
|
+
* ```ts
|
|
385
|
+
* const nodes = JJN.unwrapAll(wrappedList)
|
|
386
|
+
* ```
|
|
387
|
+
*
|
|
388
|
+
* @param iterable - The iterable to unwrap.
|
|
389
|
+
* @returns An array of native DOM nodes.
|
|
390
|
+
*/
|
|
391
|
+
static unwrapAll(iterable) {
|
|
392
|
+
return Array.from(iterable, _JJN.unwrap);
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Creates an instance of JJN.
|
|
396
|
+
*
|
|
397
|
+
* @param ref - The Node to wrap.
|
|
398
|
+
* @throws {TypeError} If `ref` is not a Node.
|
|
399
|
+
*/
|
|
400
|
+
constructor(ref) {
|
|
401
|
+
if (!isA(ref, Node)) {
|
|
402
|
+
throw new TypeError(
|
|
403
|
+
`JJN expects a Node instance. Got ${ref} (${typeof ref}). Use JJN.from(node) with a DOM Node, or check that you're passing a valid DOM element.`
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
super(ref);
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Clones the Node.
|
|
410
|
+
*
|
|
411
|
+
* @param deep - If true, clones the subtree.
|
|
412
|
+
* @returns A new wrapped instance of the clone.
|
|
413
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode | Node.cloneNode}
|
|
414
|
+
*/
|
|
415
|
+
clone(deep) {
|
|
416
|
+
return _JJN.wrap(this.ref.cloneNode(deep));
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Creates a Text node from a string and appends it to this Node.
|
|
420
|
+
*
|
|
421
|
+
* @remarks
|
|
422
|
+
* This method is overridden in JJT to append to the existing text content instead.
|
|
423
|
+
*
|
|
424
|
+
* @example
|
|
425
|
+
* ```ts
|
|
426
|
+
* el.addText('Hello ')
|
|
427
|
+
* el.addText('World')
|
|
428
|
+
* ```
|
|
429
|
+
*
|
|
430
|
+
* @param text - The text to add. If null or undefined, nothing is added.
|
|
431
|
+
* @returns This instance for chaining.
|
|
432
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/createTextNode | document.createTextNode}
|
|
433
|
+
*/
|
|
434
|
+
addText(text) {
|
|
435
|
+
if (text) {
|
|
436
|
+
this.ref.appendChild(document.createTextNode(text));
|
|
437
|
+
}
|
|
438
|
+
return this;
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
// src/wrappers/JJNx.ts
|
|
443
|
+
var JJNx = class extends JJN {
|
|
444
|
+
/**
|
|
445
|
+
* Finds the first element matching a selector within this Element.
|
|
446
|
+
*
|
|
447
|
+
* @example
|
|
448
|
+
* ```ts
|
|
449
|
+
* const span = el.find('span') // Returns null if not found
|
|
450
|
+
* const span = el.find('span', true) // Throws if not found
|
|
451
|
+
* ```
|
|
452
|
+
*
|
|
453
|
+
* @param selector - The CSS selector.
|
|
454
|
+
* @param required - Whether to throw an error if not found. Defaults to false.
|
|
455
|
+
* @returns The wrapped element, or null if not found and required is false.
|
|
456
|
+
* @throws {TypeError} If selector is not a string or element not found and required is true.
|
|
457
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector | Element.querySelector}
|
|
458
|
+
*/
|
|
459
|
+
find(selector, required = false) {
|
|
460
|
+
const queryResult = this.ref.querySelector(selector);
|
|
461
|
+
if (queryResult) {
|
|
462
|
+
return JJN.wrap(queryResult);
|
|
463
|
+
}
|
|
464
|
+
if (required) {
|
|
465
|
+
throw new TypeError(`No element matched query "${selector}"`);
|
|
466
|
+
}
|
|
467
|
+
return null;
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Finds all elements matching a selector within this Element.
|
|
471
|
+
*
|
|
472
|
+
* @example
|
|
473
|
+
* ```ts
|
|
474
|
+
* const items = el.findAll('li')
|
|
475
|
+
* ```
|
|
476
|
+
*
|
|
477
|
+
* @param selector - The CSS selector.
|
|
478
|
+
* @returns An array of wrapped elements.
|
|
479
|
+
* @throws {TypeError} If selector is not a string.
|
|
480
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll | Element.querySelectorAll}
|
|
481
|
+
*/
|
|
482
|
+
findAll(selector) {
|
|
483
|
+
return JJN.wrapAll(this.ref.querySelectorAll(selector));
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Appends children to this Element.
|
|
487
|
+
*
|
|
488
|
+
* @example
|
|
489
|
+
* ```ts
|
|
490
|
+
* el.addChild(h('span', null, 'hello'))
|
|
491
|
+
* ```
|
|
492
|
+
*
|
|
493
|
+
* @remarks
|
|
494
|
+
* To make template codes easier, this function ignores any child that is not possible to `wrap()` (e.g. undefined, null, false).
|
|
495
|
+
*
|
|
496
|
+
* @param children - The children to append.
|
|
497
|
+
* @returns This instance for chaining.
|
|
498
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/append | Element.append}
|
|
499
|
+
*/
|
|
500
|
+
addChild(...children) {
|
|
501
|
+
const nodes = JJN.unwrapAll(children.filter(JJN.isWrapable));
|
|
502
|
+
this.ref.append(...nodes);
|
|
503
|
+
return this;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Prepends children to this Element.
|
|
507
|
+
*
|
|
508
|
+
* @example
|
|
509
|
+
* ```ts
|
|
510
|
+
* el.preChild(h('span', null, 'first'))
|
|
511
|
+
* ```
|
|
512
|
+
*
|
|
513
|
+
* @remarks
|
|
514
|
+
* To make template codes easier, this function ignores any child that is not possible to `wrap()` (e.g. undefined, null, false).
|
|
515
|
+
*
|
|
516
|
+
* @param children - The children to prepend.
|
|
517
|
+
* @returns This instance for chaining.
|
|
518
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/prepend | Element.prepend}
|
|
519
|
+
*/
|
|
520
|
+
preChild(...children) {
|
|
521
|
+
const nodes = JJN.unwrapAll(children.filter(JJN.isWrapable));
|
|
522
|
+
this.ref.prepend(...nodes);
|
|
523
|
+
return this;
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Maps an array to children and appends them.
|
|
527
|
+
*
|
|
528
|
+
* @example
|
|
529
|
+
* ```ts
|
|
530
|
+
* node.addChildMap(['a', 'b'], item => h('li', null, item))
|
|
531
|
+
* ```
|
|
532
|
+
*
|
|
533
|
+
* @remarks
|
|
534
|
+
* To make template codes easier, this function ignores any child that is not possible to `wrap()` (e.g. undefined, null, false).
|
|
535
|
+
*
|
|
536
|
+
* @param array - The source array.
|
|
537
|
+
* @param mapFn - The mapping function returning a Wrappable.
|
|
538
|
+
* @returns This instance for chaining.
|
|
539
|
+
*/
|
|
540
|
+
addChildMap(array, mapFn) {
|
|
541
|
+
return this.addChild(...array.map(mapFn));
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* Maps an array to children and prepends them.
|
|
545
|
+
*
|
|
546
|
+
* @example
|
|
547
|
+
* ```ts
|
|
548
|
+
* node.preChildMap(['a', 'b'], item => JJHE.create('li').setText(item))
|
|
549
|
+
* ```
|
|
550
|
+
*
|
|
551
|
+
* @remarks
|
|
552
|
+
* To make template codes easier, this function ignores any child that is not possible to `wrap()` (e.g. undefined, null, false).
|
|
553
|
+
*
|
|
554
|
+
* @param array - The source array.
|
|
555
|
+
* @param mapFn - The mapping function.
|
|
556
|
+
* @returns This instance for chaining.
|
|
557
|
+
*/
|
|
558
|
+
preChildMap(array, mapFn) {
|
|
559
|
+
return this.preChild(...array.map(mapFn));
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Replaces the existing children of an Element with a specified new set of children.
|
|
563
|
+
*
|
|
564
|
+
* @remarks
|
|
565
|
+
* If no children are provided, it empties the Element.
|
|
566
|
+
* To make template codes easier, this function ignores any child that is not possible to `wrap()` (e.g. undefined, null, false).
|
|
567
|
+
*
|
|
568
|
+
* @example
|
|
569
|
+
* ```ts
|
|
570
|
+
* el.setChildren(h('p', null, 'New Content'))
|
|
571
|
+
* ```
|
|
572
|
+
* @param children - The children to replace with.
|
|
573
|
+
* @returns This instance for chaining.
|
|
574
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/replaceChildren | Element.replaceChildren}
|
|
575
|
+
*/
|
|
576
|
+
setChildren(...children) {
|
|
577
|
+
const nodes = JJN.unwrapAll(children.filter(JJN.isWrapable));
|
|
578
|
+
this.ref.replaceChildren(...nodes);
|
|
579
|
+
return this;
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Removes all children from this Element.
|
|
583
|
+
*
|
|
584
|
+
* @example
|
|
585
|
+
* ```ts
|
|
586
|
+
* el.empty()
|
|
587
|
+
* ```
|
|
588
|
+
*
|
|
589
|
+
* @returns This instance for chaining.
|
|
590
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/replaceChildren | Element.setChildren}
|
|
591
|
+
*/
|
|
592
|
+
empty() {
|
|
593
|
+
this.setChildren();
|
|
594
|
+
return this;
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
|
|
598
|
+
// src/wrappers/JJDF.ts
|
|
599
|
+
var JJDF = class _JJDF extends JJNx {
|
|
600
|
+
/**
|
|
601
|
+
* Creates a JJDF instance from a DocumentFragment reference.
|
|
602
|
+
*
|
|
603
|
+
* @example
|
|
604
|
+
* ```ts
|
|
605
|
+
* const frag = JJDF.from(myFrag)
|
|
606
|
+
* ```
|
|
607
|
+
*
|
|
608
|
+
*
|
|
609
|
+
* @param ref - The DocumentFragment instance.
|
|
610
|
+
* @returns A new JJDF instance.
|
|
611
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment | DocumentFragment}
|
|
612
|
+
*/
|
|
613
|
+
static from(ref) {
|
|
614
|
+
return new _JJDF(ref);
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Creates a new empty JJDF instance (wraps a new DocumentFragment).
|
|
618
|
+
*
|
|
619
|
+
* @example
|
|
620
|
+
* ```ts
|
|
621
|
+
* const frag = JJDF.create()
|
|
622
|
+
* ```
|
|
623
|
+
*
|
|
624
|
+
* @returns A new JJDF instance.
|
|
625
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/createDocumentFragment | document.createDocumentFragment}
|
|
626
|
+
*/
|
|
627
|
+
static create() {
|
|
628
|
+
return new _JJDF(document.createDocumentFragment());
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* Creates an instance of JJDF.
|
|
632
|
+
*
|
|
633
|
+
* @param ref - The DocumentFragment instance to wrap.
|
|
634
|
+
* @throws {TypeError} If `ref` is not a DocumentFragment.
|
|
635
|
+
*/
|
|
636
|
+
constructor(ref) {
|
|
637
|
+
if (!isA(ref, DocumentFragment)) {
|
|
638
|
+
throw typeErr("ref", "a DocumentFragment", ref);
|
|
639
|
+
}
|
|
640
|
+
super(ref);
|
|
641
|
+
}
|
|
642
|
+
};
|
|
643
|
+
|
|
644
|
+
// src/wrappers/JJSR.ts
|
|
645
|
+
var JJSR = class _JJSR extends JJDF {
|
|
646
|
+
/**
|
|
647
|
+
* Creates a JJSR instance from a ShadowRoot reference.
|
|
648
|
+
*
|
|
649
|
+
* @example
|
|
650
|
+
* ```ts
|
|
651
|
+
* const shadow = JJSR.from(element.shadowRoot)
|
|
652
|
+
* ```
|
|
653
|
+
*
|
|
654
|
+
* @param shadowRoot - The ShadowRoot instance.
|
|
655
|
+
* @returns A new JJSR instance.
|
|
656
|
+
*/
|
|
657
|
+
static from(shadowRoot) {
|
|
658
|
+
return new _JJSR(shadowRoot);
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* Creates an instance of JJSR.
|
|
662
|
+
*
|
|
663
|
+
* @param shadowRoot - The ShadowRoot to wrap.
|
|
664
|
+
* @throws {TypeError} If `shadowRoot` is not a ShadowRoot.
|
|
665
|
+
*/
|
|
666
|
+
constructor(shadowRoot) {
|
|
667
|
+
if (!isA(shadowRoot, ShadowRoot)) {
|
|
668
|
+
throw new TypeError(
|
|
669
|
+
`JJSR expects a ShadowRoot instance. Got ${shadowRoot} (${typeof shadowRoot}). Access a shadow root using element.shadowRoot after calling element.attachShadow().`
|
|
670
|
+
);
|
|
671
|
+
}
|
|
672
|
+
super(shadowRoot);
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Gets the inner HTML of the ShadowRoot.
|
|
676
|
+
*
|
|
677
|
+
* @returns The inner HTML string.
|
|
678
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML | Element.innerHTML}
|
|
679
|
+
*/
|
|
680
|
+
getHTML() {
|
|
681
|
+
return this.ref.innerHTML;
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* Sets the inner HTML of the ShadowRoot.
|
|
685
|
+
*
|
|
686
|
+
* @example
|
|
687
|
+
* ```ts
|
|
688
|
+
* shadow.setHTML('<p>Hello</p>', true)
|
|
689
|
+
* ```
|
|
690
|
+
*
|
|
691
|
+
* @param html - The HTML string to set, or null/undefined to clear.
|
|
692
|
+
* @param unsafe - explicit opt-in to set innerHTML. must be true if html is provided.
|
|
693
|
+
* @returns This instance for chaining.
|
|
694
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML | Element.innerHTML}
|
|
695
|
+
*/
|
|
696
|
+
setHTML(html, unsafe) {
|
|
697
|
+
if (html && unsafe !== true) {
|
|
698
|
+
throw new Error(
|
|
699
|
+
`Setting innerHTML is unsafe. Pass true as the second argument to confirm you know what you are doing.`
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
this.ref.innerHTML = html ?? "";
|
|
703
|
+
return this;
|
|
704
|
+
}
|
|
705
|
+
/**
|
|
706
|
+
* Adds constructed stylesheets to the ShadowRoot.
|
|
707
|
+
*
|
|
708
|
+
* @example
|
|
709
|
+
* ```ts
|
|
710
|
+
* const sheet = new CSSStyleSheet()
|
|
711
|
+
* sheet.replaceSync('p { color: red; }')
|
|
712
|
+
* shadow.addStyleSheets(sheet)
|
|
713
|
+
* ```
|
|
714
|
+
*
|
|
715
|
+
* @param styleSheets - The stylesheets to add.
|
|
716
|
+
* @returns This instance for chaining.
|
|
717
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot/adoptedStyleSheets | ShadowRoot.adoptedStyleSheets}
|
|
718
|
+
*/
|
|
719
|
+
addStyleSheets(...styleSheets) {
|
|
720
|
+
this.ref.adoptedStyleSheets.push(...styleSheets);
|
|
721
|
+
return this;
|
|
722
|
+
}
|
|
723
|
+
};
|
|
724
|
+
|
|
725
|
+
// src/wrappers/JJE.ts
|
|
726
|
+
var JJE = class _JJE extends JJNx {
|
|
727
|
+
/**
|
|
728
|
+
* Creates a JJE instance from an Element reference.
|
|
729
|
+
*
|
|
730
|
+
* @example
|
|
731
|
+
* ```ts
|
|
732
|
+
* const el = JJE.from(document.querySelector('.my-class'))
|
|
733
|
+
* ```
|
|
734
|
+
*
|
|
735
|
+
* @param ref - The Element instance.
|
|
736
|
+
* @returns A new JJE instance.
|
|
737
|
+
*/
|
|
738
|
+
static from(ref) {
|
|
739
|
+
return new _JJE(ref);
|
|
740
|
+
}
|
|
741
|
+
/**
|
|
742
|
+
* Creates an instance of JJE.
|
|
743
|
+
*
|
|
744
|
+
* @param ref - The Element to wrap.
|
|
745
|
+
* @throws {TypeError} If `ref` is not an Element.
|
|
746
|
+
*/
|
|
747
|
+
constructor(ref) {
|
|
748
|
+
if (!isA(ref, Element)) {
|
|
749
|
+
throw new TypeError(
|
|
750
|
+
`JJE expects an Element instance. Got ${ref} (${typeof ref}). Use JJE.from(element) with a DOM Element, or use the specific wrapper (JJHE for HTMLElement, JJSE for SVGElement).`
|
|
751
|
+
);
|
|
752
|
+
}
|
|
753
|
+
super(ref);
|
|
754
|
+
}
|
|
755
|
+
/**
|
|
756
|
+
* Gets the value of an attribute.
|
|
757
|
+
*
|
|
758
|
+
* @param name - The name of the attribute.
|
|
759
|
+
* @returns The attribute value, or null if not present.
|
|
760
|
+
* @throws {TypeError} If `name` is not a string.
|
|
761
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttribute | Element.getAttribute}
|
|
762
|
+
*/
|
|
763
|
+
getAttr(name) {
|
|
764
|
+
if (!isStr(name)) {
|
|
765
|
+
throw typeErr("name", "a string", name);
|
|
766
|
+
}
|
|
767
|
+
return this.ref.getAttribute(name);
|
|
768
|
+
}
|
|
769
|
+
/**
|
|
770
|
+
* Checks if an attribute exists.
|
|
771
|
+
*
|
|
772
|
+
* @param name - The name of the attribute.
|
|
773
|
+
* @returns `true` if the attribute exists, otherwise `false`.
|
|
774
|
+
* @throws {TypeError} If `name` is not a string.
|
|
775
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/hasAttribute | Element.hasAttribute}
|
|
776
|
+
*/
|
|
777
|
+
hasAttr(name) {
|
|
778
|
+
if (!isStr(name)) {
|
|
779
|
+
throw typeErr("name", "a string", name);
|
|
780
|
+
}
|
|
781
|
+
return this.ref.hasAttribute(name);
|
|
782
|
+
}
|
|
783
|
+
setAttr(nameOrObj, value) {
|
|
784
|
+
if (typeof nameOrObj === "string") {
|
|
785
|
+
this.ref.setAttribute(nameOrObj, value);
|
|
786
|
+
} else if (isObj(nameOrObj)) {
|
|
787
|
+
for (const [k, v] of Object.entries(nameOrObj)) {
|
|
788
|
+
this.ref.setAttribute(k, v);
|
|
789
|
+
}
|
|
790
|
+
} else {
|
|
791
|
+
throw typeErr("nameOrObj", "a string or object", nameOrObj);
|
|
792
|
+
}
|
|
793
|
+
return this;
|
|
794
|
+
}
|
|
795
|
+
/**
|
|
796
|
+
* Removes one or more attributes from the Element.
|
|
797
|
+
*
|
|
798
|
+
* @example
|
|
799
|
+
* ```ts
|
|
800
|
+
* el.rmAttr('disabled') // Remove single
|
|
801
|
+
* el.rmAttr('hidden', 'aria-hidden') // Remove multiple
|
|
802
|
+
* ```
|
|
803
|
+
*
|
|
804
|
+
* @param names - The name(s) of the attribute(s) to remove.
|
|
805
|
+
* @returns This instance for chaining.
|
|
806
|
+
* @throws {TypeError} If any name is not a string.
|
|
807
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/removeAttribute | Element.removeAttribute}
|
|
808
|
+
*/
|
|
809
|
+
rmAttr(...names) {
|
|
810
|
+
for (const name of names) {
|
|
811
|
+
if (!isStr(name)) {
|
|
812
|
+
throw typeErr("name", "a string", name);
|
|
813
|
+
}
|
|
814
|
+
this.ref.removeAttribute(name);
|
|
815
|
+
}
|
|
816
|
+
return this;
|
|
817
|
+
}
|
|
818
|
+
/**
|
|
819
|
+
* Gets the value of an ARIA attribute.
|
|
820
|
+
*
|
|
821
|
+
* @remarks
|
|
822
|
+
* Automatically prepends `aria-` to the name.
|
|
823
|
+
*
|
|
824
|
+
* @example
|
|
825
|
+
* ```ts
|
|
826
|
+
* el.getAria('label') // gets 'aria-label'
|
|
827
|
+
* ```
|
|
828
|
+
*
|
|
829
|
+
* @param name - The ARIA attribute suffix (e.g., 'label' for 'aria-label').
|
|
830
|
+
* @returns The attribute value, or null if not present.
|
|
831
|
+
* @throws {TypeError} If `name` is not a string.
|
|
832
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes | ARIA Attributes}
|
|
833
|
+
*/
|
|
834
|
+
getAria(name) {
|
|
835
|
+
if (!isStr(name)) {
|
|
836
|
+
throw typeErr("name", "a string", name);
|
|
837
|
+
}
|
|
838
|
+
return this.ref.getAttribute(`aria-${name}`);
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* Checks if an ARIA attribute exists.
|
|
842
|
+
*
|
|
843
|
+
* @param name - The ARIA attribute suffix.
|
|
844
|
+
* @returns `true` if the attribute exists.
|
|
845
|
+
* @throws {TypeError} If `name` is not a string.
|
|
846
|
+
*/
|
|
847
|
+
hasAria(name) {
|
|
848
|
+
if (!isStr(name)) {
|
|
849
|
+
throw typeErr("name", "a string", name);
|
|
850
|
+
}
|
|
851
|
+
return this.ref.hasAttribute(`aria-${name}`);
|
|
852
|
+
}
|
|
853
|
+
setAria(nameOrObj, value) {
|
|
854
|
+
if (isStr(nameOrObj)) {
|
|
855
|
+
this.ref.setAttribute(`aria-${nameOrObj}`, value);
|
|
856
|
+
} else if (isObj(nameOrObj)) {
|
|
857
|
+
for (const [k, v] of Object.entries(nameOrObj)) {
|
|
858
|
+
this.ref.setAttribute(`aria-${k}`, v);
|
|
859
|
+
}
|
|
860
|
+
} else {
|
|
861
|
+
throw typeErr("nameOrObj", "a string or object", nameOrObj);
|
|
862
|
+
}
|
|
863
|
+
return this;
|
|
864
|
+
}
|
|
865
|
+
/**
|
|
866
|
+
* Removes one or more ARIA attributes from the Element.
|
|
867
|
+
*
|
|
868
|
+
* @example
|
|
869
|
+
* ```ts
|
|
870
|
+
* el.rmAria('hidden') // Remove single
|
|
871
|
+
* el.rmAria('label', 'hidden') // Remove multiple
|
|
872
|
+
* ```
|
|
873
|
+
*
|
|
874
|
+
* @param names - The ARIA attribute suffix(es) to remove.
|
|
875
|
+
* @returns This instance for chaining.
|
|
876
|
+
* @throws {TypeError} If any name is not a string.
|
|
877
|
+
*/
|
|
878
|
+
rmAria(...names) {
|
|
879
|
+
for (const name of names) {
|
|
880
|
+
if (!isStr(name)) {
|
|
881
|
+
throw typeErr("name", "a string", name);
|
|
882
|
+
}
|
|
883
|
+
this.ref.removeAttribute(`aria-${name}`);
|
|
884
|
+
}
|
|
885
|
+
return this;
|
|
886
|
+
}
|
|
887
|
+
/**
|
|
888
|
+
* Gets the class attribute.
|
|
889
|
+
*
|
|
890
|
+
* @returns The class attribute value, or null if not present.
|
|
891
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/className | Element.className}
|
|
892
|
+
*/
|
|
893
|
+
getClass() {
|
|
894
|
+
return this.getAttr("class");
|
|
895
|
+
}
|
|
896
|
+
setClass(classNameOrMap) {
|
|
897
|
+
if (typeof classNameOrMap === "string") {
|
|
898
|
+
return this.setAttr("class", classNameOrMap);
|
|
899
|
+
}
|
|
900
|
+
for (const [className, condition] of Object.entries(classNameOrMap)) {
|
|
901
|
+
if (condition) {
|
|
902
|
+
this.ref.classList.add(className);
|
|
903
|
+
} else {
|
|
904
|
+
this.ref.classList.remove(className);
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
return this;
|
|
908
|
+
}
|
|
909
|
+
/**
|
|
910
|
+
* Adds one or more classes to the Element.
|
|
911
|
+
*
|
|
912
|
+
* @example
|
|
913
|
+
* ```ts
|
|
914
|
+
* el.addClass('btn', 'btn-primary')
|
|
915
|
+
* ```
|
|
916
|
+
*
|
|
917
|
+
* @param classNames - The classes to add.
|
|
918
|
+
* @returns This instance for chaining.
|
|
919
|
+
* @throws {TypeError} If any class name is not a string.
|
|
920
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/classList | Element.classList}
|
|
921
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/add | DOMTokenList.add}
|
|
922
|
+
*/
|
|
923
|
+
addClass(...classNames) {
|
|
924
|
+
for (const className of classNames) {
|
|
925
|
+
if (!isStr(className)) {
|
|
926
|
+
throw typeErr("className", "a string", className);
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
this.ref.classList.add(...classNames);
|
|
930
|
+
return this;
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* Removes one or more classes from the Element.
|
|
934
|
+
*
|
|
935
|
+
* @example
|
|
936
|
+
* ```ts
|
|
937
|
+
* el.rmClass('active') // Remove single
|
|
938
|
+
* el.rmClass('btn', 'btn-primary') // Remove multiple
|
|
939
|
+
* ```
|
|
940
|
+
*
|
|
941
|
+
* @param classNames - The classes to remove.
|
|
942
|
+
* @returns This instance for chaining.
|
|
943
|
+
* @throws {TypeError} If any class name is not a string.
|
|
944
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/classList | Element.classList}
|
|
945
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/remove | DOMTokenList.remove}
|
|
946
|
+
*/
|
|
947
|
+
rmClass(...classNames) {
|
|
948
|
+
for (const className of classNames) {
|
|
949
|
+
if (!isStr(className)) {
|
|
950
|
+
throw typeErr("className", "a string", className);
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
this.ref.classList.remove(...classNames);
|
|
954
|
+
return this;
|
|
955
|
+
}
|
|
956
|
+
/**
|
|
957
|
+
* Checks if the Element has a specific class.
|
|
958
|
+
*
|
|
959
|
+
* @param className - The class to check for.
|
|
960
|
+
* @returns `true` if the element has the class.
|
|
961
|
+
* @throws {TypeError} If `className` is not a string.
|
|
962
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/classList | Element.classList}
|
|
963
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/contains | DOMTokenList.contains}
|
|
964
|
+
*/
|
|
965
|
+
hasClass(className) {
|
|
966
|
+
if (!isStr(className)) {
|
|
967
|
+
throw typeErr("className", "a string", className);
|
|
968
|
+
}
|
|
969
|
+
return this.ref.classList.contains(className);
|
|
970
|
+
}
|
|
971
|
+
/**
|
|
972
|
+
* Toggles a class on the Element.
|
|
973
|
+
*
|
|
974
|
+
* @param className - The class to toggle.
|
|
975
|
+
* @returns This instance for chaining.
|
|
976
|
+
* @throws {TypeError} If `className` is not a string.
|
|
977
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/classList | Element.classList}
|
|
978
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/toggle | DOMTokenList.toggle}
|
|
979
|
+
*/
|
|
980
|
+
toggleClass(className) {
|
|
981
|
+
if (!isStr(className)) {
|
|
982
|
+
throw typeErr("className", "a string", className);
|
|
983
|
+
}
|
|
984
|
+
this.ref.classList.toggle(className);
|
|
985
|
+
return this;
|
|
986
|
+
}
|
|
987
|
+
/**
|
|
988
|
+
* Replaces a class with another one
|
|
989
|
+
*
|
|
990
|
+
* @remarks
|
|
991
|
+
* If the `oldClassName` doesn't exist, the `newClassName` isn't added
|
|
992
|
+
*
|
|
993
|
+
* @param oldClassName - The class name to remove
|
|
994
|
+
* @param newClassName - The class name to add
|
|
995
|
+
* @throws {TypeError} If either className is not a string.
|
|
996
|
+
*/
|
|
997
|
+
replaceClass(oldClassName, newClassName) {
|
|
998
|
+
if (!isStr(oldClassName)) {
|
|
999
|
+
throw typeErr("oldClassName", "a string", oldClassName);
|
|
1000
|
+
}
|
|
1001
|
+
if (!isStr(newClassName)) {
|
|
1002
|
+
throw typeErr("newClassName", "a string", newClassName);
|
|
1003
|
+
}
|
|
1004
|
+
this.ref.classList.replace(oldClassName, newClassName);
|
|
1005
|
+
return this;
|
|
1006
|
+
}
|
|
1007
|
+
/**
|
|
1008
|
+
* Finds the closest ancestor (or self) that matches a CSS selector.
|
|
1009
|
+
*
|
|
1010
|
+
* @remarks
|
|
1011
|
+
* Returns `null` when no matching ancestor is found.
|
|
1012
|
+
*
|
|
1013
|
+
* @example
|
|
1014
|
+
* ```ts
|
|
1015
|
+
* const button = JJE.from(document.querySelector('button'))
|
|
1016
|
+
* const card = button.closest('.card')
|
|
1017
|
+
* if (card) {
|
|
1018
|
+
* card.addClass('has-action')
|
|
1019
|
+
* }
|
|
1020
|
+
* ```
|
|
1021
|
+
*
|
|
1022
|
+
* @param selector - The CSS selector to search for.
|
|
1023
|
+
* @returns A JJE wrapping the closest match, or null when none exists.
|
|
1024
|
+
* @throws {TypeError} If `selector` is not a string.
|
|
1025
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/closest | Element.closest}
|
|
1026
|
+
*/
|
|
1027
|
+
closest(selector) {
|
|
1028
|
+
if (!isStr(selector)) {
|
|
1029
|
+
throw typeErr("selector", "a string", selector);
|
|
1030
|
+
}
|
|
1031
|
+
const match = this.ref.closest(selector);
|
|
1032
|
+
return match ? JJN.wrap(match) : null;
|
|
1033
|
+
}
|
|
1034
|
+
/**
|
|
1035
|
+
|
|
1036
|
+
* Hides the Element by setting the `hidden` attribute and `aria-hidden="true"`.
|
|
1037
|
+
*
|
|
1038
|
+
* @returns This instance for chaining.
|
|
1039
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/hidden | hidden attribute}
|
|
1040
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden | aria-hidden}
|
|
1041
|
+
*/
|
|
1042
|
+
hide() {
|
|
1043
|
+
return this.setAttr("hidden", "").setAttr("aria-hidden", "true");
|
|
1044
|
+
}
|
|
1045
|
+
/**
|
|
1046
|
+
* Shows the Element by removing the `hidden` and `aria-hidden` attributes.
|
|
1047
|
+
*
|
|
1048
|
+
* @returns This instance for chaining.
|
|
1049
|
+
*/
|
|
1050
|
+
show() {
|
|
1051
|
+
return this.rmAttr("hidden", "aria-hidden");
|
|
1052
|
+
}
|
|
1053
|
+
/**
|
|
1054
|
+
* Disables the Element by setting the `disabled` attribute and `aria-disabled="true"`.
|
|
1055
|
+
*
|
|
1056
|
+
* @returns This instance for chaining.
|
|
1057
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/disabled | disabled attribute}
|
|
1058
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-disabled | aria-disabled}
|
|
1059
|
+
*/
|
|
1060
|
+
disable() {
|
|
1061
|
+
return this.setAttr("disabled", "").setAttr("aria-disabled", "true");
|
|
1062
|
+
}
|
|
1063
|
+
/**
|
|
1064
|
+
* Enables the Element by removing the `disabled` and `aria-disabled` attributes.
|
|
1065
|
+
*
|
|
1066
|
+
* @returns This instance for chaining.
|
|
1067
|
+
*/
|
|
1068
|
+
enable() {
|
|
1069
|
+
return this.rmAttr("disabled", "aria-disabled");
|
|
1070
|
+
}
|
|
1071
|
+
/**
|
|
1072
|
+
* Gets the inner HTML of the Element.
|
|
1073
|
+
*
|
|
1074
|
+
* @remarks
|
|
1075
|
+
* This method operates on `innerHTML`. The method name is kept short for convenience.
|
|
1076
|
+
*
|
|
1077
|
+
* @returns The inner HTML string.
|
|
1078
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML | Element.innerHTML}
|
|
1079
|
+
*/
|
|
1080
|
+
getHTML() {
|
|
1081
|
+
return this.ref.innerHTML;
|
|
1082
|
+
}
|
|
1083
|
+
/**
|
|
1084
|
+
* Sets the inner HTML of the Element.
|
|
1085
|
+
*
|
|
1086
|
+
* @remarks
|
|
1087
|
+
* This method operates on `innerHTML`. The method name is kept short for convenience.
|
|
1088
|
+
* Pass an empty string, `null`, or `undefined` to clear the content.
|
|
1089
|
+
*
|
|
1090
|
+
* @param html - The HTML string to set, or null/undefined to clear.
|
|
1091
|
+
* @param unsafe - explicit opt-in to set innerHTML. must be true if html is provided.
|
|
1092
|
+
* @returns This instance for chaining.
|
|
1093
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML | Element.innerHTML}
|
|
1094
|
+
*/
|
|
1095
|
+
setHTML(html, unsafe) {
|
|
1096
|
+
if (html && unsafe !== true) {
|
|
1097
|
+
throw new Error(
|
|
1098
|
+
`Setting innerHTML is unsafe. Pass true as the second argument to confirm you know what you are doing.`
|
|
1099
|
+
);
|
|
1100
|
+
}
|
|
1101
|
+
this.ref.innerHTML = html ?? "";
|
|
1102
|
+
return this;
|
|
1103
|
+
}
|
|
1104
|
+
/**
|
|
1105
|
+
* Attaches a Shadow DOM to the Element and optionally sets its content and styles.
|
|
1106
|
+
*
|
|
1107
|
+
* @remarks
|
|
1108
|
+
* We prevent FOUC by assigning the template and CSS in one go.
|
|
1109
|
+
* **Note:** You can't attach a shadow root to every type of element. There are some that can't have a
|
|
1110
|
+
* shadow DOM for security reasons (for example `<a>`).
|
|
1111
|
+
*
|
|
1112
|
+
* @param mode - The encapsulation mode ('open' or 'closed'). Defaults to 'open'.
|
|
1113
|
+
* @param config - Optional configuration object containing `template` (HTML string) and `styles` (array of CSSStyleSheet).
|
|
1114
|
+
* @returns This instance for chaining.
|
|
1115
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow | Element.attachShadow}
|
|
1116
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot/adoptedStyleSheets | ShadowRoot.adoptedStyleSheets}
|
|
1117
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/adoptedStyleSheets | Document.adoptedStyleSheets}
|
|
1118
|
+
*/
|
|
1119
|
+
initShadow(mode = "open", config) {
|
|
1120
|
+
const shadowRoot = this.ref.shadowRoot ?? this.ref.attachShadow({ mode });
|
|
1121
|
+
if (isObj(config)) {
|
|
1122
|
+
const { template, styles } = config;
|
|
1123
|
+
if (template) {
|
|
1124
|
+
if (isStr(template)) {
|
|
1125
|
+
shadowRoot.innerHTML = template;
|
|
1126
|
+
} else {
|
|
1127
|
+
shadowRoot.appendChild(template);
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
if (isArr(styles) && styles.length) {
|
|
1131
|
+
shadowRoot.adoptedStyleSheets.push(...styles);
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
return this;
|
|
1135
|
+
}
|
|
1136
|
+
/**
|
|
1137
|
+
* Gets a wrapper around the Element's Shadow Root, if it exists.
|
|
1138
|
+
*
|
|
1139
|
+
* @returns A JJSR instance wrapping the shadow root, or null if no shadow root exists.
|
|
1140
|
+
*/
|
|
1141
|
+
get shadow() {
|
|
1142
|
+
return this.ref.shadowRoot ? new JJSR(this.ref.shadowRoot) : null;
|
|
1143
|
+
}
|
|
1144
|
+
};
|
|
1145
|
+
|
|
1146
|
+
// src/wrappers/JJEx.ts
|
|
1147
|
+
var JJEx = class extends JJE {
|
|
1148
|
+
/**
|
|
1149
|
+
* Gets a data attribute from the HTMLElement.
|
|
1150
|
+
*
|
|
1151
|
+
* @example
|
|
1152
|
+
* ```ts
|
|
1153
|
+
* const value = el.getData('my-key')
|
|
1154
|
+
* ```
|
|
1155
|
+
*
|
|
1156
|
+
* @param name - The data attribute name (in camelCase).
|
|
1157
|
+
* @returns The value of the attribute, or undefined if not set.
|
|
1158
|
+
* @throws {TypeError} If `name` is not a string.
|
|
1159
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset | HTMLElement.dataset}
|
|
1160
|
+
*/
|
|
1161
|
+
getData(name) {
|
|
1162
|
+
if (!isStr(name)) {
|
|
1163
|
+
throw typeErr("name", "a string", name);
|
|
1164
|
+
}
|
|
1165
|
+
return this.ref.dataset[name];
|
|
1166
|
+
}
|
|
1167
|
+
/**
|
|
1168
|
+
* Checks if a data attribute exists on the HTMLElement.
|
|
1169
|
+
*
|
|
1170
|
+
* @example
|
|
1171
|
+
* ```ts
|
|
1172
|
+
* if (el.hasData('my-key')) {
|
|
1173
|
+
* // ...
|
|
1174
|
+
* }
|
|
1175
|
+
* ```
|
|
1176
|
+
*
|
|
1177
|
+
* @param name - The data attribute name (in camelCase).
|
|
1178
|
+
* @returns True if the attribute exists, false otherwise.
|
|
1179
|
+
* @throws {TypeError} If `name` is not a string.
|
|
1180
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset | HTMLElement.dataset}
|
|
1181
|
+
*/
|
|
1182
|
+
hasData(name) {
|
|
1183
|
+
if (!isStr(name)) {
|
|
1184
|
+
throw typeErr("name", "a string", name);
|
|
1185
|
+
}
|
|
1186
|
+
return hasProp(this.ref.dataset, name);
|
|
1187
|
+
}
|
|
1188
|
+
setData(nameOrObj, value) {
|
|
1189
|
+
if (typeof nameOrObj === "string") {
|
|
1190
|
+
this.ref.dataset[nameOrObj] = value;
|
|
1191
|
+
} else if (isObj(nameOrObj)) {
|
|
1192
|
+
for (const [k, v] of Object.entries(nameOrObj)) {
|
|
1193
|
+
this.ref.dataset[k] = v;
|
|
1194
|
+
}
|
|
1195
|
+
} else {
|
|
1196
|
+
throw typeErr("nameOrObj", "a string or object", nameOrObj);
|
|
1197
|
+
}
|
|
1198
|
+
return this;
|
|
1199
|
+
}
|
|
1200
|
+
/**
|
|
1201
|
+
* Removes one or more data attributes from the HTMLElement.
|
|
1202
|
+
*
|
|
1203
|
+
* @example
|
|
1204
|
+
* ```ts
|
|
1205
|
+
* el.rmData('myKey') // Remove single
|
|
1206
|
+
* el.rmData('myKey', 'otherKey') // Remove multiple
|
|
1207
|
+
* ```
|
|
1208
|
+
*
|
|
1209
|
+
* @param names - The data attribute name(s) (in camelCase).
|
|
1210
|
+
* @returns This instance for chaining.
|
|
1211
|
+
* @throws {TypeError} If any name is not a string.
|
|
1212
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset | HTMLElement.dataset}
|
|
1213
|
+
*/
|
|
1214
|
+
rmData(...names) {
|
|
1215
|
+
for (const name of names) {
|
|
1216
|
+
if (!isStr(name)) {
|
|
1217
|
+
throw typeErr("name", "a string", name);
|
|
1218
|
+
}
|
|
1219
|
+
delete this.ref.dataset[name];
|
|
1220
|
+
}
|
|
1221
|
+
return this;
|
|
1222
|
+
}
|
|
1223
|
+
};
|
|
1224
|
+
|
|
1225
|
+
// src/wrappers/JJHE.ts
|
|
1226
|
+
var JJHE = class _JJHE extends JJEx {
|
|
1227
|
+
/**
|
|
1228
|
+
* Creates a JJHE instance from an HTMLElement reference.
|
|
1229
|
+
*
|
|
1230
|
+
* @example
|
|
1231
|
+
* ```ts
|
|
1232
|
+
* const el = JJHE.from(document.getElementById('my-id')) // from an existing HTMLElement
|
|
1233
|
+
* const el = JJHE.from(new document.createElement('div')) // from a new HTMLElement
|
|
1234
|
+
* ```
|
|
1235
|
+
*
|
|
1236
|
+
* @param ref - The HTMLElement.
|
|
1237
|
+
* @returns A new JJHE instance.
|
|
1238
|
+
*/
|
|
1239
|
+
static from(ref) {
|
|
1240
|
+
return new _JJHE(ref);
|
|
1241
|
+
}
|
|
1242
|
+
static create(tagName, options) {
|
|
1243
|
+
if (!isStr(tagName)) {
|
|
1244
|
+
throw typeErr("tagName", "a string like 'div' or 'button'", tagName);
|
|
1245
|
+
}
|
|
1246
|
+
return new _JJHE(document.createElement(tagName, options));
|
|
1247
|
+
}
|
|
1248
|
+
/**
|
|
1249
|
+
* Creates an instance of JJHE.
|
|
1250
|
+
*
|
|
1251
|
+
* @param ref - The HTMLElement to wrap.
|
|
1252
|
+
* @throws {TypeError} If `ref` is not an HTMLElement.
|
|
1253
|
+
*/
|
|
1254
|
+
constructor(ref) {
|
|
1255
|
+
if (!isA(ref, HTMLElement)) {
|
|
1256
|
+
throw typeErr("ref", "an HTMLElement", ref);
|
|
1257
|
+
}
|
|
1258
|
+
super(ref);
|
|
1259
|
+
}
|
|
1260
|
+
/**
|
|
1261
|
+
* Gets the value property of the HTMLElement (e.g. for inputs).
|
|
1262
|
+
*
|
|
1263
|
+
* @returns The value.
|
|
1264
|
+
* @throws {Error} If the HTMLElement does not have a value property.
|
|
1265
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/value | HTMLInputElement.value}
|
|
1266
|
+
*/
|
|
1267
|
+
getValue() {
|
|
1268
|
+
if (!hasProp(this.ref, "value")) {
|
|
1269
|
+
throw new ReferenceError(`${this.ref.tagName} has no value property.`);
|
|
1270
|
+
}
|
|
1271
|
+
return this.ref.value;
|
|
1272
|
+
}
|
|
1273
|
+
/**
|
|
1274
|
+
* Sets the value property of the HTMLElement.
|
|
1275
|
+
*
|
|
1276
|
+
* @example
|
|
1277
|
+
* ```ts
|
|
1278
|
+
* input.setValue('new value')
|
|
1279
|
+
* input.setValue(42) // Numbers are automatically converted
|
|
1280
|
+
* ```
|
|
1281
|
+
*
|
|
1282
|
+
* @param value - The value to set.
|
|
1283
|
+
* @returns This instance for chaining.
|
|
1284
|
+
* @throws {Error} If the HTMLElement does not have a value property.
|
|
1285
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/value | HTMLInputElement.value}
|
|
1286
|
+
*/
|
|
1287
|
+
setValue(value) {
|
|
1288
|
+
if (!hasProp(this.ref, "value")) {
|
|
1289
|
+
throw new ReferenceError(`${this.ref.tagName} has no value property.`);
|
|
1290
|
+
}
|
|
1291
|
+
this.ref.value = value;
|
|
1292
|
+
return this;
|
|
1293
|
+
}
|
|
1294
|
+
/**
|
|
1295
|
+
* Focuses the HTMLElement.
|
|
1296
|
+
*
|
|
1297
|
+
* @returns This instance for chaining.
|
|
1298
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus | HTMLElement.focus}
|
|
1299
|
+
*/
|
|
1300
|
+
focus() {
|
|
1301
|
+
this.ref.focus();
|
|
1302
|
+
return this;
|
|
1303
|
+
}
|
|
1304
|
+
/**
|
|
1305
|
+
* Clicks the HTMLElement.
|
|
1306
|
+
*
|
|
1307
|
+
* @returns This instance for chaining.
|
|
1308
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click | HTMLElement.click}
|
|
1309
|
+
*/
|
|
1310
|
+
click() {
|
|
1311
|
+
this.ref.click();
|
|
1312
|
+
return this;
|
|
1313
|
+
}
|
|
1314
|
+
/**
|
|
1315
|
+
* Gets the inner text of the HTMLElement.
|
|
1316
|
+
*
|
|
1317
|
+
* @remarks
|
|
1318
|
+
* This method operates on `innerText`. The method name is kept short for convenience.
|
|
1319
|
+
*
|
|
1320
|
+
* @returns The inner text.
|
|
1321
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText | HTMLElement.innerText}
|
|
1322
|
+
*/
|
|
1323
|
+
getText() {
|
|
1324
|
+
return this.ref.innerText;
|
|
1325
|
+
}
|
|
1326
|
+
/**
|
|
1327
|
+
* Sets the inner text of the HTMLElement.
|
|
1328
|
+
*
|
|
1329
|
+
* @remarks
|
|
1330
|
+
* This method operates on `innerText`. The method name is kept short for convenience.
|
|
1331
|
+
* Pass an empty string, `null`, or `undefined` to clear the content.
|
|
1332
|
+
* Numbers and booleans are automatically converted to strings.
|
|
1333
|
+
*
|
|
1334
|
+
* @param text - The text to set, or null/undefined to clear.
|
|
1335
|
+
* @returns This instance for chaining.
|
|
1336
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText | HTMLElement.innerText}
|
|
1337
|
+
*/
|
|
1338
|
+
setText(text) {
|
|
1339
|
+
this.ref.innerText = text ?? "";
|
|
1340
|
+
return this;
|
|
1341
|
+
}
|
|
1342
|
+
};
|
|
1343
|
+
|
|
1344
|
+
// src/wrappers/JJT.ts
|
|
1345
|
+
var JJT = class _JJT extends JJN {
|
|
1346
|
+
/**
|
|
1347
|
+
* Creates a JJT instance from a Text node.
|
|
1348
|
+
*
|
|
1349
|
+
* @example
|
|
1350
|
+
* ```ts
|
|
1351
|
+
* const textNode = document.createTextNode('foo')
|
|
1352
|
+
* const text = JJT.from(textNode)
|
|
1353
|
+
* ```
|
|
1354
|
+
*
|
|
1355
|
+
* @param text - The Text node.
|
|
1356
|
+
* @returns A new JJT instance.
|
|
1357
|
+
* @throws {TypeError} If `text` is not a Text node.
|
|
1358
|
+
*/
|
|
1359
|
+
static from(text) {
|
|
1360
|
+
return new _JJT(text);
|
|
1361
|
+
}
|
|
1362
|
+
static fromStr(text) {
|
|
1363
|
+
return new _JJT(document.createTextNode(text));
|
|
1364
|
+
}
|
|
1365
|
+
/**
|
|
1366
|
+
* Creates an instance of JJT.
|
|
1367
|
+
*
|
|
1368
|
+
* @example
|
|
1369
|
+
* ```ts
|
|
1370
|
+
* const text = new JJT('Hello World')
|
|
1371
|
+
* ```
|
|
1372
|
+
*
|
|
1373
|
+
* @param ref - The Text node or a string to create a Text node from.
|
|
1374
|
+
* @throws {TypeError} If `ref` is not a Text node or string.
|
|
1375
|
+
*/
|
|
1376
|
+
constructor(ref) {
|
|
1377
|
+
if (!isA(ref, Text)) {
|
|
1378
|
+
throw new TypeError(
|
|
1379
|
+
`JJT expects a Text node. Got ${ref} (${typeof ref}). Create a Text node with JJT.fromStr() or document.createTextNode('text').`
|
|
1380
|
+
);
|
|
1381
|
+
}
|
|
1382
|
+
super(ref);
|
|
1383
|
+
}
|
|
1384
|
+
/**
|
|
1385
|
+
* Gets the text content of the Text node.
|
|
1386
|
+
*
|
|
1387
|
+
* @example
|
|
1388
|
+
* ```ts
|
|
1389
|
+
* const content = text.getText()
|
|
1390
|
+
* ```
|
|
1391
|
+
*
|
|
1392
|
+
* @returns The text content.
|
|
1393
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent | Node.textContent}
|
|
1394
|
+
*/
|
|
1395
|
+
getText() {
|
|
1396
|
+
return this.ref.textContent;
|
|
1397
|
+
}
|
|
1398
|
+
/**
|
|
1399
|
+
* Sets the text content of the Text node.
|
|
1400
|
+
*
|
|
1401
|
+
* @example
|
|
1402
|
+
* ```ts
|
|
1403
|
+
* text.setText('New content')
|
|
1404
|
+
* ```
|
|
1405
|
+
*
|
|
1406
|
+
* @param text - The text to set. Set it to null or undefined to remove all text
|
|
1407
|
+
* @returns This instance for chaining.
|
|
1408
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent | Node.textContent}
|
|
1409
|
+
*/
|
|
1410
|
+
setText(text) {
|
|
1411
|
+
this.ref.textContent = text ?? null;
|
|
1412
|
+
return this;
|
|
1413
|
+
}
|
|
1414
|
+
/**
|
|
1415
|
+
* Appends text to the existing content.
|
|
1416
|
+
*
|
|
1417
|
+
* @example
|
|
1418
|
+
* ```ts
|
|
1419
|
+
* text.setText('hello')
|
|
1420
|
+
* text.addText(' world')
|
|
1421
|
+
* console.log(text.getText()) // 'hello world'
|
|
1422
|
+
* ```
|
|
1423
|
+
*
|
|
1424
|
+
* @param text - The string to add to the existing contents. If null or undefined, nothing is added.
|
|
1425
|
+
* @returns This instance for chaining.
|
|
1426
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent | Node.textContent}
|
|
1427
|
+
*/
|
|
1428
|
+
addText(text) {
|
|
1429
|
+
if (text != null) {
|
|
1430
|
+
this.ref.textContent += text;
|
|
1431
|
+
}
|
|
1432
|
+
return this;
|
|
1433
|
+
}
|
|
1434
|
+
/**
|
|
1435
|
+
* Clears the text content of the Text node.
|
|
1436
|
+
*
|
|
1437
|
+
* @example
|
|
1438
|
+
* ```ts
|
|
1439
|
+
* text.empty()
|
|
1440
|
+
* ```
|
|
1441
|
+
*
|
|
1442
|
+
* @returns This instance for chaining.
|
|
1443
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent | Node.textContent}
|
|
1444
|
+
*/
|
|
1445
|
+
empty() {
|
|
1446
|
+
return this.setText("");
|
|
1447
|
+
}
|
|
1448
|
+
};
|
|
1449
|
+
|
|
1450
|
+
// src/wrappers/JJD.ts
|
|
1451
|
+
var JJD = class _JJD extends JJNx {
|
|
1452
|
+
/**
|
|
1453
|
+
* Creates a JJD instance from a Document reference.
|
|
1454
|
+
*
|
|
1455
|
+
* @example
|
|
1456
|
+
* ```ts
|
|
1457
|
+
* const doc = JJD.from(document)
|
|
1458
|
+
* ```
|
|
1459
|
+
*
|
|
1460
|
+
* @param ref - The Document instance.
|
|
1461
|
+
* @returns A new JJD instance.
|
|
1462
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document | Document}
|
|
1463
|
+
*/
|
|
1464
|
+
static from(ref) {
|
|
1465
|
+
return new _JJD(ref);
|
|
1466
|
+
}
|
|
1467
|
+
/**
|
|
1468
|
+
* Creates an instance of JJD.
|
|
1469
|
+
*
|
|
1470
|
+
* @param ref - The Document instance to wrap.
|
|
1471
|
+
* @throws {TypeError} If `ref` is not a Document.
|
|
1472
|
+
*/
|
|
1473
|
+
constructor(ref) {
|
|
1474
|
+
if (!isA(ref, Document)) {
|
|
1475
|
+
throw new TypeError(`JJD expects a Document instance. Got ${ref} (${typeof ref}). `);
|
|
1476
|
+
}
|
|
1477
|
+
super(ref);
|
|
1478
|
+
}
|
|
1479
|
+
/**
|
|
1480
|
+
* Gets the `<head>` element of the document wrapped in a `JJHE` instance.
|
|
1481
|
+
*
|
|
1482
|
+
* @returns The wrapped head element.
|
|
1483
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/head | Document.head}
|
|
1484
|
+
*/
|
|
1485
|
+
get head() {
|
|
1486
|
+
return JJHE.from(this.ref.head);
|
|
1487
|
+
}
|
|
1488
|
+
/**
|
|
1489
|
+
* Gets the `<body>` element of the document wrapped in a `JJHE` instance.
|
|
1490
|
+
*
|
|
1491
|
+
* @returns The wrapped body element.
|
|
1492
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/body | Document.body}
|
|
1493
|
+
*/
|
|
1494
|
+
get body() {
|
|
1495
|
+
return JJHE.from(this.ref.body);
|
|
1496
|
+
}
|
|
1497
|
+
};
|
|
1498
|
+
|
|
1499
|
+
// src/wrappers/JJSE.ts
|
|
1500
|
+
var SVG_NAMESPACE_URI = "http://www.w3.org/2000/svg";
|
|
1501
|
+
var JJSE = class _JJSE extends JJEx {
|
|
1502
|
+
/**
|
|
1503
|
+
* Creates a JJSE instance from an SVGElement reference.
|
|
1504
|
+
*
|
|
1505
|
+
* @example
|
|
1506
|
+
* ```ts
|
|
1507
|
+
* const svg = JJSE.from(myCircle)
|
|
1508
|
+
* ```
|
|
1509
|
+
*
|
|
1510
|
+
* @param ref - The SVGElement.
|
|
1511
|
+
* @returns A new JJSE instance.
|
|
1512
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/SVGElement | SVGElement}
|
|
1513
|
+
*/
|
|
1514
|
+
static from(ref) {
|
|
1515
|
+
return new _JJSE(ref);
|
|
1516
|
+
}
|
|
1517
|
+
/**
|
|
1518
|
+
* Creates a JJSE instance from a tag name (in the SVG namespace).
|
|
1519
|
+
*
|
|
1520
|
+
* @remarks
|
|
1521
|
+
* Automatically uses the correct SVG namespace URI: `http://www.w3.org/2000/svg`.
|
|
1522
|
+
*
|
|
1523
|
+
* @example
|
|
1524
|
+
* ```ts
|
|
1525
|
+
* const circle = JJSE.create('circle')
|
|
1526
|
+
* ```
|
|
1527
|
+
*
|
|
1528
|
+
* @param tagName - The tag name.
|
|
1529
|
+
* @param options - Element creation options.
|
|
1530
|
+
* @returns A new JJSE instance.
|
|
1531
|
+
* @throws {TypeError} If `tagName` is not a string.
|
|
1532
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS | document.createElementNS}
|
|
1533
|
+
*/
|
|
1534
|
+
static create(tagName, options) {
|
|
1535
|
+
if (!isStr(tagName)) {
|
|
1536
|
+
throw typeErr("tagName", 'a string like "circle" or "path"', tagName);
|
|
1537
|
+
}
|
|
1538
|
+
const element = document.createElementNS(SVG_NAMESPACE_URI, tagName, options);
|
|
1539
|
+
return new _JJSE(element);
|
|
1540
|
+
}
|
|
1541
|
+
/**
|
|
1542
|
+
* Creates an instance of JJSE.
|
|
1543
|
+
*
|
|
1544
|
+
* @param ref - The SVGElement to wrap.
|
|
1545
|
+
* @throws {TypeError} If `ref` is not an SVGElement.
|
|
1546
|
+
*/
|
|
1547
|
+
constructor(ref) {
|
|
1548
|
+
if (!isA(ref, SVGElement)) {
|
|
1549
|
+
throw typeErr("ref", "an SVGElement", ref);
|
|
1550
|
+
}
|
|
1551
|
+
super(ref);
|
|
1552
|
+
}
|
|
1553
|
+
/**
|
|
1554
|
+
* Gets the text content of the SVGElement.
|
|
1555
|
+
*
|
|
1556
|
+
* @remarks
|
|
1557
|
+
* This method operates on `textContent`. The method name is kept short for convenience.
|
|
1558
|
+
*
|
|
1559
|
+
* @example
|
|
1560
|
+
* ```ts
|
|
1561
|
+
* const text = svg.getText()
|
|
1562
|
+
* ```
|
|
1563
|
+
*
|
|
1564
|
+
* @returns The text content.
|
|
1565
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent | Node.textContent}
|
|
1566
|
+
*/
|
|
1567
|
+
getText() {
|
|
1568
|
+
return this.ref.textContent ?? "";
|
|
1569
|
+
}
|
|
1570
|
+
/**
|
|
1571
|
+
* Sets the text content of the SVGElement.
|
|
1572
|
+
*
|
|
1573
|
+
* @remarks
|
|
1574
|
+
* This method operates on `textContent`. The method name is kept short for convenience.
|
|
1575
|
+
* Pass an empty string, `null`, or `undefined` to clear the content.
|
|
1576
|
+
* Numbers and booleans are automatically converted to strings.
|
|
1577
|
+
*
|
|
1578
|
+
* @example
|
|
1579
|
+
* ```ts
|
|
1580
|
+
* svg.setText('Hello SVG')
|
|
1581
|
+
* svg.setText(null) // Clear content
|
|
1582
|
+
* svg.setText(42) // Numbers are converted
|
|
1583
|
+
* ```
|
|
1584
|
+
*
|
|
1585
|
+
* @param text - The text to set, or null/undefined to clear.
|
|
1586
|
+
* @returns This instance for chaining.
|
|
1587
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent | Node.textContent}
|
|
1588
|
+
*/
|
|
1589
|
+
setText(text) {
|
|
1590
|
+
this.ref.textContent = text ?? "";
|
|
1591
|
+
return this;
|
|
1592
|
+
}
|
|
1593
|
+
/**
|
|
1594
|
+
* Sets the fill attribute.
|
|
1595
|
+
*
|
|
1596
|
+
* @param value - The fill color/value.
|
|
1597
|
+
* @returns This instance for chaining.
|
|
1598
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill | fill}
|
|
1599
|
+
*/
|
|
1600
|
+
setFill(value) {
|
|
1601
|
+
return this.setAttr("fill", value);
|
|
1602
|
+
}
|
|
1603
|
+
/**
|
|
1604
|
+
* Sets the stroke attribute.
|
|
1605
|
+
*
|
|
1606
|
+
* @param value - The stroke color/value.
|
|
1607
|
+
* @returns This instance for chaining.
|
|
1608
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke | stroke}
|
|
1609
|
+
*/
|
|
1610
|
+
setStroke(value) {
|
|
1611
|
+
return this.setAttr("stroke", value);
|
|
1612
|
+
}
|
|
1613
|
+
/**
|
|
1614
|
+
* Sets the stroke-width attribute.
|
|
1615
|
+
*
|
|
1616
|
+
* @param value - The width.
|
|
1617
|
+
* @returns This instance for chaining.
|
|
1618
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width | stroke-width}
|
|
1619
|
+
*/
|
|
1620
|
+
setStrokeWidth(value) {
|
|
1621
|
+
return this.setAttr("stroke-width", String(value));
|
|
1622
|
+
}
|
|
1623
|
+
/**
|
|
1624
|
+
* Sets the viewBox attribute.
|
|
1625
|
+
*
|
|
1626
|
+
* @example
|
|
1627
|
+
* ```ts
|
|
1628
|
+
* svg.setViewBox(0, 0, 100, 100)
|
|
1629
|
+
* svg.setViewBox('0 0 100 100')
|
|
1630
|
+
* ```
|
|
1631
|
+
*
|
|
1632
|
+
* @param p1 - Min-x or string/array value.
|
|
1633
|
+
* @param p2 - Min-y.
|
|
1634
|
+
* @param p3 - Width.
|
|
1635
|
+
* @param p4 - Height.
|
|
1636
|
+
* @returns This instance for chaining.
|
|
1637
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox | viewBox}
|
|
1638
|
+
*/
|
|
1639
|
+
setViewBox(p1, p2, p3, p4) {
|
|
1640
|
+
if (typeof p1 === "number" && p2 !== void 0 && p3 !== void 0 && p4 !== void 0) {
|
|
1641
|
+
return this.setAttr("viewBox", `${p1} ${p2} ${p3} ${p4}`);
|
|
1642
|
+
}
|
|
1643
|
+
const value = p1;
|
|
1644
|
+
return this.setAttr("viewBox", Array.isArray(value) ? value.join(" ") : value);
|
|
1645
|
+
}
|
|
1646
|
+
/**
|
|
1647
|
+
* Sets the width attribute.
|
|
1648
|
+
*
|
|
1649
|
+
* @param value - The width.
|
|
1650
|
+
* @returns This instance for chaining.
|
|
1651
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/width | width}
|
|
1652
|
+
*/
|
|
1653
|
+
setWidth(value) {
|
|
1654
|
+
return this.setAttr("width", String(value));
|
|
1655
|
+
}
|
|
1656
|
+
/**
|
|
1657
|
+
* Sets the height attribute.
|
|
1658
|
+
*
|
|
1659
|
+
* @param value - The height.
|
|
1660
|
+
* @returns This instance for chaining.
|
|
1661
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/height | height}
|
|
1662
|
+
*/
|
|
1663
|
+
setHeight(value) {
|
|
1664
|
+
return this.setAttr("height", String(value));
|
|
1665
|
+
}
|
|
1666
|
+
/**
|
|
1667
|
+
* Sets the d attribute (path data).
|
|
1668
|
+
*
|
|
1669
|
+
* @param value - The path data string or array of segments.
|
|
1670
|
+
* @returns This instance for chaining.
|
|
1671
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d | d}
|
|
1672
|
+
*/
|
|
1673
|
+
setD(value) {
|
|
1674
|
+
return this.setAttr("d", Array.isArray(value) ? value.join(" ") : value);
|
|
1675
|
+
}
|
|
1676
|
+
/**
|
|
1677
|
+
* Sets the transform attribute.
|
|
1678
|
+
*
|
|
1679
|
+
* @param value - The transform string.
|
|
1680
|
+
* @returns This instance for chaining.
|
|
1681
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform | transform}
|
|
1682
|
+
*/
|
|
1683
|
+
setTransform(value) {
|
|
1684
|
+
return this.setAttr("transform", value);
|
|
1685
|
+
}
|
|
1686
|
+
};
|
|
1687
|
+
|
|
1688
|
+
// src/wrappers/JJN.ts
|
|
1689
|
+
JJN.wrap = function wrap(raw) {
|
|
1690
|
+
if (isStr(raw)) {
|
|
1691
|
+
return JJT.fromStr(raw);
|
|
1692
|
+
}
|
|
1693
|
+
if (!isObj(raw)) {
|
|
1694
|
+
throw typeErr("raw", "an object", raw);
|
|
1695
|
+
}
|
|
1696
|
+
if (isA(raw, JJN)) {
|
|
1697
|
+
return raw;
|
|
1698
|
+
}
|
|
1699
|
+
if (isA(raw, HTMLElement)) {
|
|
1700
|
+
return JJHE.from(raw);
|
|
1701
|
+
}
|
|
1702
|
+
if (isA(raw, SVGElement)) {
|
|
1703
|
+
return JJSE.from(raw);
|
|
1704
|
+
}
|
|
1705
|
+
if (isA(raw, Element)) {
|
|
1706
|
+
return JJE.from(raw);
|
|
1707
|
+
}
|
|
1708
|
+
if (isA(raw, ShadowRoot)) {
|
|
1709
|
+
return JJSR.from(raw);
|
|
1710
|
+
}
|
|
1711
|
+
if (isA(raw, DocumentFragment)) {
|
|
1712
|
+
return JJDF.from(raw);
|
|
1713
|
+
}
|
|
1714
|
+
if (isA(raw, Document)) {
|
|
1715
|
+
return JJD.from(raw);
|
|
1716
|
+
}
|
|
1717
|
+
if (isA(raw, Text)) {
|
|
1718
|
+
return JJT.from(raw);
|
|
1719
|
+
}
|
|
1720
|
+
if (isA(raw, Node)) {
|
|
1721
|
+
return JJN.from(raw);
|
|
1722
|
+
}
|
|
1723
|
+
throw typeErr("raw", "a Node", raw);
|
|
1724
|
+
};
|
|
1725
|
+
|
|
1726
|
+
// src/helpers.ts
|
|
1727
|
+
function h(tagName, attributes, ...children) {
|
|
1728
|
+
const ret = JJHE.create(tagName).addChild(...children);
|
|
1729
|
+
if (attributes) {
|
|
1730
|
+
ret.setAttr(attributes);
|
|
1731
|
+
}
|
|
1732
|
+
return ret;
|
|
1733
|
+
}
|
|
1734
|
+
function linkAs(href) {
|
|
1735
|
+
switch (fileExt(href)) {
|
|
1736
|
+
case "html":
|
|
1737
|
+
case "htm":
|
|
1738
|
+
case "md":
|
|
1739
|
+
return "fetch";
|
|
1740
|
+
case "css":
|
|
1741
|
+
return "style";
|
|
1742
|
+
case "js":
|
|
1743
|
+
case "mjs":
|
|
1744
|
+
case "cjs":
|
|
1745
|
+
return "script";
|
|
1746
|
+
default:
|
|
1747
|
+
throw new Error(`No 'as' attribute was specified and we failed to guess it from the URL: ${href}`);
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
function createLinkPre(href, rel, as) {
|
|
1751
|
+
if (!isStr(href)) {
|
|
1752
|
+
if (!isA(href, URL)) {
|
|
1753
|
+
throw typeErr("href", "a string or URL", href);
|
|
1754
|
+
}
|
|
1755
|
+
href = href.toString();
|
|
1756
|
+
}
|
|
1757
|
+
if (!["prefetch", "preload"].includes(rel)) {
|
|
1758
|
+
throw new RangeError(errMsg("rel", `'prefetch' or 'preload'`, rel));
|
|
1759
|
+
}
|
|
1760
|
+
if (!as) {
|
|
1761
|
+
as = linkAs(href);
|
|
1762
|
+
if (!as) {
|
|
1763
|
+
throw new Error(`Could not guess 'as' attribute from URL: ${href}`);
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
if (!["fetch", "style", "script"].includes(as)) {
|
|
1767
|
+
throw new RangeError(errMsg("as", `'fetch', 'style', or 'script'`, as));
|
|
1768
|
+
}
|
|
1769
|
+
return JJHE.create("link").setAttr({
|
|
1770
|
+
href,
|
|
1771
|
+
rel,
|
|
1772
|
+
as
|
|
1773
|
+
});
|
|
1774
|
+
}
|
|
1775
|
+
function addLinkPre(...args) {
|
|
1776
|
+
const link = createLinkPre(...args);
|
|
1777
|
+
document.head.append(link.ref);
|
|
1778
|
+
return link;
|
|
1779
|
+
}
|
|
1780
|
+
async function fetchText(url, mime = "text/*") {
|
|
1781
|
+
if (!isStr(mime)) {
|
|
1782
|
+
throw typeErr("mime", "a string", mime);
|
|
1783
|
+
}
|
|
1784
|
+
const response = await fetch(url, { headers: { Accept: mime } });
|
|
1785
|
+
if (!response.ok) {
|
|
1786
|
+
throw new Error(`GET ${url} failed: ${response.status} ${response.statusText}`);
|
|
1787
|
+
}
|
|
1788
|
+
return response.text();
|
|
1789
|
+
}
|
|
1790
|
+
async function fetchHtml(url) {
|
|
1791
|
+
return await fetchText(url, "text/html");
|
|
1792
|
+
}
|
|
1793
|
+
async function fetchCss(url) {
|
|
1794
|
+
return await fetchText(url, "text/css");
|
|
1795
|
+
}
|
|
1796
|
+
async function fetchStyle(url) {
|
|
1797
|
+
return await cssToStyle(await fetchCss(url));
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
// src/components.ts
|
|
1801
|
+
function attr2prop(instance, name, oldValue, newValue) {
|
|
1802
|
+
if (!isA(instance, HTMLElement)) {
|
|
1803
|
+
throw typeErr("instance", "an HTMLElement", instance);
|
|
1804
|
+
}
|
|
1805
|
+
if (oldValue !== newValue) {
|
|
1806
|
+
const propName = keb2cam(name);
|
|
1807
|
+
if (hasProp(instance, propName)) {
|
|
1808
|
+
instance[propName] = newValue;
|
|
1809
|
+
return true;
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
return false;
|
|
1813
|
+
}
|
|
1814
|
+
async function registerComponent(name, constructor, options) {
|
|
1815
|
+
if (!isStr(name)) {
|
|
1816
|
+
throw typeErr("name", "a string", name);
|
|
1817
|
+
}
|
|
1818
|
+
if (!isFn(constructor)) {
|
|
1819
|
+
throw typeErr("constructor", "a function", constructor);
|
|
1820
|
+
}
|
|
1821
|
+
if (!customElements.get(name)) {
|
|
1822
|
+
customElements.define(name, constructor, options);
|
|
1823
|
+
await customElements.whenDefined(name);
|
|
1824
|
+
}
|
|
1825
|
+
}
|
|
1826
|
+
|
|
1827
|
+
// src/ShadowMaster.ts
|
|
1828
|
+
async function templatePromise(templateConfig) {
|
|
1829
|
+
if (templateConfig === void 0) {
|
|
1830
|
+
return void 0;
|
|
1831
|
+
}
|
|
1832
|
+
if (isFn(templateConfig)) {
|
|
1833
|
+
templateConfig = await templateConfig();
|
|
1834
|
+
}
|
|
1835
|
+
templateConfig = await templateConfig;
|
|
1836
|
+
if (isStr(templateConfig)) {
|
|
1837
|
+
return templateConfig;
|
|
1838
|
+
}
|
|
1839
|
+
if (isA(templateConfig, JJDF)) {
|
|
1840
|
+
return templateConfig.ref.cloneNode(true);
|
|
1841
|
+
}
|
|
1842
|
+
if (isA(templateConfig, DocumentFragment)) {
|
|
1843
|
+
return templateConfig.cloneNode(true);
|
|
1844
|
+
}
|
|
1845
|
+
if (isA(templateConfig, JJHE)) {
|
|
1846
|
+
if (templateConfig.ref instanceof HTMLTemplateElement) {
|
|
1847
|
+
return templateConfig.ref.content.cloneNode(true);
|
|
1848
|
+
}
|
|
1849
|
+
return templateConfig.ref.outerHTML;
|
|
1850
|
+
}
|
|
1851
|
+
if (isA(templateConfig, HTMLElement)) {
|
|
1852
|
+
return templateConfig instanceof HTMLTemplateElement ? templateConfig.content.cloneNode(true) : templateConfig.outerHTML;
|
|
1853
|
+
}
|
|
1854
|
+
throw typeErr("template", "a string, JJHE, JJDF, HTMLElement, or DocumentFragment", templateConfig);
|
|
1855
|
+
}
|
|
1856
|
+
async function stylePromise(styleConfig) {
|
|
1857
|
+
if (isFn(styleConfig)) {
|
|
1858
|
+
styleConfig = await styleConfig();
|
|
1859
|
+
}
|
|
1860
|
+
styleConfig = await styleConfig;
|
|
1861
|
+
if (isA(styleConfig, CSSStyleSheet)) {
|
|
1862
|
+
return styleConfig;
|
|
1863
|
+
}
|
|
1864
|
+
if (isStr(styleConfig)) {
|
|
1865
|
+
return await cssToStyle(styleConfig);
|
|
1866
|
+
}
|
|
1867
|
+
throw typeErr("style", "a CSS string or CSSStyleSheet", styleConfig);
|
|
1868
|
+
}
|
|
1869
|
+
function stylePromises(styleConfigs) {
|
|
1870
|
+
if (!isArr(styleConfigs)) {
|
|
1871
|
+
return [];
|
|
1872
|
+
}
|
|
1873
|
+
return styleConfigs.map(stylePromise);
|
|
1874
|
+
}
|
|
1875
|
+
async function resolveConfig(templateConfig, styleConfigs) {
|
|
1876
|
+
const [template, ...styles] = await Promise.all([templatePromise(templateConfig), ...stylePromises(styleConfigs)]);
|
|
1877
|
+
return { template, styles };
|
|
1878
|
+
}
|
|
1879
|
+
var _templateConfig, _stylesConfig, _normalizedConfig;
|
|
1880
|
+
var _ShadowMaster = class _ShadowMaster {
|
|
1881
|
+
constructor() {
|
|
1882
|
+
__privateAdd(this, _templateConfig);
|
|
1883
|
+
__privateAdd(this, _stylesConfig, []);
|
|
1884
|
+
__privateAdd(this, _normalizedConfig);
|
|
1885
|
+
}
|
|
1886
|
+
/**
|
|
1887
|
+
* Creates a new instance of ShadowMaster.
|
|
1888
|
+
*
|
|
1889
|
+
* @returns A new ShadowMaster instance.
|
|
1890
|
+
*/
|
|
1891
|
+
static create() {
|
|
1892
|
+
return new _ShadowMaster();
|
|
1893
|
+
}
|
|
1894
|
+
/**
|
|
1895
|
+
* Sets the template configuration.
|
|
1896
|
+
*
|
|
1897
|
+
* @param templateConfig - The template configuration.
|
|
1898
|
+
* @returns The instance for chaining.
|
|
1899
|
+
*
|
|
1900
|
+
* @example
|
|
1901
|
+
* ```ts
|
|
1902
|
+
* // Accepts string, promise, or fetchHtml result
|
|
1903
|
+
* sm.setTemplate(fetchHtml('./template.html'))
|
|
1904
|
+
* ```
|
|
1905
|
+
*/
|
|
1906
|
+
setTemplate(templateConfig) {
|
|
1907
|
+
__privateSet(this, _templateConfig, templateConfig);
|
|
1908
|
+
return this;
|
|
1909
|
+
}
|
|
1910
|
+
/**
|
|
1911
|
+
* Adds one or more style configurations.
|
|
1912
|
+
*
|
|
1913
|
+
* @param stylesConfig - Variable number of style configurations.
|
|
1914
|
+
* @returns The instance for chaining.
|
|
1915
|
+
*
|
|
1916
|
+
* @example
|
|
1917
|
+
* ```ts
|
|
1918
|
+
* sm.addStyles(
|
|
1919
|
+
* 'p { color: red; }',
|
|
1920
|
+
* fetchCss('./styles.css'),
|
|
1921
|
+
* () => fetchCss('../lazy-loaded-styles.css'),
|
|
1922
|
+
* )
|
|
1923
|
+
* ```
|
|
1924
|
+
*/
|
|
1925
|
+
addStyles(...stylesConfig) {
|
|
1926
|
+
__privateGet(this, _stylesConfig).push(...stylesConfig);
|
|
1927
|
+
return this;
|
|
1928
|
+
}
|
|
1929
|
+
/**
|
|
1930
|
+
* Resolves the configuration to something that can be fed to `JJHE.initShadow()` function
|
|
1931
|
+
*
|
|
1932
|
+
* The result is cached, so subsequent calls return the same promise.
|
|
1933
|
+
* Note: Any changes made to the ShadowMaster instance (via setTemplate/addStyles)
|
|
1934
|
+
* after the first call to getResolved() will be ignored.
|
|
1935
|
+
*
|
|
1936
|
+
* @returns A promise resolving to the ShadowConfig.
|
|
1937
|
+
*/
|
|
1938
|
+
async getResolved() {
|
|
1939
|
+
if (!__privateGet(this, _normalizedConfig)) {
|
|
1940
|
+
__privateSet(this, _normalizedConfig, resolveConfig(__privateGet(this, _templateConfig), __privateGet(this, _stylesConfig)));
|
|
1941
|
+
}
|
|
1942
|
+
return await __privateGet(this, _normalizedConfig);
|
|
1943
|
+
}
|
|
1944
|
+
};
|
|
1945
|
+
_templateConfig = new WeakMap();
|
|
1946
|
+
_stylesConfig = new WeakMap();
|
|
1947
|
+
_normalizedConfig = new WeakMap();
|
|
1948
|
+
var ShadowMaster = _ShadowMaster;
|
|
1949
|
+
|
|
1950
|
+
// src/index.ts
|
|
1951
|
+
var doc = JJD.from(document);
|
|
1952
|
+
})();
|
|
1953
|
+
//# sourceMappingURL=bundle.global.js.map
|