glass-easel 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.
- package/README.md +40 -0
- package/dist/glass_easel.all.d.ts +1 -0
- package/dist/glass_easel.all.js +2 -0
- package/dist/glass_easel.all.js.map +1 -0
- package/dist/glass_easel.domlike.global.d.ts +1 -0
- package/dist/glass_easel.domlike.global.js +2 -0
- package/dist/glass_easel.domlike.global.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/types/src/backend/backend_protocol.d.ts +119 -0
- package/dist/types/src/backend/backend_protocol.d.ts.map +1 -0
- package/dist/types/src/backend/composed_backend_protocol.d.ts +90 -0
- package/dist/types/src/backend/composed_backend_protocol.d.ts.map +1 -0
- package/dist/types/src/backend/domlike_backend_protocol.d.ts +76 -0
- package/dist/types/src/backend/domlike_backend_protocol.d.ts.map +1 -0
- package/dist/types/src/backend/mode.d.ts +46 -0
- package/dist/types/src/backend/mode.d.ts.map +1 -0
- package/dist/types/src/backend/suggested_backend_protocol.d.ts +30 -0
- package/dist/types/src/backend/suggested_backend_protocol.d.ts.map +1 -0
- package/dist/types/src/behavior.d.ts +428 -0
- package/dist/types/src/behavior.d.ts.map +1 -0
- package/dist/types/src/class_list.d.ts +79 -0
- package/dist/types/src/class_list.d.ts.map +1 -0
- package/dist/types/src/component.d.ts +291 -0
- package/dist/types/src/component.d.ts.map +1 -0
- package/dist/types/src/component_params.d.ts +239 -0
- package/dist/types/src/component_params.d.ts.map +1 -0
- package/dist/types/src/component_space.d.ts +164 -0
- package/dist/types/src/component_space.d.ts.map +1 -0
- package/dist/types/src/data_path.d.ts +5 -0
- package/dist/types/src/data_path.d.ts.map +1 -0
- package/dist/types/src/data_proxy.d.ts +107 -0
- package/dist/types/src/data_proxy.d.ts.map +1 -0
- package/dist/types/src/data_utils.d.ts +3 -0
- package/dist/types/src/data_utils.d.ts.map +1 -0
- package/dist/types/src/element.d.ts +275 -0
- package/dist/types/src/element.d.ts.map +1 -0
- package/dist/types/src/element_iterator.d.ts +43 -0
- package/dist/types/src/element_iterator.d.ts.map +1 -0
- package/dist/types/src/event.d.ts +104 -0
- package/dist/types/src/event.d.ts.map +1 -0
- package/dist/types/src/external_shadow_tree.d.ts +20 -0
- package/dist/types/src/external_shadow_tree.d.ts.map +1 -0
- package/dist/types/src/func_arr.d.ts +39 -0
- package/dist/types/src/func_arr.d.ts.map +1 -0
- package/dist/types/src/global_options.d.ts +111 -0
- package/dist/types/src/global_options.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +43 -0
- package/dist/types/src/index.d.ts.map +1 -0
- package/dist/types/src/mutation_observer.d.ts +79 -0
- package/dist/types/src/mutation_observer.d.ts.map +1 -0
- package/dist/types/src/native_node.d.ts +8 -0
- package/dist/types/src/native_node.d.ts.map +1 -0
- package/dist/types/src/node.d.ts +49 -0
- package/dist/types/src/node.d.ts.map +1 -0
- package/dist/types/src/relation.d.ts +47 -0
- package/dist/types/src/relation.d.ts.map +1 -0
- package/dist/types/src/render.d.ts +3 -0
- package/dist/types/src/render.d.ts.map +1 -0
- package/dist/types/src/selector.d.ts +32 -0
- package/dist/types/src/selector.d.ts.map +1 -0
- package/dist/types/src/shadow_root.d.ts +136 -0
- package/dist/types/src/shadow_root.d.ts.map +1 -0
- package/dist/types/src/template_engine.d.ts +18 -0
- package/dist/types/src/template_engine.d.ts.map +1 -0
- package/dist/types/src/text_node.d.ts +32 -0
- package/dist/types/src/text_node.d.ts.map +1 -0
- package/dist/types/src/tmpl/index.d.ts +18 -0
- package/dist/types/src/tmpl/index.d.ts.map +1 -0
- package/dist/types/src/tmpl/native_rendering.d.ts +45 -0
- package/dist/types/src/tmpl/native_rendering.d.ts.map +1 -0
- package/dist/types/src/tmpl/proc_gen_wrapper.d.ts +80 -0
- package/dist/types/src/tmpl/proc_gen_wrapper.d.ts.map +1 -0
- package/dist/types/src/tmpl/proc_gen_wrapper_dom.d.ts +50 -0
- package/dist/types/src/tmpl/proc_gen_wrapper_dom.d.ts.map +1 -0
- package/dist/types/src/tmpl/range_list_diff.d.ts +19 -0
- package/dist/types/src/tmpl/range_list_diff.d.ts.map +1 -0
- package/dist/types/src/trait_behaviors.d.ts +38 -0
- package/dist/types/src/trait_behaviors.d.ts.map +1 -0
- package/dist/types/src/virtual_node.d.ts +10 -0
- package/dist/types/src/virtual_node.d.ts.map +1 -0
- package/dist/types/tests/backend/domlike.test.d.ts +2 -0
- package/dist/types/tests/backend/domlike.test.d.ts.map +1 -0
- package/dist/types/tests/base/env.d.ts +29 -0
- package/dist/types/tests/base/env.d.ts.map +1 -0
- package/dist/types/tests/base/match.d.ts +9 -0
- package/dist/types/tests/base/match.d.ts.map +1 -0
- package/dist/types/tests/core/backend.test.d.ts +2 -0
- package/dist/types/tests/core/backend.test.d.ts.map +1 -0
- package/dist/types/tests/core/behavior.test.d.ts +2 -0
- package/dist/types/tests/core/behavior.test.d.ts.map +1 -0
- package/dist/types/tests/core/component_space.test.d.ts +2 -0
- package/dist/types/tests/core/component_space.test.d.ts.map +1 -0
- package/dist/types/tests/core/data_update.test.d.ts +2 -0
- package/dist/types/tests/core/data_update.test.d.ts.map +1 -0
- package/dist/types/tests/core/misc.test.d.ts +2 -0
- package/dist/types/tests/core/misc.test.d.ts.map +1 -0
- package/dist/types/tests/core/placeholder.test.d.ts +2 -0
- package/dist/types/tests/core/placeholder.test.d.ts.map +1 -0
- package/dist/types/tests/core/slot.test.d.ts +2 -0
- package/dist/types/tests/core/slot.test.d.ts.map +1 -0
- package/dist/types/tests/core/trait_behaviors.test.d.ts +2 -0
- package/dist/types/tests/core/trait_behaviors.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/binding_map.test.d.ts +2 -0
- package/dist/types/tests/tmpl/binding_map.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/event.test.d.ts +2 -0
- package/dist/types/tests/tmpl/event.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/expression.test.d.ts +2 -0
- package/dist/types/tests/tmpl/expression.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/lvalue.test.d.ts +2 -0
- package/dist/types/tests/tmpl/lvalue.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/native_rendering.test.d.ts +2 -0
- package/dist/types/tests/tmpl/native_rendering.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/structure.test.d.ts +2 -0
- package/dist/types/tests/tmpl/structure.test.d.ts.map +1 -0
- package/dist/types/tests/types/chaining.test.d.ts +2 -0
- package/dist/types/tests/types/chaining.test.d.ts.map +1 -0
- package/dist/types/tests/types/createElement.test.d.ts +2 -0
- package/dist/types/tests/types/createElement.test.d.ts.map +1 -0
- package/dist/types/tests/types/definition.test.d.ts +2 -0
- package/dist/types/tests/types/definition.test.d.ts.map +1 -0
- package/guide/zh_CN/advanced/binding_map_update.md +32 -0
- package/guide/zh_CN/advanced/build_args.md +28 -0
- package/guide/zh_CN/advanced/component_filter.md +70 -0
- package/guide/zh_CN/advanced/component_space.md +124 -0
- package/guide/zh_CN/advanced/custom_backend.md +53 -0
- package/guide/zh_CN/advanced/error_listener.md +32 -0
- package/guide/zh_CN/advanced/external_component.md +73 -0
- package/guide/zh_CN/advanced/template_engine.md +61 -0
- package/guide/zh_CN/appendix/backend_protocol.md +501 -0
- package/guide/zh_CN/appendix/list_diff_algorithm.md +406 -0
- package/guide/zh_CN/basic/beginning.md +94 -0
- package/guide/zh_CN/basic/component.md +156 -0
- package/guide/zh_CN/basic/event.md +169 -0
- package/guide/zh_CN/basic/lifetime.md +66 -0
- package/guide/zh_CN/basic/method.md +62 -0
- package/guide/zh_CN/basic/template.md +135 -0
- package/guide/zh_CN/data_management/advanced_update.md +170 -0
- package/guide/zh_CN/data_management/data_deep_copy.md +157 -0
- package/guide/zh_CN/data_management/data_observer.md +154 -0
- package/guide/zh_CN/data_management/property_early_init.md +31 -0
- package/guide/zh_CN/data_management/pure_data_pattern.md +21 -0
- package/guide/zh_CN/index.md +93 -0
- package/guide/zh_CN/interaction/behavior.md +52 -0
- package/guide/zh_CN/interaction/component_path.md +37 -0
- package/guide/zh_CN/interaction/generic.md +73 -0
- package/guide/zh_CN/interaction/placeholder.md +40 -0
- package/guide/zh_CN/interaction/relation.md +151 -0
- package/guide/zh_CN/interaction/slot.md +137 -0
- package/guide/zh_CN/interaction/template_import.md +94 -0
- package/guide/zh_CN/interaction/trait_behavior.md +117 -0
- package/guide/zh_CN/styling/external_class.md +46 -0
- package/guide/zh_CN/styling/style_isolation.md +54 -0
- package/guide/zh_CN/styling/virtual_host.md +52 -0
- package/guide/zh_CN/tree/element_iterator.md +54 -0
- package/guide/zh_CN/tree/mutation_observer.md +52 -0
- package/guide/zh_CN/tree/node_tree.md +142 -0
- package/guide/zh_CN/tree/node_tree_modification.md +78 -0
- package/guide/zh_CN/tree/selector.md +66 -0
- package/jest.config.js +6 -0
- package/jest.dts.config.js +9 -0
- package/jest.unit.config.js +14 -0
- package/package.json +28 -0
- package/src/backend/backend_protocol.ts +313 -0
- package/src/backend/composed_backend_protocol.ts +252 -0
- package/src/backend/domlike_backend_protocol.ts +370 -0
- package/src/backend/mode.ts +51 -0
- package/src/backend/suggested_backend_protocol.ts +83 -0
- package/src/behavior.ts +1655 -0
- package/src/bootstrap_dom_dev.js +22 -0
- package/src/class_list.ts +376 -0
- package/src/component.ts +1309 -0
- package/src/component_params.ts +461 -0
- package/src/component_space.ts +547 -0
- package/src/data_path.ts +225 -0
- package/src/data_proxy.ts +670 -0
- package/src/data_utils.ts +50 -0
- package/src/element.ts +1966 -0
- package/src/element_iterator.ts +158 -0
- package/src/event.ts +401 -0
- package/src/external_shadow_tree.ts +27 -0
- package/src/func_arr.ts +198 -0
- package/src/global_options.ts +242 -0
- package/src/index.ts +187 -0
- package/src/mutation_observer.ts +252 -0
- package/src/native_node.ts +74 -0
- package/src/node.ts +174 -0
- package/src/relation.ts +380 -0
- package/src/render.ts +25 -0
- package/src/selector.ts +218 -0
- package/src/shadow_root.ts +766 -0
- package/src/template_engine.ts +45 -0
- package/src/text_node.ts +149 -0
- package/src/tmpl/index.ts +199 -0
- package/src/tmpl/native_rendering.ts +175 -0
- package/src/tmpl/proc_gen_wrapper.ts +954 -0
- package/src/tmpl/proc_gen_wrapper_dom.ts +230 -0
- package/src/tmpl/range_list_diff.ts +443 -0
- package/src/trait_behaviors.ts +51 -0
- package/src/virtual_node.ts +51 -0
- package/tests/backend/domlike.test.ts +254 -0
- package/tests/base/env.ts +78 -0
- package/tests/base/match.ts +185 -0
- package/tests/core/backend.test.ts +144 -0
- package/tests/core/behavior.test.ts +546 -0
- package/tests/core/component_space.test.ts +212 -0
- package/tests/core/data_update.test.ts +461 -0
- package/tests/core/misc.test.ts +339 -0
- package/tests/core/placeholder.test.ts +180 -0
- package/tests/core/slot.test.ts +1495 -0
- package/tests/core/trait_behaviors.test.ts +153 -0
- package/tests/legacy/README.md +3 -0
- package/tests/legacy/behavior.test.js +293 -0
- package/tests/legacy/component.test.js +1247 -0
- package/tests/legacy/data_path.test.js +149 -0
- package/tests/legacy/data_proxy.test.js +759 -0
- package/tests/legacy/element_iterator.test.js +148 -0
- package/tests/legacy/event.test.js +849 -0
- package/tests/legacy/external.test.js +510 -0
- package/tests/legacy/extra_info.test.js +109 -0
- package/tests/legacy/generics.test.js +176 -0
- package/tests/legacy/mutation_observer.test.js +210 -0
- package/tests/legacy/relation.test.js +517 -0
- package/tests/legacy/selector.test.js +263 -0
- package/tests/legacy/slot.test.js +915 -0
- package/tests/legacy/virtual.test.js +394 -0
- package/tests/tmpl/binding_map.test.ts +208 -0
- package/tests/tmpl/event.test.ts +206 -0
- package/tests/tmpl/expression.test.ts +429 -0
- package/tests/tmpl/lvalue.test.ts +160 -0
- package/tests/tmpl/native_rendering.test.ts +155 -0
- package/tests/tmpl/structure.test.ts +998 -0
- package/tests/types/chaining.test.ts +614 -0
- package/tests/types/createElement.test.ts +82 -0
- package/tests/types/definition.test.ts +442 -0
- package/tsconfig.json +11 -0
- package/webpack.config.js +270 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
GeneralBehavior,
|
|
3
|
+
} from './behavior'
|
|
4
|
+
import {
|
|
5
|
+
GeneralComponentInstance,
|
|
6
|
+
} from './component_params'
|
|
7
|
+
import {
|
|
8
|
+
ShadowRoot,
|
|
9
|
+
} from './shadow_root'
|
|
10
|
+
import {
|
|
11
|
+
DataChange,
|
|
12
|
+
DataValue,
|
|
13
|
+
} from './data_proxy'
|
|
14
|
+
import {
|
|
15
|
+
NormalizedComponentOptions,
|
|
16
|
+
} from './global_options'
|
|
17
|
+
import {
|
|
18
|
+
ExternalShadowRoot,
|
|
19
|
+
} from './external_shadow_tree'
|
|
20
|
+
|
|
21
|
+
export interface TemplateEngine {
|
|
22
|
+
create(
|
|
23
|
+
behavior: GeneralBehavior,
|
|
24
|
+
componentOptions: NormalizedComponentOptions,
|
|
25
|
+
): Template
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface Template {
|
|
29
|
+
createInstance(
|
|
30
|
+
elem: GeneralComponentInstance,
|
|
31
|
+
): TemplateInstance
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface TemplateInstance {
|
|
35
|
+
shadowRoot: ShadowRoot | ExternalShadowRoot
|
|
36
|
+
|
|
37
|
+
initValues(
|
|
38
|
+
data: DataValue,
|
|
39
|
+
): void
|
|
40
|
+
|
|
41
|
+
updateValues(
|
|
42
|
+
data: DataValue,
|
|
43
|
+
changes: DataChange[],
|
|
44
|
+
): void
|
|
45
|
+
}
|
package/src/text_node.ts
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import * as backend from './backend/backend_protocol'
|
|
2
|
+
import * as composedBackend from './backend/composed_backend_protocol'
|
|
3
|
+
import * as domlikeBackend from './backend/domlike_backend_protocol'
|
|
4
|
+
import {
|
|
5
|
+
ShadowRoot,
|
|
6
|
+
} from './shadow_root'
|
|
7
|
+
import {
|
|
8
|
+
Element,
|
|
9
|
+
} from './element'
|
|
10
|
+
import {
|
|
11
|
+
MutationObserverTarget,
|
|
12
|
+
} from './mutation_observer'
|
|
13
|
+
import {
|
|
14
|
+
GeneralBackendElement, NodeCast,
|
|
15
|
+
} from './node'
|
|
16
|
+
import {
|
|
17
|
+
BM,
|
|
18
|
+
BackendMode,
|
|
19
|
+
} from './backend/mode'
|
|
20
|
+
import {
|
|
21
|
+
Component,
|
|
22
|
+
} from './component'
|
|
23
|
+
|
|
24
|
+
export class TextNode implements NodeCast {
|
|
25
|
+
private _$backendElement: GeneralBackendElement | null
|
|
26
|
+
private _$text: string
|
|
27
|
+
ownerShadowRoot: ShadowRoot
|
|
28
|
+
parentNode: Element | null
|
|
29
|
+
/** @internal */
|
|
30
|
+
_$destroyOnDetach = false
|
|
31
|
+
/** @internal */
|
|
32
|
+
_$nodeSlotElement: Element | null
|
|
33
|
+
|
|
34
|
+
constructor(
|
|
35
|
+
text: string,
|
|
36
|
+
owner: ShadowRoot,
|
|
37
|
+
) {
|
|
38
|
+
this._$text = String(text)
|
|
39
|
+
let backendElement: GeneralBackendElement | null
|
|
40
|
+
if (BM.DOMLIKE || (BM.DYNAMIC && owner.getBackendMode() === BackendMode.Domlike)) {
|
|
41
|
+
backendElement = (owner._$nodeTreeContext as domlikeBackend.Context)
|
|
42
|
+
.document.createTextNode(text)
|
|
43
|
+
} else if (BM.SHADOW || (BM.DYNAMIC && owner.getBackendMode() === BackendMode.Shadow)) {
|
|
44
|
+
const backend = owner._$backendShadowRoot
|
|
45
|
+
backendElement = backend?.createTextNode(text) || null
|
|
46
|
+
} else {
|
|
47
|
+
const backend = owner._$nodeTreeContext as composedBackend.Context
|
|
48
|
+
backendElement = backend.createTextNode(text)
|
|
49
|
+
}
|
|
50
|
+
this._$backendElement = backendElement
|
|
51
|
+
if (backendElement) {
|
|
52
|
+
backendElement.__wxElement = this
|
|
53
|
+
}
|
|
54
|
+
this.ownerShadowRoot = owner
|
|
55
|
+
this.parentNode = null
|
|
56
|
+
this._$nodeSlotElement = null
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
static create(
|
|
60
|
+
text: string,
|
|
61
|
+
ownerShadowRoot: ShadowRoot,
|
|
62
|
+
): TextNode {
|
|
63
|
+
return new TextNode(text, ownerShadowRoot)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
asTextNode(): TextNode {
|
|
67
|
+
return this
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// eslint-disable-next-line class-methods-use-this
|
|
71
|
+
asElement(): null {
|
|
72
|
+
return null
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// eslint-disable-next-line class-methods-use-this
|
|
76
|
+
asNativeNode(): null {
|
|
77
|
+
return null
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// eslint-disable-next-line class-methods-use-this
|
|
81
|
+
asVirtualNode(): null {
|
|
82
|
+
return null
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// eslint-disable-next-line class-methods-use-this
|
|
86
|
+
asInstanceOf(): null {
|
|
87
|
+
return null
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Destroy the backend element */
|
|
91
|
+
destroyBackendElement() {
|
|
92
|
+
if (this._$backendElement) {
|
|
93
|
+
if (!(
|
|
94
|
+
BM.DOMLIKE || (BM.DYNAMIC && this.ownerShadowRoot.getBackendMode() === BackendMode.Domlike)
|
|
95
|
+
)) {
|
|
96
|
+
(this._$backendElement as backend.Element | composedBackend.Element).release()
|
|
97
|
+
}
|
|
98
|
+
this._$backendElement = null
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Destroy the backend element on next detach */
|
|
103
|
+
destroyBackendElementOnDetach() {
|
|
104
|
+
this._$destroyOnDetach = true
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Get the backend element */
|
|
108
|
+
getBackendElement(): GeneralBackendElement | null {
|
|
109
|
+
return this._$backendElement
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Get composed parent (including virtual nodes) */
|
|
113
|
+
getComposedParent(): Element | null {
|
|
114
|
+
let parent = this.parentNode
|
|
115
|
+
while (parent?._$inheritSlots) {
|
|
116
|
+
parent = parent.parentNode
|
|
117
|
+
}
|
|
118
|
+
if (parent instanceof Component && !parent._$external) {
|
|
119
|
+
const slot = (parent.shadowRoot as ShadowRoot).getContainingSlot(this)
|
|
120
|
+
return slot
|
|
121
|
+
}
|
|
122
|
+
return parent
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
get $$() {
|
|
126
|
+
return this._$backendElement
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
get textContent() {
|
|
130
|
+
return this._$text
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
set textContent(text: string) {
|
|
134
|
+
this._$text = String(text)
|
|
135
|
+
if (this._$backendElement) {
|
|
136
|
+
if (
|
|
137
|
+
BM.DOMLIKE || (BM.DYNAMIC && this.ownerShadowRoot.getBackendMode() === BackendMode.Domlike)
|
|
138
|
+
) {
|
|
139
|
+
(this._$backendElement as domlikeBackend.Element).textContent = this._$text
|
|
140
|
+
} else {
|
|
141
|
+
(this._$backendElement as backend.Element | composedBackend.Element).setText(this._$text)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
MutationObserverTarget.callTextObservers(this, {
|
|
145
|
+
type: 'characterData',
|
|
146
|
+
target: this,
|
|
147
|
+
})
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/* eslint-disable class-methods-use-this */
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
ShadowRoot,
|
|
5
|
+
ExternalShadowRoot,
|
|
6
|
+
DataValue,
|
|
7
|
+
templateEngine,
|
|
8
|
+
GeneralBehavior,
|
|
9
|
+
NormalizedComponentOptions,
|
|
10
|
+
GeneralComponent,
|
|
11
|
+
} from '..'
|
|
12
|
+
import { DataChange } from '../data_proxy'
|
|
13
|
+
import { GlassEaselTemplateDOM } from './native_rendering'
|
|
14
|
+
import {
|
|
15
|
+
ProcGenWrapper,
|
|
16
|
+
ProcGenEnv,
|
|
17
|
+
ProcGen,
|
|
18
|
+
BindingMapGen,
|
|
19
|
+
UpdatePathTreeNode,
|
|
20
|
+
} from './proc_gen_wrapper'
|
|
21
|
+
|
|
22
|
+
const DEFAULT_PROC_GEN: ProcGen = () => ({
|
|
23
|
+
C: (isCreation, defineTextNode, defineElement, defineIfGroup, defineForLoop, defineSlot) => {
|
|
24
|
+
defineSlot('')
|
|
25
|
+
},
|
|
26
|
+
B: Object.create(null) as { [field: string]: BindingMapGen[] },
|
|
27
|
+
})
|
|
28
|
+
export const DEFAULT_PROC_GEN_GROUP: (name: string) => ProcGen = () => DEFAULT_PROC_GEN
|
|
29
|
+
|
|
30
|
+
export type ProcGenGroup = (name: string) => ProcGen
|
|
31
|
+
|
|
32
|
+
export type ProcGenGroupList = { [path: string]: ProcGenGroup }
|
|
33
|
+
|
|
34
|
+
export type ComponentTemplate = {
|
|
35
|
+
groupList?: ProcGenGroupList,
|
|
36
|
+
content: (name: string) => ProcGen,
|
|
37
|
+
updateMode?: string,
|
|
38
|
+
disallowNativeNode?: boolean,
|
|
39
|
+
procGenWrapperType?: typeof ProcGenWrapper,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const enum BindingMapUpdateEnabled {
|
|
43
|
+
Disabled,
|
|
44
|
+
Enabled,
|
|
45
|
+
Forced,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export class GlassEaselTemplateEngine implements templateEngine.TemplateEngine {
|
|
49
|
+
create(
|
|
50
|
+
behavior: GeneralBehavior,
|
|
51
|
+
componentOptions: NormalizedComponentOptions,
|
|
52
|
+
): templateEngine.Template {
|
|
53
|
+
if (componentOptions.externalComponent) {
|
|
54
|
+
return new GlassEaselTemplateDOM(behavior)
|
|
55
|
+
}
|
|
56
|
+
return new GlassEaselTemplate(behavior)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
class GlassEaselTemplate implements templateEngine.Template {
|
|
61
|
+
genObjectGroupEnv: ProcGenEnv
|
|
62
|
+
updateMode: string
|
|
63
|
+
disallowNativeNode: boolean
|
|
64
|
+
|
|
65
|
+
constructor(
|
|
66
|
+
behavior: GeneralBehavior,
|
|
67
|
+
) {
|
|
68
|
+
if (typeof behavior._$template !== 'object' && behavior._$template !== undefined) {
|
|
69
|
+
throw new Error(`Component template of ${behavior.is} must be a valid compiled template (or "null" for default template).`)
|
|
70
|
+
}
|
|
71
|
+
const c = (behavior._$template as ComponentTemplate | null | undefined) || {
|
|
72
|
+
content: DEFAULT_PROC_GEN_GROUP,
|
|
73
|
+
}
|
|
74
|
+
this.genObjectGroupEnv = {
|
|
75
|
+
list: c.groupList || (Object.create(null) as ProcGenGroupList),
|
|
76
|
+
group: c.content,
|
|
77
|
+
}
|
|
78
|
+
this.updateMode = c.updateMode || ''
|
|
79
|
+
this.disallowNativeNode = c.disallowNativeNode || false
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
createInstance(
|
|
83
|
+
comp: GeneralComponent,
|
|
84
|
+
): templateEngine.TemplateInstance {
|
|
85
|
+
return new GlassEaselTemplateInstance(this, comp)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
class GlassEaselTemplateInstance implements templateEngine.TemplateInstance {
|
|
90
|
+
template: GlassEaselTemplate
|
|
91
|
+
comp: GeneralComponent
|
|
92
|
+
shadowRoot: ShadowRoot
|
|
93
|
+
procGenWrapper: ProcGenWrapper
|
|
94
|
+
bindingMapGen: { [field: string]: BindingMapGen[] } | undefined
|
|
95
|
+
forceBindingMapUpdate: BindingMapUpdateEnabled
|
|
96
|
+
|
|
97
|
+
constructor(template: GlassEaselTemplate, comp: GeneralComponent) {
|
|
98
|
+
this.template = template
|
|
99
|
+
const procGen = template.genObjectGroupEnv.group('') || DEFAULT_PROC_GEN_GROUP('')
|
|
100
|
+
if (template.updateMode === 'bindingMap') {
|
|
101
|
+
this.forceBindingMapUpdate = BindingMapUpdateEnabled.Forced
|
|
102
|
+
} else if (template.updateMode === 'virtualTree') {
|
|
103
|
+
this.forceBindingMapUpdate = BindingMapUpdateEnabled.Disabled
|
|
104
|
+
} else {
|
|
105
|
+
this.forceBindingMapUpdate = BindingMapUpdateEnabled.Enabled
|
|
106
|
+
}
|
|
107
|
+
this.comp = comp
|
|
108
|
+
this.shadowRoot = ShadowRoot.createShadowRoot(comp)
|
|
109
|
+
this.shadowRoot.destroyBackendElementOnDetach()
|
|
110
|
+
this.procGenWrapper = new ProcGenWrapper(this.shadowRoot, procGen, template.disallowNativeNode)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
initValues(
|
|
114
|
+
data: DataValue,
|
|
115
|
+
): ShadowRoot | ExternalShadowRoot {
|
|
116
|
+
this.bindingMapGen = this.procGenWrapper.create(data)
|
|
117
|
+
return this.shadowRoot
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
updateValues(
|
|
121
|
+
data: DataValue,
|
|
122
|
+
changes: DataChange[],
|
|
123
|
+
) {
|
|
124
|
+
if (this.forceBindingMapUpdate === BindingMapUpdateEnabled.Forced) {
|
|
125
|
+
for (let i = 0; i < changes.length; i += 1) {
|
|
126
|
+
this.tryBindingMapUpdate(data, changes[i])
|
|
127
|
+
}
|
|
128
|
+
return
|
|
129
|
+
}
|
|
130
|
+
if (this.forceBindingMapUpdate === BindingMapUpdateEnabled.Enabled && changes.length <= 1) {
|
|
131
|
+
if (this.bindingMapGen) {
|
|
132
|
+
if (this.tryBindingMapUpdate(data, changes[0])) {
|
|
133
|
+
return
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const dataUpdatePathTree: UpdatePathTreeNode = Object.create(null) as UpdatePathTreeNode
|
|
138
|
+
for (let i = 0; i < changes.length; i += 1) {
|
|
139
|
+
const [p, newVal, spliceIndex, spliceDel] = changes[i]!
|
|
140
|
+
let cur = dataUpdatePathTree as { [key: string]: UpdatePathTreeNode }
|
|
141
|
+
for (let j = 0; j < p.length; j += 1) {
|
|
142
|
+
const field = p[j]!
|
|
143
|
+
const v = cur[field]
|
|
144
|
+
if (v === true) break
|
|
145
|
+
if (j === p.length - 1) {
|
|
146
|
+
if (spliceDel === undefined) {
|
|
147
|
+
cur[field] = true
|
|
148
|
+
} else {
|
|
149
|
+
const startIndex = spliceIndex
|
|
150
|
+
if (v === undefined) {
|
|
151
|
+
cur[field] = new Array(startIndex)
|
|
152
|
+
} else if (!Array.isArray(v)) {
|
|
153
|
+
const arr = new Array(startIndex)
|
|
154
|
+
const keys = Object.keys(v)
|
|
155
|
+
for (let i = 0; i < keys.length; i += 1) {
|
|
156
|
+
const key = keys[i]!
|
|
157
|
+
const item = v[key]!
|
|
158
|
+
const index = Number(key)
|
|
159
|
+
if (arr.length < index) arr.length = index
|
|
160
|
+
arr[key as unknown as number] = item
|
|
161
|
+
}
|
|
162
|
+
cur[field] = arr
|
|
163
|
+
}
|
|
164
|
+
const arr = cur[field] as UpdatePathTreeNode[]
|
|
165
|
+
if (arr.length < startIndex) {
|
|
166
|
+
arr.length = startIndex
|
|
167
|
+
}
|
|
168
|
+
const inserts = new Array(newVal.length)
|
|
169
|
+
inserts.fill(true)
|
|
170
|
+
arr.splice(spliceIndex, spliceDel, ...inserts)
|
|
171
|
+
}
|
|
172
|
+
break
|
|
173
|
+
}
|
|
174
|
+
if (v === undefined) {
|
|
175
|
+
const next = Object.create(null) as { [key: string]: UpdatePathTreeNode }
|
|
176
|
+
cur[field] = next
|
|
177
|
+
cur = next
|
|
178
|
+
} else {
|
|
179
|
+
cur = v as { [key: string]: UpdatePathTreeNode }
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
this.procGenWrapper.update(data, dataUpdatePathTree)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
tryBindingMapUpdate(
|
|
187
|
+
data: DataValue,
|
|
188
|
+
change?: DataChange,
|
|
189
|
+
): boolean {
|
|
190
|
+
if (!change) return true
|
|
191
|
+
const bindingMapGen = this.bindingMapGen
|
|
192
|
+
if (!bindingMapGen) {
|
|
193
|
+
return false
|
|
194
|
+
}
|
|
195
|
+
const [path] = change
|
|
196
|
+
if (path.length !== 1) return false
|
|
197
|
+
return this.procGenWrapper.bindingMapUpdate(path[0] as string, data, bindingMapGen)
|
|
198
|
+
}
|
|
199
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/* global document: false */
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
ExternalShadowRoot,
|
|
5
|
+
DataValue,
|
|
6
|
+
templateEngine,
|
|
7
|
+
GeneralFuncType,
|
|
8
|
+
GeneralBehavior,
|
|
9
|
+
Event,
|
|
10
|
+
ShadowedEvent,
|
|
11
|
+
GeneralBackendElement,
|
|
12
|
+
BackendMode,
|
|
13
|
+
GeneralComponent,
|
|
14
|
+
} from '..'
|
|
15
|
+
import { DataChange } from '../data_proxy'
|
|
16
|
+
import {
|
|
17
|
+
ProcGenEnv,
|
|
18
|
+
ProcGen,
|
|
19
|
+
BindingMapGen,
|
|
20
|
+
} from './proc_gen_wrapper'
|
|
21
|
+
import {
|
|
22
|
+
ProcGenWrapperDom,
|
|
23
|
+
} from './proc_gen_wrapper_dom'
|
|
24
|
+
import {
|
|
25
|
+
ComponentTemplate,
|
|
26
|
+
ProcGenGroupList,
|
|
27
|
+
} from './index'
|
|
28
|
+
|
|
29
|
+
type ElementWithEvent = Element & {
|
|
30
|
+
_$wxTmplEv: { [ev: string]: (event: ShadowedEvent<unknown>) => unknown }
|
|
31
|
+
}
|
|
32
|
+
export type ExternalEvent = Event<unknown> & { target: Element, currentTarget: Element }
|
|
33
|
+
|
|
34
|
+
const DEFAULT_PROC_GEN_DOM: ProcGen = () => ({
|
|
35
|
+
C: (isCreation, defineTextNode, defineElement, defineIfGroup, defineForLoop, defineSlot) => {
|
|
36
|
+
defineSlot('')
|
|
37
|
+
},
|
|
38
|
+
B: Object.create(null) as { [field: string]: BindingMapGen[] },
|
|
39
|
+
})
|
|
40
|
+
export const DEFAULT_PROC_GEN_GROUP_DOM: (name: string) => ProcGen = () => DEFAULT_PROC_GEN_DOM
|
|
41
|
+
|
|
42
|
+
export class GlassEaselTemplateDOM implements templateEngine.Template {
|
|
43
|
+
data: DataValue
|
|
44
|
+
innerData: DataValue
|
|
45
|
+
genObjectGroupEnv: ProcGenEnv
|
|
46
|
+
updateMode: string
|
|
47
|
+
methods: { [name: string]: GeneralFuncType }
|
|
48
|
+
|
|
49
|
+
constructor(
|
|
50
|
+
behavior: GeneralBehavior,
|
|
51
|
+
) {
|
|
52
|
+
if (typeof behavior._$template !== 'object' && behavior._$template !== undefined) {
|
|
53
|
+
throw new Error(`Component template of ${behavior.is} must be a valid compiled template (or "null" for default template).`)
|
|
54
|
+
} else {
|
|
55
|
+
const c = (behavior._$template as ComponentTemplate | null | undefined) || {
|
|
56
|
+
content: DEFAULT_PROC_GEN_GROUP_DOM,
|
|
57
|
+
}
|
|
58
|
+
this.genObjectGroupEnv = {
|
|
59
|
+
list: c.groupList || (Object.create(null) as ProcGenGroupList),
|
|
60
|
+
group: c.content,
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
this.updateMode = ''
|
|
64
|
+
this.methods = behavior._$methodMap
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
createInstance(
|
|
68
|
+
comp: GeneralComponent,
|
|
69
|
+
): templateEngine.TemplateInstance {
|
|
70
|
+
return new GlassEaselTemplateDOMInstance(this, comp)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export class GlassEaselTemplateDOMInstance
|
|
75
|
+
implements templateEngine.TemplateInstance, ExternalShadowRoot {
|
|
76
|
+
template: GlassEaselTemplateDOM
|
|
77
|
+
comp: GeneralComponent
|
|
78
|
+
shadowRoot: ExternalShadowRoot
|
|
79
|
+
shadowRootElement: Element
|
|
80
|
+
root: GeneralBackendElement
|
|
81
|
+
slot: GeneralBackendElement
|
|
82
|
+
idMap: { [key: string]: Element }
|
|
83
|
+
listeners: Array<unknown>
|
|
84
|
+
procGenWrapper: ProcGenWrapperDom
|
|
85
|
+
bindingMapGen: { [field: string]: BindingMapGen[] } | undefined
|
|
86
|
+
|
|
87
|
+
constructor(template: GlassEaselTemplateDOM, comp: GeneralComponent) {
|
|
88
|
+
if (comp.getBackendMode() !== BackendMode.Domlike) {
|
|
89
|
+
throw new Error(`Component template of ${comp.is} cannot be initialized since external rendering is only supported in Domlike backend currently.`)
|
|
90
|
+
}
|
|
91
|
+
const shadowRootElement = comp.getBackendElement() as unknown as Element
|
|
92
|
+
if (!shadowRootElement) {
|
|
93
|
+
throw new Error(`Component template of ${comp.is} cannot be initialized as external components since no suitable backend element found.`)
|
|
94
|
+
}
|
|
95
|
+
this.comp = comp
|
|
96
|
+
this.shadowRoot = this
|
|
97
|
+
this.shadowRootElement = shadowRootElement
|
|
98
|
+
this.root = shadowRootElement as unknown as GeneralBackendElement
|
|
99
|
+
this.slot = shadowRootElement as unknown as GeneralBackendElement
|
|
100
|
+
this.template = template
|
|
101
|
+
const procGen = template.genObjectGroupEnv.group('') || DEFAULT_PROC_GEN_GROUP_DOM('')
|
|
102
|
+
this.procGenWrapper = new ProcGenWrapperDom(this, procGen)
|
|
103
|
+
this.idMap = Object.create(null) as { [key: string]: Element }
|
|
104
|
+
this.listeners = []
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
initValues(
|
|
108
|
+
data: DataValue,
|
|
109
|
+
) {
|
|
110
|
+
this.bindingMapGen = this.procGenWrapper.create(data)
|
|
111
|
+
if (!this.bindingMapGen) {
|
|
112
|
+
throw new Error('The component template does not support binding-map-update, so it cannot be used as external components.')
|
|
113
|
+
}
|
|
114
|
+
const shadowRoot = this.shadowRootElement
|
|
115
|
+
if (this.slot as unknown as Element === shadowRoot && shadowRoot.childNodes.length > 0) {
|
|
116
|
+
// if `<slot />` is forgot, add one at the end of the child list
|
|
117
|
+
const slot = document.createElement('virtual')
|
|
118
|
+
shadowRoot.appendChild(slot)
|
|
119
|
+
this.slot = slot as unknown as GeneralBackendElement
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
getIdMap(): { [key: string]: GeneralBackendElement } {
|
|
124
|
+
return this.idMap as unknown as { [key: string]: GeneralBackendElement }
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
updateValues(
|
|
128
|
+
data: DataValue,
|
|
129
|
+
changes: DataChange[],
|
|
130
|
+
) {
|
|
131
|
+
const bindingMapGen = this.bindingMapGen!
|
|
132
|
+
for (let i = 0; i < changes.length; i += 1) {
|
|
133
|
+
const [path] = changes[i]!
|
|
134
|
+
this.procGenWrapper.bindingMapUpdate(path[0] as string, data, bindingMapGen)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// eslint-disable-next-line class-methods-use-this
|
|
139
|
+
setListener<T>(
|
|
140
|
+
elem: GeneralBackendElement,
|
|
141
|
+
ev: string,
|
|
142
|
+
listener: (event: ShadowedEvent<T>) => unknown,
|
|
143
|
+
) {
|
|
144
|
+
const target = elem as unknown as ElementWithEvent
|
|
145
|
+
if (target._$wxTmplEv) {
|
|
146
|
+
target._$wxTmplEv[ev] = listener as (event: ShadowedEvent<unknown>) => unknown
|
|
147
|
+
} else {
|
|
148
|
+
target._$wxTmplEv = { [ev]: listener as (event: ShadowedEvent<unknown>) => unknown }
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
handleEvent(elem: GeneralBackendElement, event: Event<unknown>) {
|
|
153
|
+
const target = elem as unknown as ElementWithEvent
|
|
154
|
+
let cur: Element = target
|
|
155
|
+
const root = this.shadowRootElement
|
|
156
|
+
const evName = event.type
|
|
157
|
+
const bubbles = event.bubbles
|
|
158
|
+
for (;;) {
|
|
159
|
+
const shadowedEvent = event.wrapShadowedEvent(target as any, null, cur as any)
|
|
160
|
+
const f = (cur as unknown as ElementWithEvent)._$wxTmplEv?.[evName]
|
|
161
|
+
if (f) {
|
|
162
|
+
const r = f.call(cur, shadowedEvent)
|
|
163
|
+
if (r === false) {
|
|
164
|
+
event.preventDefault()
|
|
165
|
+
event.stopPropagation()
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (!bubbles || event.propagationStopped()) break
|
|
169
|
+
if (cur === root) break
|
|
170
|
+
const next = cur.parentNode
|
|
171
|
+
if (next) cur = next as Element
|
|
172
|
+
else break
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|