aptechka 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/.prettierignore +16 -0
  2. package/.prettierrc +9 -0
  3. package/.vscode/extensions.json +4 -0
  4. package/.vscode/launch.json +11 -0
  5. package/.vscode/settings.json +18 -0
  6. package/README.md +0 -0
  7. package/index.html +32 -0
  8. package/package.json +272 -0
  9. package/public/vite.svg +1 -0
  10. package/src/packages/animation/Animated.ts +189 -0
  11. package/src/packages/animation/Damped.ts +39 -0
  12. package/src/packages/animation/Tweened.ts +51 -0
  13. package/src/packages/animation/index.ts +10 -0
  14. package/src/packages/attribute/index.ts +59 -0
  15. package/src/packages/canvas-2d/index.ts +137 -0
  16. package/src/packages/controls/Controls.ts +15 -0
  17. package/src/packages/controls/KeyboardControls.ts +63 -0
  18. package/src/packages/controls/LinearControls.ts +27 -0
  19. package/src/packages/controls/User.ts +20 -0
  20. package/src/packages/controls/WheelControls.ts +92 -0
  21. package/src/packages/controls/index.ts +5 -0
  22. package/src/packages/css-unit-parser/index.ts +32 -0
  23. package/src/packages/custom-element/index.ts +19 -0
  24. package/src/packages/device/Device.ts +113 -0
  25. package/src/packages/device/Viewport.ts +67 -0
  26. package/src/packages/device/index.ts +2 -0
  27. package/src/packages/element-constructor/ElementConstructor.ts +577 -0
  28. package/src/packages/element-constructor/htmlTags.ts +679 -0
  29. package/src/packages/element-constructor/index.ts +4 -0
  30. package/src/packages/element-constructor/specialObjects.ts +8 -0
  31. package/src/packages/element-constructor/svgTags.ts +588 -0
  32. package/src/packages/en3/attachments/En3SourceManager.ts +116 -0
  33. package/src/packages/en3/core/en3.ts +306 -0
  34. package/src/packages/en3/index.ts +52 -0
  35. package/src/packages/en3/instances/en3LazyLoader.ts +22 -0
  36. package/src/packages/en3/libs/MeshoptDecoder.js +138 -0
  37. package/src/packages/en3/loaders/en3GLTFLoader.ts +54 -0
  38. package/src/packages/en3/loaders/en3TextureLoader.ts +3 -0
  39. package/src/packages/en3/objects/En3Clip.ts +53 -0
  40. package/src/packages/en3/objects/En3ClipHelpers.ts +12 -0
  41. package/src/packages/en3/objects/En3GLTF.ts +35 -0
  42. package/src/packages/en3/objects/En3Image.ts +18 -0
  43. package/src/packages/en3/objects/En3ImageLike.ts +101 -0
  44. package/src/packages/en3/objects/En3SourceConsumer.ts +5 -0
  45. package/src/packages/en3/objects/En3Video.ts +88 -0
  46. package/src/packages/en3/test/En3HTML.ts +55 -0
  47. package/src/packages/en3/test/En3ModifiedMaterial.ts +221 -0
  48. package/src/packages/en3/test/En3Raycaster.ts +187 -0
  49. package/src/packages/en3/utils/coverTexture.ts +29 -0
  50. package/src/packages/en3/utils/dispose.ts +27 -0
  51. package/src/packages/en3/utils/traverseMaterials.ts +10 -0
  52. package/src/packages/en3/utils/traverseMeshes.ts +9 -0
  53. package/src/packages/image/index.ts +19 -0
  54. package/src/packages/intersector/index.ts +83 -0
  55. package/src/packages/ladder/index.ts +112 -0
  56. package/src/packages/layout-box/index.ts +417 -0
  57. package/src/packages/loading/index.ts +131 -0
  58. package/src/packages/measurer/CumulativeOffsetLeft.ts +8 -0
  59. package/src/packages/measurer/CumulativeOffsetTop.ts +8 -0
  60. package/src/packages/measurer/Meaurer.ts +38 -0
  61. package/src/packages/measurer/index.ts +3 -0
  62. package/src/packages/media/index.ts +38 -0
  63. package/src/packages/morph/Link.ts +32 -0
  64. package/src/packages/morph/Morph.ts +246 -0
  65. package/src/packages/morph/index.ts +10 -0
  66. package/src/packages/notifier/index.ts +41 -0
  67. package/src/packages/order/index.ts +14 -0
  68. package/src/packages/resizer/index.ts +55 -0
  69. package/src/packages/router/Link.ts +33 -0
  70. package/src/packages/router/Route.ts +152 -0
  71. package/src/packages/router/RouteElement.ts +34 -0
  72. package/src/packages/router/Router.ts +190 -0
  73. package/src/packages/router/index.ts +13 -0
  74. package/src/packages/scroll/ScrollElement.ts +618 -0
  75. package/src/packages/scroll/ScrollUserElement.ts +21 -0
  76. package/src/packages/scroll/ScrollbarElement.ts +170 -0
  77. package/src/packages/scroll/index.ts +2 -0
  78. package/src/packages/scroll-entries/index.ts +74 -0
  79. package/src/packages/source/SourceClass.ts +77 -0
  80. package/src/packages/source/SourceElement.ts +177 -0
  81. package/src/packages/source/SourceManager.ts +61 -0
  82. package/src/packages/source/SourceSet.ts +52 -0
  83. package/src/packages/source/index.ts +8 -0
  84. package/src/packages/store/Composed.ts +33 -0
  85. package/src/packages/store/Derived.ts +24 -0
  86. package/src/packages/store/DerivedArray.ts +36 -0
  87. package/src/packages/store/Resource.ts +38 -0
  88. package/src/packages/store/Store.ts +144 -0
  89. package/src/packages/store/StoreRegistry.ts +105 -0
  90. package/src/packages/store/index.ts +23 -0
  91. package/src/packages/ticker/index.ts +173 -0
  92. package/src/packages/utils/array.ts +3 -0
  93. package/src/packages/utils/attributes.ts +19 -0
  94. package/src/packages/utils/browser.ts +2 -0
  95. package/src/packages/utils/canvas.ts +46 -0
  96. package/src/packages/utils/collisions.ts +12 -0
  97. package/src/packages/utils/coordinates.ts +40 -0
  98. package/src/packages/utils/decoding.ts +11 -0
  99. package/src/packages/utils/dev.ts +5 -0
  100. package/src/packages/utils/dom.ts +48 -0
  101. package/src/packages/utils/easings.ts +69 -0
  102. package/src/packages/utils/file.ts +17 -0
  103. package/src/packages/utils/function.ts +29 -0
  104. package/src/packages/utils/index.ts +61 -0
  105. package/src/packages/utils/layout.ts +22 -0
  106. package/src/packages/utils/math.ts +74 -0
  107. package/src/packages/utils/number.ts +26 -0
  108. package/src/packages/utils/object.ts +108 -0
  109. package/src/packages/utils/string.ts +49 -0
  110. package/src/packages/utils/ts-shape.ts +25 -0
  111. package/src/packages/utils/ts-utility.ts +47 -0
  112. package/src/packages/video/index.ts +39 -0
  113. package/src/playground/index.ts +0 -0
  114. package/tsconfig.json +31 -0
  115. package/vite.config.ts +65 -0
@@ -0,0 +1,577 @@
1
+ import { Store } from '$packages/store'
2
+ import { isBrowser, camelToKebab } from '$packages/utils'
3
+
4
+ export type ElementConstructorTagNameMap = HTMLElementTagNameMap & SVGElementTagNameMap
5
+
6
+ export type ElementConstructorTagNames = keyof ElementConstructorTagNameMap
7
+
8
+ export type ElementConstructorStringStoreClass = Store<string | null | undefined> | Store<string>
9
+
10
+ export type ElementConstructorStringArrayStoreClass =
11
+ | Store<Array<string | null | undefined>>
12
+ | Store<Array<string>>
13
+
14
+ export type ElementConstructorClass =
15
+ | string
16
+ | Array<string | ElementConstructorStringStoreClass | ElementConstructorStringArrayStoreClass>
17
+ | ElementConstructorStringStoreClass
18
+ | ElementConstructorStringArrayStoreClass
19
+ | { [key: string]: boolean | Store<boolean> }
20
+
21
+ export type ElementConstructorStyleToken = Exclude<
22
+ Extract<keyof CSSStyleDeclaration, string> | `--${string}`,
23
+ 'length' | 'parentRule'
24
+ >
25
+
26
+ export type ElementConstructorStyleValue = string | Store<string | null | undefined> | Store<string>
27
+
28
+ export type ElementConstructorStyle = Partial<{
29
+ [K in ElementConstructorStyleToken]: ElementConstructorStyleValue
30
+ }>
31
+
32
+ export type ElementConstructorJSSWrapper = {
33
+ [key: string]: object | ElementConstructorStyle
34
+ }
35
+
36
+ export type ElementConstructorJSS =
37
+ | ElementConstructorStyle
38
+ | {
39
+ [key: string]: ElementConstructorJSSWrapper | ElementConstructorStyle
40
+ }
41
+
42
+ export type ElementConstructorEventMap = HTMLElementEventMap & SVGElementEventMap
43
+
44
+ export type ElementConstructorEventNames = keyof ElementConstructorEventMap
45
+
46
+ export type ElementConstructorEventValue<E extends Event> =
47
+ | {
48
+ callback: (event: E) => void
49
+ options?: AddEventListenerOptions
50
+ }
51
+ | ((event: E) => void)
52
+
53
+ export type ElementConstructorEvents = Partial<{
54
+ [EventName in
55
+ | ElementConstructorEventNames
56
+ | `custom:${string}`]: EventName extends ElementConstructorEventNames
57
+ ? ElementConstructorEventValue<HTMLElementEventMap[EventName]>
58
+ : ElementConstructorEventValue<CustomEvent>
59
+ }>
60
+
61
+ export type ElementConstructorNativeAttribute<
62
+ TagName extends ElementConstructorTagNames,
63
+ E = ElementConstructorTagNameMap[TagName]
64
+ > = {
65
+ [K in keyof E]: E[K] extends string ? K : never
66
+ }[keyof E]
67
+
68
+ type ElementConstructorAttributeValue =
69
+ | string
70
+ | undefined
71
+ | null
72
+ | boolean
73
+ | number
74
+ | Store<string>
75
+ | Store<string | undefined | null>
76
+ | Store<boolean>
77
+ | Store<boolean | undefined | null>
78
+ | Store<number>
79
+ | Store<number | undefined | null>
80
+
81
+ export type ElementConstructorNativeAttributes<T extends ElementConstructorTagNames> = Partial<{
82
+ [K in ElementConstructorNativeAttribute<T>]: ElementConstructorAttributeValue
83
+ }>
84
+
85
+ export type ElementConstructorCustomAttributes = {
86
+ [key: string]: ElementConstructorAttributeValue
87
+ }
88
+
89
+ export type ElementConstructorAttributes<T extends ElementConstructorTagNames> =
90
+ | ElementConstructorNativeAttributes<T>
91
+ | ElementConstructorCustomAttributes
92
+
93
+ export type ElementConstructorPrimitiveChild = string | number | boolean | null | undefined
94
+
95
+ export type ElementConstructorSimpleChild =
96
+ | ElementConstructorPrimitiveChild
97
+ | ElementConstructor
98
+ | Node
99
+ | Array<ElementConstructorPrimitiveChild>
100
+ | Array<ElementConstructor>
101
+ | Array<Node>
102
+
103
+ export type ElementConstructorStoreChild = Store<any>
104
+ export type ElementConstructorStoreChildren = Store<Array<any>>
105
+
106
+ export type ElementConstructorChildren = Array<
107
+ ElementConstructorSimpleChild | ElementConstructorStoreChild | ElementConstructorStoreChildren
108
+ >
109
+
110
+ export type ElementConstructorParent = Node | ElementConstructor
111
+
112
+ export type ElementConstructorCreatedCallback<TagName extends ElementConstructorTagNames> = (
113
+ element: ElementConstructorTagNameMap[TagName]
114
+ ) => void
115
+
116
+ export type ElementConstructorTagObject<TagName extends ElementConstructorTagNames> = {
117
+ class?: ElementConstructorClass
118
+ style?: TagName extends 'style' ? ElementConstructorJSS : ElementConstructorStyle
119
+ events?: ElementConstructorEvents
120
+ attributes?: ElementConstructorAttributes<TagName>
121
+ children?: ElementConstructorChildren
122
+ shadowChildren?: ElementConstructorChildren
123
+ parent?: ElementConstructorParent
124
+ svg?: boolean
125
+ created?: ElementConstructorCreatedCallback<TagName>
126
+ }
127
+
128
+ export type ElementConstructorObject =
129
+ | Partial<{
130
+ [T in ElementConstructorTagNames]: ElementConstructorTagObject<T>
131
+ }>
132
+ | {
133
+ [key: `${string}-${string}`]: ElementConstructorTagObject<'div'>
134
+ }
135
+
136
+ export type ElementConstructorType = HTMLElement | SVGElement
137
+
138
+ export class ElementConstructor<T extends ElementConstructorTagNames = ElementConstructorTagNames> {
139
+ #rootElements: Array<ElementConstructorType> = []
140
+
141
+ constructor(object: ElementConstructorObject)
142
+ constructor(value: string, object: ElementConstructorTagObject<T>)
143
+ constructor(element: HTMLElement, object: ElementConstructorTagObject<T>)
144
+ constructor(...args: any[]) {
145
+ const p1 = args[0]
146
+ const p2 = args[1]
147
+
148
+ if (isBrowser) {
149
+ if (typeof p1 === 'string') {
150
+ const wrapper = document.createElement('div')
151
+ wrapper.innerHTML = p1
152
+ const element = wrapper.firstElementChild as HTMLElement
153
+ this.#rootElements = [element]
154
+ this.#applyProperties(element, p2)
155
+ } else if (p1 instanceof HTMLElement) {
156
+ this.#rootElements = [p1]
157
+ this.#applyProperties(p1, p2)
158
+ } else {
159
+ this.#rootElements = this.#createElements(p1)
160
+ }
161
+ }
162
+ }
163
+
164
+ public get rootElements() {
165
+ return this.#rootElements
166
+ }
167
+
168
+ #createElements(object: ElementConstructorObject) {
169
+ const elements: Array<ElementConstructorType> = []
170
+
171
+ for (const k in object) {
172
+ const tagName = k as keyof ElementConstructorObject
173
+ const properties = object[tagName] as ElementConstructorTagObject<any>
174
+ const element = this.#createElement(tagName, properties?.svg)
175
+
176
+ if (properties) {
177
+ this.#applyProperties(element, properties)
178
+ }
179
+
180
+ elements.push(element)
181
+ }
182
+
183
+ return elements
184
+ }
185
+
186
+ #createElement(tagName: ElementConstructorTagNames, isSVG = false) {
187
+ let element: HTMLElement | SVGElement = null!
188
+
189
+ if (tagName.includes('-')) {
190
+ element = new (customElements.get(tagName)!)()
191
+ } else if (isSVG) {
192
+ element = document.createElementNS('http://www.w3.org/2000/svg', tagName)
193
+ } else {
194
+ element = document.createElement(tagName)
195
+ }
196
+
197
+ return element
198
+ }
199
+
200
+ #applyProperties(element: ElementConstructorType, properties?: ElementConstructorTagObject<any>) {
201
+ for (const k in properties) {
202
+ const propertyName = k as keyof ElementConstructorTagObject<any>
203
+
204
+ if (propertyName === 'class') {
205
+ this.#createClassList(element, properties[propertyName])
206
+ } else if (propertyName === 'style') {
207
+ this.#createStyle(element, properties[propertyName])
208
+ } else if (propertyName === 'events') {
209
+ this.#createEvents(element, properties[propertyName])
210
+ } else if (propertyName === 'attributes') {
211
+ this.#createAttributes(element, properties[propertyName])
212
+ } else if (propertyName === 'children') {
213
+ this.#createChildren(element, properties[propertyName])
214
+ } else if (propertyName === 'shadowChildren') {
215
+ this.#createChildren(element.shadowRoot || element, properties[propertyName])
216
+ } else if (propertyName === 'parent') {
217
+ this.#createParent(element, properties[propertyName])
218
+ }
219
+ }
220
+
221
+ if (properties?.created) {
222
+ properties.created(element)
223
+ }
224
+ }
225
+
226
+ // Class
227
+
228
+ #createClassList(element: ElementConstructorType, classObject?: ElementConstructorClass) {
229
+ if (!classObject) {
230
+ return
231
+ } else if (typeof classObject === 'string') {
232
+ element.classList.add(classObject)
233
+ } else if (Array.isArray(classObject)) {
234
+ classObject.forEach((v) => {
235
+ this.#createClassList(element, v)
236
+ })
237
+ } else if (typeof classObject === 'object') {
238
+ if (classObject instanceof Store) {
239
+ this.#manageStringStoreClass(
240
+ element,
241
+ classObject as
242
+ | ElementConstructorStringStoreClass
243
+ | ElementConstructorStringArrayStoreClass
244
+ )
245
+ } else {
246
+ for (const className in classObject) {
247
+ const isActive = classObject[className]
248
+
249
+ if (isActive instanceof Store) {
250
+ this.#manageBooleanStoreClass(element, className, isActive)
251
+ } else if (isActive) {
252
+ element.classList.add(className)
253
+ } else {
254
+ element.classList.remove(className)
255
+ }
256
+ }
257
+ }
258
+ }
259
+ }
260
+
261
+ #manageStringStoreClass(
262
+ element: ElementConstructorType,
263
+ store: ElementConstructorStringStoreClass | ElementConstructorStringArrayStoreClass
264
+ ) {
265
+ store.subscribe(({ current, previous }) => {
266
+ if (previous) {
267
+ ;[previous].flat().forEach((v) => {
268
+ if (v) {
269
+ element.classList.remove(v)
270
+ }
271
+ })
272
+ }
273
+
274
+ if (current) {
275
+ ;[current].flat().forEach((v) => {
276
+ if (v) {
277
+ element.classList.add(v)
278
+ }
279
+ })
280
+ }
281
+ })
282
+ }
283
+
284
+ #manageBooleanStoreClass(
285
+ element: ElementConstructorType,
286
+ className: string,
287
+ store: Store<boolean>
288
+ ) {
289
+ store.subscribe(({ current }) => {
290
+ if (current) {
291
+ element.classList.add(className)
292
+ } else {
293
+ element.classList.remove(className)
294
+ }
295
+ })
296
+ }
297
+
298
+ // Style
299
+
300
+ #createStyle(
301
+ element: ElementConstructorType,
302
+ object?: ElementConstructorStyle | ElementConstructorJSS
303
+ ) {
304
+ if (!object) {
305
+ return
306
+ }
307
+
308
+ const isJSS = element.tagName === 'style' || element.tagName === 'STYLE'
309
+
310
+ if (isJSS) {
311
+ this.#createJSSStyle(element, object as ElementConstructorJSS)
312
+ } else {
313
+ this.#createAttributeStyle(element, object as ElementConstructorStyle)
314
+ }
315
+ }
316
+
317
+ #createAttributeStyle(element: ElementConstructorType, object: ElementConstructorStyle) {
318
+ for (const k in object) {
319
+ const token = k as ElementConstructorStyleToken
320
+ const value = object[token]
321
+
322
+ if (value instanceof Store) {
323
+ value.subscribe(({ current }) => {
324
+ this.#setStyleProperty(element, token, current)
325
+ })
326
+ } else {
327
+ this.#setStyleProperty(element, token, value)
328
+ }
329
+ }
330
+ }
331
+
332
+ #createJSSStyle(element: ElementConstructorType, object: ElementConstructorJSS) {
333
+ for (const key in object) {
334
+ const value = (object as any)[key]
335
+
336
+ if (typeof value === 'object' && !(value instanceof Store)) {
337
+ element.appendChild(new Text(`${key} {`))
338
+ this.#createJSSStyle(element, value)
339
+ element.appendChild(new Text(`}`))
340
+ } else {
341
+ if (value instanceof Store) {
342
+ const text = new Text()
343
+
344
+ value.subscribe((e) => {
345
+ if (e.current) {
346
+ text.nodeValue = `${camelToKebab(key)}: ${e.current};`
347
+ } else {
348
+ text.nodeValue = ''
349
+ }
350
+ })
351
+
352
+ element.appendChild(text)
353
+ } else {
354
+ element.appendChild(new Text(`${camelToKebab(key)}: ${value};`))
355
+ }
356
+ }
357
+ }
358
+ }
359
+
360
+ #setStyleProperty(
361
+ element: ElementConstructorType,
362
+ token: ElementConstructorStyleToken,
363
+ value?: string | null | undefined
364
+ ) {
365
+ if (token.includes('--')) {
366
+ if (value) {
367
+ element.style.setProperty(token, value)
368
+ } else {
369
+ element.style.removeProperty(token)
370
+ }
371
+ } else {
372
+ if (value) {
373
+ element.style[token as any] = value
374
+ } else {
375
+ element.style[token as any] = ''
376
+ }
377
+ }
378
+ }
379
+
380
+ // Events
381
+
382
+ #createEvents(element: ElementConstructorType, events?: ElementConstructorEvents) {
383
+ if (!events) {
384
+ return
385
+ }
386
+
387
+ for (const k in events) {
388
+ const eventName = k as keyof ElementConstructorEvents
389
+ const listener = events[eventName]
390
+
391
+ if (typeof listener === 'object') {
392
+ element.addEventListener(eventName, listener.callback as EventListener, listener.options)
393
+ } else if (typeof listener === 'function') {
394
+ element.addEventListener(eventName, listener as EventListener)
395
+ }
396
+ }
397
+ }
398
+
399
+ // Attributes
400
+
401
+ #createAttributes(
402
+ element: ElementConstructorType,
403
+ attributes?: ElementConstructorAttributes<any>
404
+ ) {
405
+ for (const attributeName in attributes) {
406
+ const value = attributes[attributeName]
407
+
408
+ if (value instanceof Store) {
409
+ value.subscribe(({ current }) => {
410
+ this.#setAttribute(element, attributeName, current)
411
+ })
412
+ } else {
413
+ this.#setAttribute(element, attributeName, value)
414
+ }
415
+ }
416
+ }
417
+
418
+ #setAttribute(
419
+ element: ElementConstructorType,
420
+ name: string,
421
+ value: string | boolean | number | null | undefined
422
+ ) {
423
+ if (name in element && !(element.constructor as any)?.observedAttributes?.includes(name)) {
424
+ if (value != undefined) {
425
+ ;(element as any)[name as any] = value.toString()
426
+ }
427
+ } else {
428
+ if (value != undefined) {
429
+ element.setAttribute(name, value.toString())
430
+ }
431
+ }
432
+ }
433
+
434
+ // Children
435
+
436
+ #createChildren(
437
+ root: ElementConstructorType | ShadowRoot,
438
+ children?: ElementConstructorChildren
439
+ ) {
440
+ if (!children) {
441
+ return
442
+ }
443
+
444
+ children.forEach((child) => {
445
+ if (child instanceof Store) {
446
+ const storeRootElement = document.createElement('div')
447
+ storeRootElement.style.display = 'contents'
448
+ root.appendChild(storeRootElement)
449
+
450
+ child.subscribe(({ current }) => {
451
+ this.#replaceChildren(
452
+ storeRootElement,
453
+ this.#getChildrenArray(current),
454
+ Array.from(storeRootElement.childNodes)
455
+ )
456
+ })
457
+ } else if (child instanceof ElementConstructor) {
458
+ root.append(...child.rootElements)
459
+ } else {
460
+ if (
461
+ typeof child === 'string' &&
462
+ child.trim().startsWith('<') &&
463
+ child.trim().endsWith('>')
464
+ ) {
465
+ const wrapper = document.createElement('div')
466
+ wrapper.innerHTML = child
467
+ root.append(wrapper.firstElementChild!)
468
+ } else {
469
+ const childNodeOrUndefined = this.#getOrCreateNode(child)
470
+
471
+ if (childNodeOrUndefined instanceof Node) {
472
+ root.append(childNodeOrUndefined)
473
+ }
474
+ }
475
+ }
476
+ })
477
+ }
478
+
479
+ #getChildrenArray(children: ElementConstructorSimpleChild) {
480
+ const arr = [children]
481
+ .flat()
482
+ .map((v) => {
483
+ if (v instanceof ElementConstructor) {
484
+ return v.rootElements
485
+ } else {
486
+ return this.#getOrCreateNode(v)
487
+ }
488
+ })
489
+ .flat()
490
+ .filter(Boolean) as Array<Node | ElementConstructorType>
491
+
492
+ return arr
493
+ }
494
+
495
+ #replaceChildren(
496
+ rootElement: HTMLElement,
497
+ newChildren: Array<Node>,
498
+ currentChildren: Array<Node>
499
+ ) {
500
+ currentChildren.forEach((currentChild, index) => {
501
+ if (index < newChildren.length) {
502
+ const newChild = newChildren[index]
503
+
504
+ if (!this.#areNodesEqual(currentChild, newChild)) {
505
+ rootElement.replaceChild(newChild, currentChild)
506
+ }
507
+ } else {
508
+ rootElement.removeChild(currentChild)
509
+ }
510
+ })
511
+
512
+ for (let i = currentChildren.length; i < newChildren.length; i++) {
513
+ rootElement.appendChild(newChildren[i])
514
+ }
515
+ }
516
+
517
+ #areNodesEqual(
518
+ currentChild: Node,
519
+ newChild: Exclude<ElementConstructorSimpleChild, ElementConstructor>
520
+ ) {
521
+ if (!newChild) {
522
+ return false
523
+ }
524
+
525
+ if (newChild instanceof Node) {
526
+ return currentChild.isEqualNode(newChild)
527
+ } else {
528
+ return currentChild.textContent === newChild.toString()
529
+ }
530
+ }
531
+
532
+ #getOrCreateNode(child: Exclude<ElementConstructorSimpleChild, ElementConstructor>) {
533
+ if (child instanceof Node) {
534
+ return child
535
+ } else if (child != undefined) {
536
+ return new Text(String(child))
537
+ } else {
538
+ return undefined
539
+ }
540
+ }
541
+
542
+ // Parent
543
+
544
+ #createParent(element: ElementConstructorType, parent?: ElementConstructorParent) {
545
+ if (!parent) {
546
+ return
547
+ }
548
+
549
+ const parentNode = parent instanceof ElementConstructor ? parent.rootElements[0] : parent
550
+
551
+ parentNode.appendChild(element)
552
+ }
553
+ }
554
+
555
+ export function element(object: ElementConstructorObject): ElementConstructor
556
+ export function element<T extends ElementConstructorTagNames = ElementConstructorTagNames>(
557
+ value: string,
558
+ object?: ElementConstructorTagObject<T>
559
+ ): ElementConstructor
560
+ export function element(
561
+ element: HTMLElement,
562
+ object: ElementConstructorTagObject<any>
563
+ ): ElementConstructor
564
+ export function element(...args: any[]) {
565
+ return new (ElementConstructor as any)(...args)
566
+ }
567
+
568
+ export function elementFactory(object: ElementConstructorObject): () => ElementConstructor
569
+ export function elementFactory(
570
+ element: HTMLElement,
571
+ object: ElementConstructorTagObject<any>
572
+ ): () => ElementConstructor
573
+ export function elementFactory(...args: any[]) {
574
+ return () => {
575
+ return new (ElementConstructor as any)(...args)
576
+ }
577
+ }