web-toolkit-x 0.0.1 → 0.70.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 (45) hide show
  1. package/AUTHORS +3 -0
  2. package/LICENSE +1 -1
  3. package/NOTICE +7 -0
  4. package/README.md +162 -6
  5. package/dist/release/index.d.ts +650 -0
  6. package/dist/release/index.d.ts.map +1 -0
  7. package/dist/release/index.js +2831 -0
  8. package/dist/release/index.js.map +1 -0
  9. package/dist/release/toolkit-0.70.0.js +2834 -0
  10. package/dist/release/toolkit-0.70.0.js.map +1 -0
  11. package/package.json +71 -18
  12. package/src/core/bragi.ts +122 -0
  13. package/src/core/browser.ts +538 -0
  14. package/src/core/child-nodes.ts +77 -0
  15. package/src/core/comment.ts +24 -0
  16. package/src/core/component.ts +190 -0
  17. package/src/core/created-roots.ts +38 -0
  18. package/src/core/custom-element.ts +191 -0
  19. package/src/core/description.ts +241 -0
  20. package/src/core/diff.ts +590 -0
  21. package/src/core/dispatcher.ts +221 -0
  22. package/src/core/dom.ts +124 -0
  23. package/src/core/draft.ts +609 -0
  24. package/src/core/lifecycle.ts +301 -0
  25. package/src/core/nodes.ts +13 -0
  26. package/src/core/patch.ts +412 -0
  27. package/src/core/plugins.ts +231 -0
  28. package/src/core/reconciler.ts +185 -0
  29. package/src/core/renderer.ts +75 -0
  30. package/src/core/runtime.ts +36 -0
  31. package/src/core/sandbox.ts +128 -0
  32. package/src/core/service.ts +39 -0
  33. package/src/core/template.ts +472 -0
  34. package/src/core/text.ts +24 -0
  35. package/src/core/toolkit.ts +220 -0
  36. package/src/core/utils.ts +148 -0
  37. package/src/core/virtual-dom.ts +118 -0
  38. package/src/core/virtual-element.ts +72 -0
  39. package/src/core/virtual-node.ts +87 -0
  40. package/src/core/web-component.ts +285 -0
  41. package/src/globals.d.ts +10 -0
  42. package/src/index.ts +62 -0
  43. package/src/plugins/logger.ts +38 -0
  44. package/src/release.ts +3 -0
  45. package/index.js +0 -1
@@ -0,0 +1,301 @@
1
+ import type {
2
+ ComponentDescription,
3
+ NodeDescription,
4
+ Props,
5
+ } from './description.js'
6
+ import type {
7
+ Component,
8
+ ParentVirtualNode,
9
+ VirtualNode,
10
+ WebComponent,
11
+ } from './nodes.js'
12
+ import Patch from './patch.js'
13
+
14
+ /* The errors of the hooks called while collecting them, if collecting. */
15
+ let hookErrors: unknown[] | null = null
16
+
17
+ /*
18
+ * Calls a hook, collecting its error if collecting, so that a throwing hook
19
+ * does not stop the other hooks from being called.
20
+ */
21
+ const callHook = (hook: () => void) => {
22
+ if (!hookErrors) {
23
+ return hook()
24
+ }
25
+ try {
26
+ hook()
27
+ } catch (error) {
28
+ hookErrors.push(error)
29
+ }
30
+ }
31
+
32
+ /*
33
+ * Calls the hook of a component being removed, ignoring the commands it
34
+ * issues. The dispatcher is shared with the root, so its mode is restored.
35
+ */
36
+ const callIgnoringCommands = (component: Component, hook: () => void) => {
37
+ const { dispatcher } = component
38
+ const { mode } = dispatcher
39
+ dispatcher.ignoreIncoming()
40
+ try {
41
+ callHook(hook)
42
+ } finally {
43
+ dispatcher.mode = mode
44
+ }
45
+ }
46
+
47
+ /* Throws the errors, aggregated when there are more of them. */
48
+ export const throwErrors = (errors: unknown[], message: string) => {
49
+ if (errors.length === 1) {
50
+ throw errors[0]
51
+ }
52
+ if (errors.length > 1) {
53
+ throw new AggregateError(errors, message)
54
+ }
55
+ }
56
+
57
+ const Lifecycle = {
58
+ /**
59
+ * Calls the hooks in the callback, collecting the errors they throw in
60
+ * the given list instead of stopping at the first one.
61
+ */
62
+ collectingErrors(errors: unknown[], callback: () => void) {
63
+ const prevErrors = hookErrors
64
+ hookErrors = errors
65
+ try {
66
+ callback()
67
+ } finally {
68
+ hookErrors = prevErrors
69
+ }
70
+ },
71
+
72
+ onComponentCreated(component: Component) {
73
+ if (component.hasOwnMethod('onCreated')) {
74
+ callHook(() => component.onCreated!.call(component.sandbox))
75
+ }
76
+ if (component.content) {
77
+ this.onNodeCreated(component.content)
78
+ }
79
+ },
80
+
81
+ onElementCreated(element: ParentVirtualNode) {
82
+ if (element.childNodes) {
83
+ for (const child of element.childNodes) {
84
+ this.onNodeCreated(child)
85
+ }
86
+ }
87
+ },
88
+
89
+ onNodeCreated(node: VirtualNode): void {
90
+ if (node.isElement()) {
91
+ return this.onElementCreated(node)
92
+ } else if (node.isComponent() && !node.isRoot()) {
93
+ return this.onComponentCreated(node)
94
+ }
95
+ },
96
+
97
+ onRootCreated(root: WebComponent) {
98
+ if (root.hasOwnMethod('onCreated')) {
99
+ callHook(() => root.onCreated!.call(root.sandbox))
100
+ }
101
+ const { childNodes } = root
102
+ if (childNodes) {
103
+ for (const child of childNodes) {
104
+ this.onNodeCreated(child)
105
+ }
106
+ }
107
+ },
108
+
109
+ onComponentAttached(component: Component) {
110
+ if (component.content) {
111
+ this.onNodeAttached(component.content)
112
+ }
113
+ if (component.hasOwnMethod('onAttached')) {
114
+ callHook(() => component.onAttached!.call(component.sandbox))
115
+ }
116
+ },
117
+
118
+ onElementAttached(element: ParentVirtualNode) {
119
+ if (element.childNodes) {
120
+ for (const child of element.childNodes) {
121
+ this.onNodeAttached(child)
122
+ }
123
+ }
124
+ },
125
+
126
+ onNodeAttached(node: VirtualNode): void {
127
+ if (node.isElement()) {
128
+ return this.onElementAttached(node)
129
+ } else if (node.isComponent() && !node.isRoot()) {
130
+ return this.onComponentAttached(node)
131
+ }
132
+ },
133
+
134
+ onNodeReceivedDescription(node: VirtualNode, description: NodeDescription) {
135
+ if (node.isComponent()) {
136
+ this.onComponentReceivedProps(
137
+ node,
138
+ (description as ComponentDescription).props,
139
+ )
140
+ }
141
+ },
142
+
143
+ onNodeUpdated(node: VirtualNode, prevDescription: NodeDescription) {
144
+ if (node.isComponent()) {
145
+ this.onComponentUpdated(
146
+ node,
147
+ (prevDescription as ComponentDescription).props,
148
+ )
149
+ }
150
+ },
151
+
152
+ onRootAttached(root: WebComponent) {
153
+ const { childNodes } = root
154
+ if (childNodes) {
155
+ for (const child of childNodes) {
156
+ this.onNodeAttached(child)
157
+ }
158
+ }
159
+ if (root.hasOwnMethod('onAttached')) {
160
+ callHook(() => root.onAttached!.call(root.sandbox))
161
+ }
162
+ },
163
+
164
+ onComponentReceivedProps(component: Component, nextProps: Props = {}) {
165
+ if (component.hasOwnMethod('onPropsReceived')) {
166
+ callHook(() =>
167
+ component.onPropsReceived!.call(component.sandbox, nextProps),
168
+ )
169
+ }
170
+ },
171
+
172
+ onComponentUpdated(component: Component, prevProps: Props = {}) {
173
+ if (component.hasOwnMethod('onUpdated')) {
174
+ callHook(() => component.onUpdated!.call(component.sandbox, prevProps))
175
+ }
176
+ },
177
+
178
+ onComponentDestroyed(component: Component) {
179
+ component.destroy()
180
+ if (component.hasOwnMethod('onDestroyed')) {
181
+ callIgnoringCommands(component, () =>
182
+ component.onDestroyed!.call(component.sandbox),
183
+ )
184
+ }
185
+ if (component.content) {
186
+ this.onNodeDestroyed(component.content)
187
+ }
188
+ if (component.isRoot()) {
189
+ this.onElementDestroyed(component)
190
+ }
191
+ },
192
+
193
+ onElementDestroyed(element: ParentVirtualNode) {
194
+ if (element.childNodes) {
195
+ for (const child of element.childNodes) {
196
+ this.onNodeDestroyed(child)
197
+ }
198
+ }
199
+ },
200
+
201
+ onNodeDestroyed(node: VirtualNode): void {
202
+ if (node.isElement()) {
203
+ return this.onElementDestroyed(node)
204
+ } else if (node.isComponent() && !node.isRoot()) {
205
+ return this.onComponentDestroyed(node)
206
+ }
207
+ },
208
+
209
+ onComponentDetached(component: Component) {
210
+ if (component.isRoot()) {
211
+ this.onElementDetached(component)
212
+ }
213
+ if (component.content) {
214
+ this.onNodeDetached(component.content)
215
+ }
216
+ if (component.hasOwnMethod('onDetached')) {
217
+ callIgnoringCommands(component, () =>
218
+ component.onDetached!.call(component.sandbox),
219
+ )
220
+ }
221
+ },
222
+
223
+ onElementDetached(element: ParentVirtualNode) {
224
+ if (element.childNodes) {
225
+ for (const child of element.childNodes) {
226
+ this.onNodeDetached(child)
227
+ }
228
+ }
229
+ },
230
+
231
+ onNodeDetached(node: VirtualNode) {
232
+ if (node.isElement()) {
233
+ this.onElementDetached(node)
234
+ node.parentNode = null
235
+ } else if (node.isComponent() && !node.isRoot()) {
236
+ this.onComponentDetached(node)
237
+ node.parentNode = null
238
+ }
239
+ },
240
+
241
+ beforeUpdate(patches: Patch[]) {
242
+ for (const patch of patches) {
243
+ this.beforePatchApplied(patch)
244
+ }
245
+ },
246
+
247
+ beforePatchApplied(patch: Patch) {
248
+ const Type = Patch.Type
249
+ switch (patch.type) {
250
+ case Type.INIT_ROOT_COMPONENT:
251
+ this.onRootCreated(patch.root)
252
+ return
253
+ case Type.INSERT_CHILD:
254
+ this.onNodeCreated(patch.node)
255
+ return
256
+ case Type.REPLACE_CHILD:
257
+ case Type.SET_CONTENT:
258
+ this.onNodeDestroyed(patch.child)
259
+ this.onNodeCreated(patch.node)
260
+ return
261
+ case Type.REMOVE_CHILD:
262
+ this.onNodeDestroyed(patch.child)
263
+ return
264
+ case Type.UPDATE_NODE:
265
+ this.onNodeReceivedDescription(patch.node, patch.description)
266
+ return
267
+ }
268
+ },
269
+
270
+ afterUpdate(patches: Patch[]) {
271
+ patches = [...patches].reverse()
272
+ for (const patch of patches) {
273
+ this.afterPatchApplied(patch)
274
+ }
275
+ },
276
+
277
+ afterPatchApplied(patch: Patch) {
278
+ const Type = Patch.Type
279
+ switch (patch.type) {
280
+ case Type.INIT_ROOT_COMPONENT:
281
+ this.onRootAttached(patch.root)
282
+ return
283
+ case Type.INSERT_CHILD:
284
+ this.onNodeAttached(patch.node)
285
+ return
286
+ case Type.REPLACE_CHILD:
287
+ case Type.SET_CONTENT:
288
+ this.onNodeDetached(patch.child)
289
+ this.onNodeAttached(patch.node)
290
+ return
291
+ case Type.REMOVE_CHILD:
292
+ this.onNodeDetached(patch.child)
293
+ return
294
+ case Type.UPDATE_NODE:
295
+ this.onNodeUpdated(patch.node, patch.prevDescription)
296
+ return
297
+ }
298
+ },
299
+ }
300
+
301
+ export default Lifecycle
@@ -0,0 +1,13 @@
1
+ /* The virtual DOM nodes, each one defined in its own module. */
2
+ export type { ParentVirtualNode } from './child-nodes.js'
3
+ export { default as Comment } from './comment.js'
4
+ export {
5
+ default as Component,
6
+ type CleanUpTask,
7
+ type ComponentClass,
8
+ type Connectable,
9
+ } from './component.js'
10
+ export { default as Text } from './text.js'
11
+ export { default as VirtualElement } from './virtual-element.js'
12
+ export { default as VirtualNode, type NodeRef } from './virtual-node.js'
13
+ export { default as WebComponent, default as Root } from './web-component.js'
@@ -0,0 +1,412 @@
1
+ import type {
2
+ ComponentDescription,
3
+ Listener,
4
+ NodeDescription,
5
+ } from './description.js'
6
+ import DOM from './dom.js'
7
+ import type {
8
+ Component,
9
+ ParentVirtualNode,
10
+ VirtualElement,
11
+ VirtualNode,
12
+ WebComponent,
13
+ } from './nodes.js'
14
+
15
+ /* A node rendered as an HTML element, e.g. a root with a custom element. */
16
+ type PatchTarget = VirtualNode & { ref: HTMLElement }
17
+
18
+ const Type = {
19
+ INIT_ROOT_COMPONENT: 'init-root-component',
20
+ UPDATE_NODE: 'update-node',
21
+ UPDATE_ROOT: 'update-root',
22
+ SET_ATTRIBUTE: 'set-attribute',
23
+ REMOVE_ATTRIBUTE: 'remove-attribute',
24
+ SET_DATA_ATTRIBUTE: 'set-data-attribute',
25
+ REMOVE_DATA_ATTRIBUTE: 'remove-data-attribute',
26
+ SET_STYLE_PROPERTY: 'set-style-property',
27
+ REMOVE_STYLE_PROPERTY: 'remove-style-property',
28
+ SET_CLASS_NAME: 'set-class-name',
29
+ ADD_LISTENER: 'add-listener',
30
+ REPLACE_LISTENER: 'replace-listener',
31
+ REMOVE_LISTENER: 'remove-listener',
32
+ SET_PROPERTY: 'set-property',
33
+ DELETE_PROPERTY: 'delete-property',
34
+ INSERT_CHILD: 'insert-child',
35
+ REPLACE_CHILD: 'replace-child',
36
+ MOVE_CHILD: 'move-child',
37
+ REMOVE_CHILD: 'remove-child',
38
+ SET_CONTENT: 'set-content',
39
+ } as const
40
+
41
+ /*
42
+ * A single change of the virtual and rendered DOM, applied by Patch.apply().
43
+ */
44
+ type Patch =
45
+ | { type: 'init-root-component'; root: WebComponent }
46
+ | {
47
+ type: 'update-node'
48
+ node: VirtualNode
49
+ prevDescription: NodeDescription
50
+ description: NodeDescription
51
+ }
52
+ | {
53
+ type: 'update-root'
54
+ root: WebComponent
55
+ description: ComponentDescription
56
+ }
57
+ | {
58
+ type: 'set-attribute'
59
+ name: string
60
+ value: string
61
+ target: PatchTarget
62
+ isCustom: boolean
63
+ }
64
+ | {
65
+ type: 'remove-attribute'
66
+ name: string
67
+ target: PatchTarget
68
+ isCustom: boolean
69
+ }
70
+ | {
71
+ type: 'set-data-attribute'
72
+ name: string
73
+ value: string
74
+ target: PatchTarget
75
+ }
76
+ | { type: 'remove-data-attribute'; name: string; target: PatchTarget }
77
+ | {
78
+ type: 'set-style-property'
79
+ property: string
80
+ value: string
81
+ target: PatchTarget
82
+ }
83
+ | { type: 'remove-style-property'; property: string; target: PatchTarget }
84
+ | { type: 'set-class-name'; className: string; target: PatchTarget }
85
+ | {
86
+ type: 'add-listener'
87
+ name: string
88
+ listener: Listener
89
+ target: PatchTarget
90
+ isCustom: boolean
91
+ }
92
+ | {
93
+ type: 'replace-listener'
94
+ name: string
95
+ removed: Listener
96
+ added: Listener
97
+ target: PatchTarget
98
+ isCustom: boolean
99
+ }
100
+ | {
101
+ type: 'remove-listener'
102
+ name: string
103
+ listener: Listener
104
+ target: PatchTarget
105
+ isCustom: boolean
106
+ }
107
+ | { type: 'set-property'; key: string; value: unknown; target: PatchTarget }
108
+ | { type: 'delete-property'; key: string; target: PatchTarget }
109
+ | {
110
+ type: 'insert-child'
111
+ node: VirtualNode
112
+ at: number
113
+ parent: ParentVirtualNode
114
+ }
115
+ | {
116
+ type: 'replace-child'
117
+ child: VirtualNode
118
+ node: VirtualNode
119
+ parent: ParentVirtualNode
120
+ }
121
+ | {
122
+ type: 'move-child'
123
+ child: VirtualNode
124
+ from: number
125
+ to: number
126
+ parent: ParentVirtualNode
127
+ }
128
+ | {
129
+ type: 'remove-child'
130
+ child: VirtualNode
131
+ at: number
132
+ parent: ParentVirtualNode
133
+ }
134
+ | {
135
+ type: 'set-content'
136
+ node: VirtualNode
137
+ child: VirtualNode
138
+ parent: Component
139
+ }
140
+
141
+ /* The patch of the given type. */
142
+ type PatchOf<T extends Patch['type']> = Extract<Patch, { type: T }>
143
+
144
+ const Patch = {
145
+ Type,
146
+
147
+ /**
148
+ * Applies the change to the virtual and rendered DOM.
149
+ */
150
+ apply(patch: Patch) {
151
+ switch (patch.type) {
152
+ case Type.INIT_ROOT_COMPONENT: {
153
+ const container = patch.root.container
154
+ ? patch.root.container
155
+ : patch.root.shadow!
156
+ container.appendChild(patch.root.content!.ref)
157
+ return
158
+ }
159
+ case Type.UPDATE_NODE:
160
+ patch.node.description = patch.description
161
+ return
162
+ case Type.UPDATE_ROOT:
163
+ patch.root.update(patch.description)
164
+ return
165
+ case Type.SET_ATTRIBUTE: {
166
+ const { target, name, value, isCustom } = patch
167
+ DOM.setAttribute(target.ref, name, value, isCustom)
168
+ return
169
+ }
170
+ case Type.REMOVE_ATTRIBUTE:
171
+ DOM.removeAttribute(patch.target.ref, patch.name, patch.isCustom)
172
+ return
173
+ case Type.SET_DATA_ATTRIBUTE:
174
+ DOM.setDataAttribute(patch.target.ref, patch.name, patch.value)
175
+ return
176
+ case Type.REMOVE_DATA_ATTRIBUTE:
177
+ DOM.removeDataAttribute(patch.target.ref, patch.name)
178
+ return
179
+ case Type.SET_STYLE_PROPERTY:
180
+ DOM.setStyleProperty(patch.target.ref, patch.property, patch.value)
181
+ return
182
+ case Type.REMOVE_STYLE_PROPERTY:
183
+ DOM.removeStyleProperty(patch.target.ref, patch.property)
184
+ return
185
+ case Type.SET_CLASS_NAME:
186
+ DOM.setClassName(patch.target.ref, patch.className)
187
+ return
188
+ case Type.ADD_LISTENER: {
189
+ const { target, name, listener, isCustom } = patch
190
+ DOM.addListener(target.ref, name, listener, isCustom)
191
+ return
192
+ }
193
+ case Type.REPLACE_LISTENER: {
194
+ const { target, name, removed, added, isCustom } = patch
195
+ DOM.removeListener(target.ref, name, removed, isCustom)
196
+ DOM.addListener(target.ref, name, added, isCustom)
197
+ return
198
+ }
199
+ case Type.REMOVE_LISTENER: {
200
+ const { target, name, listener, isCustom } = patch
201
+ DOM.removeListener(target.ref, name, listener, isCustom)
202
+ return
203
+ }
204
+ case Type.SET_PROPERTY:
205
+ DOM.setProperty(patch.target.ref, patch.key, patch.value)
206
+ return
207
+ case Type.DELETE_PROPERTY:
208
+ DOM.deleteProperty(patch.target.ref, patch.key)
209
+ return
210
+ case Type.INSERT_CHILD:
211
+ patch.parent.insertChild(patch.node, patch.at)
212
+ return
213
+ case Type.REPLACE_CHILD:
214
+ patch.parent.replaceChild(patch.child, patch.node)
215
+ return
216
+ case Type.MOVE_CHILD:
217
+ patch.parent.moveChild(patch.child, patch.from, patch.to)
218
+ return
219
+ case Type.REMOVE_CHILD:
220
+ patch.parent.removeChild(patch.child)
221
+ return
222
+ case Type.SET_CONTENT:
223
+ patch.parent.setContent(patch.node)
224
+ return
225
+ default: {
226
+ // fails to compile when a patch type is not handled above
227
+ const unsupported: never = patch
228
+ throw new Error(
229
+ `Unsupported patch type: ${(unsupported as Patch).type}`,
230
+ )
231
+ }
232
+ }
233
+ },
234
+
235
+ initRootComponent(root: WebComponent): PatchOf<'init-root-component'> {
236
+ return { type: Type.INIT_ROOT_COMPONENT, root }
237
+ },
238
+
239
+ updateNode(
240
+ node: VirtualNode,
241
+ description: NodeDescription,
242
+ ): PatchOf<'update-node'> {
243
+ return {
244
+ type: Type.UPDATE_NODE,
245
+ node,
246
+ prevDescription: node.description,
247
+ description,
248
+ }
249
+ },
250
+
251
+ /* Passes the props to a nested root, which renders them itself. */
252
+ updateRoot(
253
+ root: WebComponent,
254
+ description: ComponentDescription,
255
+ ): PatchOf<'update-root'> {
256
+ return { type: Type.UPDATE_ROOT, root, description }
257
+ },
258
+
259
+ insertChild(
260
+ node: VirtualNode,
261
+ at: number,
262
+ parent: ParentVirtualNode,
263
+ ): PatchOf<'insert-child'> {
264
+ return { type: Type.INSERT_CHILD, node, at, parent }
265
+ },
266
+
267
+ moveChild(
268
+ child: VirtualNode,
269
+ from: number,
270
+ to: number,
271
+ parent: ParentVirtualNode,
272
+ ): PatchOf<'move-child'> {
273
+ return { type: Type.MOVE_CHILD, child, from, to, parent }
274
+ },
275
+
276
+ replaceChild(
277
+ child: VirtualNode,
278
+ node: VirtualNode,
279
+ parent: ParentVirtualNode,
280
+ ): PatchOf<'replace-child'> {
281
+ return { type: Type.REPLACE_CHILD, child, node, parent }
282
+ },
283
+
284
+ removeChild(
285
+ child: VirtualNode,
286
+ at: number,
287
+ parent: ParentVirtualNode,
288
+ ): PatchOf<'remove-child'> {
289
+ return { type: Type.REMOVE_CHILD, child, at, parent }
290
+ },
291
+
292
+ setContent(node: VirtualNode, parent: Component): PatchOf<'set-content'> {
293
+ return { type: Type.SET_CONTENT, node, child: parent.content!, parent }
294
+ },
295
+
296
+ setAttribute(
297
+ name: string,
298
+ value: string,
299
+ target: VirtualElement | WebComponent,
300
+ isCustom: boolean,
301
+ ): PatchOf<'set-attribute'> {
302
+ return {
303
+ type: Type.SET_ATTRIBUTE,
304
+ name,
305
+ value,
306
+ target: target as PatchTarget,
307
+ isCustom,
308
+ }
309
+ },
310
+
311
+ removeAttribute(
312
+ name: string,
313
+ target: VirtualElement | WebComponent,
314
+ isCustom: boolean,
315
+ ): PatchOf<'remove-attribute'> {
316
+ return {
317
+ type: Type.REMOVE_ATTRIBUTE,
318
+ name,
319
+ target: target as PatchTarget,
320
+ isCustom,
321
+ }
322
+ },
323
+
324
+ setDataAttribute(
325
+ name: string,
326
+ value: string,
327
+ target: VirtualElement,
328
+ ): PatchOf<'set-data-attribute'> {
329
+ return { type: Type.SET_DATA_ATTRIBUTE, name, value, target }
330
+ },
331
+
332
+ removeDataAttribute(
333
+ name: string,
334
+ target: VirtualElement,
335
+ ): PatchOf<'remove-data-attribute'> {
336
+ return { type: Type.REMOVE_DATA_ATTRIBUTE, name, target }
337
+ },
338
+
339
+ setStyleProperty(
340
+ property: string,
341
+ value: string,
342
+ target: VirtualElement,
343
+ ): PatchOf<'set-style-property'> {
344
+ return { type: Type.SET_STYLE_PROPERTY, property, value, target }
345
+ },
346
+
347
+ removeStyleProperty(
348
+ property: string,
349
+ target: VirtualElement,
350
+ ): PatchOf<'remove-style-property'> {
351
+ return { type: Type.REMOVE_STYLE_PROPERTY, property, target }
352
+ },
353
+
354
+ setClassName(
355
+ className: string,
356
+ target: VirtualElement,
357
+ ): PatchOf<'set-class-name'> {
358
+ return { type: Type.SET_CLASS_NAME, className, target }
359
+ },
360
+
361
+ addListener(
362
+ name: string,
363
+ listener: Listener,
364
+ target: VirtualElement,
365
+ isCustom: boolean,
366
+ ): PatchOf<'add-listener'> {
367
+ return { type: Type.ADD_LISTENER, name, listener, target, isCustom }
368
+ },
369
+
370
+ replaceListener(
371
+ name: string,
372
+ removed: Listener,
373
+ added: Listener,
374
+ target: VirtualElement,
375
+ isCustom: boolean,
376
+ ): PatchOf<'replace-listener'> {
377
+ return {
378
+ type: Type.REPLACE_LISTENER,
379
+ name,
380
+ removed,
381
+ added,
382
+ target,
383
+ isCustom,
384
+ }
385
+ },
386
+
387
+ removeListener(
388
+ name: string,
389
+ listener: Listener,
390
+ target: VirtualElement,
391
+ isCustom: boolean,
392
+ ): PatchOf<'remove-listener'> {
393
+ return { type: Type.REMOVE_LISTENER, name, listener, target, isCustom }
394
+ },
395
+
396
+ setProperty(
397
+ key: string,
398
+ value: unknown,
399
+ target: VirtualElement,
400
+ ): PatchOf<'set-property'> {
401
+ return { type: Type.SET_PROPERTY, key, value, target }
402
+ },
403
+
404
+ deleteProperty(
405
+ key: string,
406
+ target: VirtualElement,
407
+ ): PatchOf<'delete-property'> {
408
+ return { type: Type.DELETE_PROPERTY, key, target }
409
+ },
410
+ }
411
+
412
+ export default Patch