@lvce-editor/virtual-dom 1.6.0 → 1.8.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.
package/dist/index.js CHANGED
@@ -1,89 +1,11 @@
1
- // src/parts/UidSymbol/UidSymbol.ts
2
- var uidSymbol = Symbol("uid");
3
-
4
- // src/parts/GetUidTarget/GetUidTarget.ts
5
- var getUidTarget = ($Element) => {
6
- while ($Element) {
7
- if ($Element[uidSymbol]) {
8
- return $Element;
9
- }
10
- $Element = $Element.parentNode;
11
- }
12
- return void 0;
13
- };
14
-
15
- // src/parts/ComponentUid/ComponentUid.ts
16
- var setComponentUid = ($Element, uid) => {
17
- $Element[uidSymbol] = uid;
18
- };
19
- var getComponentUid = ($Element) => {
20
- const $Target = getUidTarget($Element);
21
- if (!$Target) {
22
- return 0;
23
- }
24
- return $Target[uidSymbol];
25
- };
26
- var getComponentUidFromEvent = (event) => {
27
- const { target, currentTarget } = event;
28
- return getComponentUid(currentTarget || target);
29
- };
30
-
31
- // src/parts/IpcState/IpcState.ts
32
- var state = {
33
- ipc: void 0
34
- };
35
- var getIpc = () => {
36
- return state.ipc;
37
- };
38
- var setIpc = (value) => {
39
- state.ipc = value;
40
- };
41
-
42
- // src/parts/NameAnonymousFunction/NameAnonymousFunction.ts
43
- var nameAnonymousFunction = (fn, name) => {
44
- Object.defineProperty(fn, "name", {
45
- value: name
46
- });
47
- };
48
-
49
- // src/parts/RegisterEventListeners/RegisterEventListeners.ts
50
- var listeners = /* @__PURE__ */ Object.create(null);
51
- var getArgs = (params, event) => {
52
- return [...params];
53
- };
54
- var createFn = (info) => {
55
- const fn = (event) => {
56
- if (info.preventDefault) {
57
- event.preventDefault(event);
58
- }
59
- const uid = getComponentUidFromEvent(event);
60
- const args = getArgs(info.params, event);
61
- if (args.length === 0) {
62
- return;
63
- }
64
- const ipc = getIpc();
65
- ipc.send("Viewlet.executeViewletCommand", uid, ...args);
66
- };
67
- nameAnonymousFunction(fn, info.name);
68
- return fn;
69
- };
70
- var registerEventListeners = (id, eventListeners) => {
71
- const map = /* @__PURE__ */ Object.create(null);
72
- for (const info of eventListeners) {
73
- const fn = createFn(info);
74
- map[info.name] = fn;
75
- }
76
- listeners[id] = map;
77
- };
78
- var getEventListenerMap = (id) => {
79
- const map = listeners[id];
80
- return map;
81
- };
82
-
83
- // src/parts/ClearNode/ClearNode.ts
84
- var clearNode = ($Node) => {
85
- $Node.textContent = "";
86
- };
1
+ // src/parts/PatchType/PatchType.ts
2
+ var SetText = 1;
3
+ var SetAttribute = 3;
4
+ var RemoveAttribute = 4;
5
+ var Add = 6;
6
+ var NavigateChild = 7;
7
+ var RemoveChild = 9;
8
+ var NavigateSibling = 10;
87
9
 
88
10
  // src/parts/ElementTags/ElementTags.ts
89
11
  var Audio = "audio";
@@ -314,6 +236,47 @@ var getEventListenerOptions = (eventName) => {
314
236
  }
315
237
  };
316
238
 
239
+ // src/parts/UidSymbol/UidSymbol.ts
240
+ var uidSymbol = Symbol("uid");
241
+
242
+ // src/parts/GetUidTarget/GetUidTarget.ts
243
+ var getUidTarget = ($Element) => {
244
+ while ($Element) {
245
+ if ($Element[uidSymbol]) {
246
+ return $Element;
247
+ }
248
+ $Element = $Element.parentNode;
249
+ }
250
+ return void 0;
251
+ };
252
+
253
+ // src/parts/ComponentUid/ComponentUid.ts
254
+ var setComponentUid = ($Element, uid) => {
255
+ $Element[uidSymbol] = uid;
256
+ };
257
+ var getComponentUid = ($Element) => {
258
+ const $Target = getUidTarget($Element);
259
+ if (!$Target) {
260
+ return 0;
261
+ }
262
+ return $Target[uidSymbol];
263
+ };
264
+ var getComponentUidFromEvent = (event) => {
265
+ const { target, currentTarget } = event;
266
+ return getComponentUid(currentTarget || target);
267
+ };
268
+
269
+ // src/parts/IpcState/IpcState.ts
270
+ var state = {
271
+ ipc: void 0
272
+ };
273
+ var getIpc = () => {
274
+ return state.ipc;
275
+ };
276
+ var setIpc = (value) => {
277
+ state.ipc = value;
278
+ };
279
+
317
280
  // src/parts/ListenerCache/ListenerCache.ts
318
281
  var cache = /* @__PURE__ */ new Map();
319
282
  var has = (listener) => {
@@ -326,6 +289,13 @@ var get = (listener) => {
326
289
  return cache.get(listener);
327
290
  };
328
291
 
292
+ // src/parts/NameAnonymousFunction/NameAnonymousFunction.ts
293
+ var nameAnonymousFunction = (fn, name) => {
294
+ Object.defineProperty(fn, "name", {
295
+ value: name
296
+ });
297
+ };
298
+
329
299
  // src/parts/GetWrappedListener/GetWrappedListener.ts
330
300
  var getWrappedListener = (listener, returnValue) => {
331
301
  if (!returnValue) {
@@ -500,6 +470,99 @@ var renderInternal2 = ($Parent, elements, eventMap, newEventMap) => {
500
470
  $Parent.append(...stack);
501
471
  };
502
472
 
473
+ // src/parts/PatchFunctions/PatchFunctions.ts
474
+ var setAttribute = ($Element, key, value) => {
475
+ $Element.setAttribute(key, value);
476
+ };
477
+ var removeAttribute = ($Element, key) => {
478
+ $Element.removeAttribute(key);
479
+ };
480
+ var setText = ($Element, value) => {
481
+ $Element.nodeValue = value;
482
+ };
483
+ var removeChild = ($Element, index) => {
484
+ const $Child = $Element.children[index];
485
+ $Child.remove();
486
+ };
487
+ var add = ($Element, nodes) => {
488
+ renderInternal2($Element, nodes, {}, {});
489
+ };
490
+
491
+ // src/parts/ApplyPatch/ApplyPatch.ts
492
+ var applyPatch = ($Element, patches) => {
493
+ let $Current = $Element;
494
+ for (const patch of patches) {
495
+ switch (patch.type) {
496
+ case SetAttribute:
497
+ setAttribute(
498
+ $Current,
499
+ patch.key,
500
+ patch.value
501
+ );
502
+ break;
503
+ case RemoveAttribute:
504
+ removeAttribute($Current, patch.key);
505
+ break;
506
+ case SetText:
507
+ setText($Current, patch.value);
508
+ break;
509
+ case RemoveChild:
510
+ removeChild($Current, patch.index);
511
+ break;
512
+ case Add:
513
+ add($Current, patch.nodes);
514
+ break;
515
+ case NavigateSibling:
516
+ $Current = $Current.parentNode.childNodes[patch.index];
517
+ break;
518
+ case NavigateChild:
519
+ $Current = $Current.childNodes[patch.index];
520
+ break;
521
+ default:
522
+ break;
523
+ }
524
+ }
525
+ };
526
+
527
+ // src/parts/RegisterEventListeners/RegisterEventListeners.ts
528
+ var listeners = /* @__PURE__ */ Object.create(null);
529
+ var getArgs = (params, event) => {
530
+ return [...params];
531
+ };
532
+ var createFn = (info) => {
533
+ const fn = (event) => {
534
+ if (info.preventDefault) {
535
+ event.preventDefault(event);
536
+ }
537
+ const uid = getComponentUidFromEvent(event);
538
+ const args = getArgs(info.params, event);
539
+ if (args.length === 0) {
540
+ return;
541
+ }
542
+ const ipc = getIpc();
543
+ ipc.send("Viewlet.executeViewletCommand", uid, ...args);
544
+ };
545
+ nameAnonymousFunction(fn, info.name);
546
+ return fn;
547
+ };
548
+ var registerEventListeners = (id, eventListeners) => {
549
+ const map = /* @__PURE__ */ Object.create(null);
550
+ for (const info of eventListeners) {
551
+ const fn = createFn(info);
552
+ map[info.name] = fn;
553
+ }
554
+ listeners[id] = map;
555
+ };
556
+ var getEventListenerMap = (id) => {
557
+ const map = listeners[id];
558
+ return map;
559
+ };
560
+
561
+ // src/parts/ClearNode/ClearNode.ts
562
+ var clearNode = ($Node) => {
563
+ $Node.textContent = "";
564
+ };
565
+
503
566
  // src/parts/VirtualDom/VirtualDom.ts
504
567
  var renderInto = ($Parent, dom, eventMap = {}) => {
505
568
  clearNode($Parent);
@@ -520,7 +583,10 @@ var rememberFocus = ($Viewlet, dom, eventMap, uid = 0) => {
520
583
  const oldTop = $Viewlet.style.top;
521
584
  const oldWidth = $Viewlet.style.width;
522
585
  const oldHeight = $Viewlet.style.height;
523
- const focused = document.activeElement.getAttribute("name");
586
+ const activeElement = document.activeElement;
587
+ const isTreeFocused = activeElement?.getAttribute("role") === "tree";
588
+ const isRootTree = $Viewlet.getAttribute("role") === "tree" && activeElement === $Viewlet;
589
+ const focused = activeElement?.getAttribute("name");
524
590
  const $$Inputs = queryInputs($Viewlet);
525
591
  const inputMap = /* @__PURE__ */ Object.create(null);
526
592
  for (const $Input of $$Inputs) {
@@ -539,7 +605,14 @@ var rememberFocus = ($Viewlet, dom, eventMap, uid = 0) => {
539
605
  for (const $Input of $$NewInputs) {
540
606
  $Input.value = inputMap[$Input.name] || $Input.value || "";
541
607
  }
542
- if (focused) {
608
+ if (isRootTree) {
609
+ $Viewlet.focus();
610
+ } else if (isTreeFocused) {
611
+ const $Tree = $Viewlet.querySelector('[role="tree"]');
612
+ if ($Tree) {
613
+ $Tree.focus();
614
+ }
615
+ } else if (focused) {
543
616
  const $Focused = $Viewlet.querySelector(`[name="${focused}"]`);
544
617
  if ($Focused) {
545
618
  $Focused.focus();
@@ -552,6 +625,7 @@ var rememberFocus = ($Viewlet, dom, eventMap, uid = 0) => {
552
625
  return $Viewlet;
553
626
  };
554
627
  export {
628
+ applyPatch,
555
629
  getComponentUid,
556
630
  getComponentUidFromEvent,
557
631
  registerEventListeners,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/virtual-dom",
3
- "version": "1.6.0",
3
+ "version": "1.8.0",
4
4
  "main": "dist/index.js",
5
5
  "type": "module",
6
6
  "keywords": [],
@@ -0,0 +1,7 @@
1
+ import type { VirtualDomNode } from '../VirtualDomNode/VirtualDomNode.ts'
2
+
3
+ export interface AddPatch {
4
+ readonly type: 6
5
+ readonly index: number
6
+ readonly nodes: readonly VirtualDomNode[]
7
+ }
@@ -0,0 +1,38 @@
1
+ import { Patch } from '../Patch/Patch.ts'
2
+ import * as PatchType from '../PatchType/PatchType.ts'
3
+ import * as PatchFunctions from '../PatchFunctions/PatchFunctions.ts'
4
+
5
+ export const applyPatch = ($Element: Node, patches: readonly Patch[]): void => {
6
+ let $Current = $Element
7
+ for (const patch of patches) {
8
+ switch (patch.type) {
9
+ case PatchType.SetAttribute:
10
+ PatchFunctions.setAttribute(
11
+ $Current as HTMLElement,
12
+ patch.key,
13
+ patch.value,
14
+ )
15
+ break
16
+ case PatchType.RemoveAttribute:
17
+ PatchFunctions.removeAttribute($Current as HTMLElement, patch.key)
18
+ break
19
+ case PatchType.SetText:
20
+ PatchFunctions.setText($Current as Text, patch.value)
21
+ break
22
+ case PatchType.RemoveChild:
23
+ PatchFunctions.removeChild($Current as HTMLElement, patch.index)
24
+ break
25
+ case PatchType.Add:
26
+ PatchFunctions.add($Current as HTMLElement, patch.nodes)
27
+ break
28
+ case PatchType.NavigateSibling:
29
+ $Current = ($Current.parentNode as HTMLElement).childNodes[patch.index]
30
+ break
31
+ case PatchType.NavigateChild:
32
+ $Current = ($Current as HTMLElement).childNodes[patch.index]
33
+ break
34
+ default:
35
+ break
36
+ }
37
+ }
38
+ }
@@ -0,0 +1,5 @@
1
+ export interface AttributePatch {
2
+ readonly type: 3
3
+ readonly key: string
4
+ readonly value: any
5
+ }
@@ -1,3 +1,4 @@
1
+ export { applyPatch } from '../ApplyPatch/ApplyPatch.ts'
1
2
  export {
2
3
  getComponentUid,
3
4
  getComponentUidFromEvent,
@@ -0,0 +1,4 @@
1
+ export type NavigateChildPatch = {
2
+ readonly type: 7
3
+ readonly index: number
4
+ }
@@ -0,0 +1,4 @@
1
+ export type NavigateParentPatch = {
2
+ readonly type: 8
3
+ readonly count: number
4
+ }
@@ -0,0 +1,4 @@
1
+ export type NavigateSiblingPatch = {
2
+ readonly type: 10
3
+ readonly index: number
4
+ }
@@ -0,0 +1,22 @@
1
+ import type { AddPatch } from '../AddPatch/AddPatch.ts'
2
+ import type { AttributePatch } from '../AttributePatch/AttributePatch.ts'
3
+ import type { NavigateChildPatch } from '../NavigateChildPatch/NavigateChildPatch.ts'
4
+ import type { NavigateParentPatch } from '../NavigateParentPatch/NavigateParentPatch.ts'
5
+ import type { NavigateSiblingPatch } from '../NavigateSiblingPatch/NavigateSiblingPatch.ts'
6
+ import type { RemoveAttributePatch } from '../RemoveAttributePatch/RemoveAttributePatch.ts'
7
+ import type { RemoveChildPatch } from '../RemoveChildPatch/RemoveChildPatch.ts'
8
+ import type { RemovePatch } from '../RemovePatch/RemovePatch.ts'
9
+ import type { ReplacePatch } from '../ReplacePatch/ReplacePatch.ts'
10
+ import type { TextPatch } from '../TextPatch/TextPatch.ts'
11
+
12
+ export type Patch =
13
+ | TextPatch
14
+ | AttributePatch
15
+ | ReplacePatch
16
+ | RemoveAttributePatch
17
+ | RemovePatch
18
+ | AddPatch
19
+ | NavigateChildPatch
20
+ | NavigateParentPatch
21
+ | RemoveChildPatch
22
+ | NavigateSiblingPatch
@@ -0,0 +1,30 @@
1
+ import { VirtualDomNode } from '../VirtualDomNode/VirtualDomNode.ts'
2
+ import * as RenderInternal from '../RenderInternal/RenderInternal.ts'
3
+
4
+ export const setAttribute = (
5
+ $Element: HTMLElement,
6
+ key: string,
7
+ value: any,
8
+ ): void => {
9
+ $Element.setAttribute(key, value)
10
+ }
11
+
12
+ export const removeAttribute = ($Element: HTMLElement, key: string): void => {
13
+ $Element.removeAttribute(key)
14
+ }
15
+
16
+ export const setText = ($Element: Text, value: string): void => {
17
+ $Element.nodeValue = value
18
+ }
19
+
20
+ export const removeChild = ($Element: HTMLElement, index: number): void => {
21
+ const $Child = $Element.children[index]
22
+ $Child.remove()
23
+ }
24
+
25
+ export const add = (
26
+ $Element: HTMLElement,
27
+ nodes: readonly VirtualDomNode[],
28
+ ): void => {
29
+ RenderInternal.renderInternal($Element, nodes, {}, {})
30
+ }
@@ -0,0 +1,10 @@
1
+ export const SetText = 1
2
+ export const Replace = 2
3
+ export const SetAttribute = 3
4
+ export const RemoveAttribute = 4
5
+ export const Remove = 5
6
+ export const Add = 6
7
+ export const NavigateChild = 7
8
+ export const NavigateParent = 8
9
+ export const RemoveChild = 9
10
+ export const NavigateSibling = 10
@@ -12,20 +12,25 @@ export const rememberFocus = (
12
12
  eventMap: any,
13
13
  uid = 0,
14
14
  ) => {
15
- // TODO replace this workaround with
16
- // virtual dom diffing
17
15
  const oldLeft = $Viewlet.style.left
18
16
  const oldTop = $Viewlet.style.top
19
17
  const oldWidth = $Viewlet.style.width
20
18
  const oldHeight = $Viewlet.style.height
21
- // @ts-expect-error
22
- const focused = document.activeElement.getAttribute('name')
19
+
20
+ const activeElement = document.activeElement
21
+ const isTreeFocused = activeElement?.getAttribute('role') === 'tree'
22
+ const isRootTree =
23
+ $Viewlet.getAttribute('role') === 'tree' && activeElement === $Viewlet
24
+
25
+ const focused = activeElement?.getAttribute('name')
26
+
23
27
  const $$Inputs = queryInputs($Viewlet)
24
28
  const inputMap = Object.create(null)
25
29
  for (const $Input of $$Inputs) {
26
30
  // @ts-ignore
27
31
  inputMap[$Input.name] = $Input.value
28
32
  }
33
+
29
34
  if (uid) {
30
35
  const newEventMap = RegisterEventListeners.getEventListenerMap(uid)
31
36
  const $New = VirtualDom.render(dom, eventMap, newEventMap).firstChild
@@ -37,12 +42,22 @@ export const rememberFocus = (
37
42
  } else {
38
43
  VirtualDom.renderInto($Viewlet, dom, eventMap)
39
44
  }
45
+
40
46
  const $$NewInputs = queryInputs($Viewlet)
41
47
  for (const $Input of $$NewInputs) {
42
48
  // @ts-ignore
43
49
  $Input.value = inputMap[$Input.name] || $Input.value || ''
44
50
  }
45
- if (focused) {
51
+
52
+ if (isRootTree) {
53
+ $Viewlet.focus()
54
+ } else if (isTreeFocused) {
55
+ const $Tree = $Viewlet.querySelector('[role="tree"]')
56
+ if ($Tree) {
57
+ // @ts-ignore
58
+ $Tree.focus()
59
+ }
60
+ } else if (focused) {
46
61
  const $Focused = $Viewlet.querySelector(`[name="${focused}"]`)
47
62
  if ($Focused) {
48
63
  // @ts-ignore
@@ -0,0 +1,5 @@
1
+ export interface RemoveAttributePatch {
2
+ readonly type: 4
3
+ readonly index: number
4
+ readonly key: string
5
+ }
@@ -0,0 +1,4 @@
1
+ export interface RemoveChildPatch {
2
+ readonly type: 9
3
+ readonly index: number
4
+ }
@@ -0,0 +1,4 @@
1
+ export interface RemovePatch {
2
+ readonly type: 5
3
+ readonly index: number
4
+ }
@@ -2,7 +2,7 @@ import * as VirtualDomElement from '../VirtualDomElement/VirtualDomElement.ts'
2
2
 
3
3
  export const renderInternal = (
4
4
  $Parent: HTMLElement,
5
- elements: any[],
5
+ elements: readonly any[],
6
6
  eventMap: any,
7
7
  newEventMap?: any,
8
8
  ) => {
@@ -0,0 +1,7 @@
1
+ import type { VirtualDomNode } from '../VirtualDomNode/VirtualDomNode.ts'
2
+
3
+ export interface ReplacePatch {
4
+ readonly type: 2
5
+ readonly index: number
6
+ readonly node: VirtualDomNode
7
+ }
@@ -0,0 +1,4 @@
1
+ export interface TextPatch {
2
+ readonly type: 1
3
+ readonly value: string
4
+ }
@@ -0,0 +1,4 @@
1
+ export interface VirtualDomNode {
2
+ readonly type: number
3
+ readonly [key: string]: any
4
+ }