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.
Files changed (237) hide show
  1. package/README.md +40 -0
  2. package/dist/glass_easel.all.d.ts +1 -0
  3. package/dist/glass_easel.all.js +2 -0
  4. package/dist/glass_easel.all.js.map +1 -0
  5. package/dist/glass_easel.domlike.global.d.ts +1 -0
  6. package/dist/glass_easel.domlike.global.js +2 -0
  7. package/dist/glass_easel.domlike.global.js.map +1 -0
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.js +1 -0
  10. package/dist/types/src/backend/backend_protocol.d.ts +119 -0
  11. package/dist/types/src/backend/backend_protocol.d.ts.map +1 -0
  12. package/dist/types/src/backend/composed_backend_protocol.d.ts +90 -0
  13. package/dist/types/src/backend/composed_backend_protocol.d.ts.map +1 -0
  14. package/dist/types/src/backend/domlike_backend_protocol.d.ts +76 -0
  15. package/dist/types/src/backend/domlike_backend_protocol.d.ts.map +1 -0
  16. package/dist/types/src/backend/mode.d.ts +46 -0
  17. package/dist/types/src/backend/mode.d.ts.map +1 -0
  18. package/dist/types/src/backend/suggested_backend_protocol.d.ts +30 -0
  19. package/dist/types/src/backend/suggested_backend_protocol.d.ts.map +1 -0
  20. package/dist/types/src/behavior.d.ts +428 -0
  21. package/dist/types/src/behavior.d.ts.map +1 -0
  22. package/dist/types/src/class_list.d.ts +79 -0
  23. package/dist/types/src/class_list.d.ts.map +1 -0
  24. package/dist/types/src/component.d.ts +291 -0
  25. package/dist/types/src/component.d.ts.map +1 -0
  26. package/dist/types/src/component_params.d.ts +239 -0
  27. package/dist/types/src/component_params.d.ts.map +1 -0
  28. package/dist/types/src/component_space.d.ts +164 -0
  29. package/dist/types/src/component_space.d.ts.map +1 -0
  30. package/dist/types/src/data_path.d.ts +5 -0
  31. package/dist/types/src/data_path.d.ts.map +1 -0
  32. package/dist/types/src/data_proxy.d.ts +107 -0
  33. package/dist/types/src/data_proxy.d.ts.map +1 -0
  34. package/dist/types/src/data_utils.d.ts +3 -0
  35. package/dist/types/src/data_utils.d.ts.map +1 -0
  36. package/dist/types/src/element.d.ts +275 -0
  37. package/dist/types/src/element.d.ts.map +1 -0
  38. package/dist/types/src/element_iterator.d.ts +43 -0
  39. package/dist/types/src/element_iterator.d.ts.map +1 -0
  40. package/dist/types/src/event.d.ts +104 -0
  41. package/dist/types/src/event.d.ts.map +1 -0
  42. package/dist/types/src/external_shadow_tree.d.ts +20 -0
  43. package/dist/types/src/external_shadow_tree.d.ts.map +1 -0
  44. package/dist/types/src/func_arr.d.ts +39 -0
  45. package/dist/types/src/func_arr.d.ts.map +1 -0
  46. package/dist/types/src/global_options.d.ts +111 -0
  47. package/dist/types/src/global_options.d.ts.map +1 -0
  48. package/dist/types/src/index.d.ts +43 -0
  49. package/dist/types/src/index.d.ts.map +1 -0
  50. package/dist/types/src/mutation_observer.d.ts +79 -0
  51. package/dist/types/src/mutation_observer.d.ts.map +1 -0
  52. package/dist/types/src/native_node.d.ts +8 -0
  53. package/dist/types/src/native_node.d.ts.map +1 -0
  54. package/dist/types/src/node.d.ts +49 -0
  55. package/dist/types/src/node.d.ts.map +1 -0
  56. package/dist/types/src/relation.d.ts +47 -0
  57. package/dist/types/src/relation.d.ts.map +1 -0
  58. package/dist/types/src/render.d.ts +3 -0
  59. package/dist/types/src/render.d.ts.map +1 -0
  60. package/dist/types/src/selector.d.ts +32 -0
  61. package/dist/types/src/selector.d.ts.map +1 -0
  62. package/dist/types/src/shadow_root.d.ts +136 -0
  63. package/dist/types/src/shadow_root.d.ts.map +1 -0
  64. package/dist/types/src/template_engine.d.ts +18 -0
  65. package/dist/types/src/template_engine.d.ts.map +1 -0
  66. package/dist/types/src/text_node.d.ts +32 -0
  67. package/dist/types/src/text_node.d.ts.map +1 -0
  68. package/dist/types/src/tmpl/index.d.ts +18 -0
  69. package/dist/types/src/tmpl/index.d.ts.map +1 -0
  70. package/dist/types/src/tmpl/native_rendering.d.ts +45 -0
  71. package/dist/types/src/tmpl/native_rendering.d.ts.map +1 -0
  72. package/dist/types/src/tmpl/proc_gen_wrapper.d.ts +80 -0
  73. package/dist/types/src/tmpl/proc_gen_wrapper.d.ts.map +1 -0
  74. package/dist/types/src/tmpl/proc_gen_wrapper_dom.d.ts +50 -0
  75. package/dist/types/src/tmpl/proc_gen_wrapper_dom.d.ts.map +1 -0
  76. package/dist/types/src/tmpl/range_list_diff.d.ts +19 -0
  77. package/dist/types/src/tmpl/range_list_diff.d.ts.map +1 -0
  78. package/dist/types/src/trait_behaviors.d.ts +38 -0
  79. package/dist/types/src/trait_behaviors.d.ts.map +1 -0
  80. package/dist/types/src/virtual_node.d.ts +10 -0
  81. package/dist/types/src/virtual_node.d.ts.map +1 -0
  82. package/dist/types/tests/backend/domlike.test.d.ts +2 -0
  83. package/dist/types/tests/backend/domlike.test.d.ts.map +1 -0
  84. package/dist/types/tests/base/env.d.ts +29 -0
  85. package/dist/types/tests/base/env.d.ts.map +1 -0
  86. package/dist/types/tests/base/match.d.ts +9 -0
  87. package/dist/types/tests/base/match.d.ts.map +1 -0
  88. package/dist/types/tests/core/backend.test.d.ts +2 -0
  89. package/dist/types/tests/core/backend.test.d.ts.map +1 -0
  90. package/dist/types/tests/core/behavior.test.d.ts +2 -0
  91. package/dist/types/tests/core/behavior.test.d.ts.map +1 -0
  92. package/dist/types/tests/core/component_space.test.d.ts +2 -0
  93. package/dist/types/tests/core/component_space.test.d.ts.map +1 -0
  94. package/dist/types/tests/core/data_update.test.d.ts +2 -0
  95. package/dist/types/tests/core/data_update.test.d.ts.map +1 -0
  96. package/dist/types/tests/core/misc.test.d.ts +2 -0
  97. package/dist/types/tests/core/misc.test.d.ts.map +1 -0
  98. package/dist/types/tests/core/placeholder.test.d.ts +2 -0
  99. package/dist/types/tests/core/placeholder.test.d.ts.map +1 -0
  100. package/dist/types/tests/core/slot.test.d.ts +2 -0
  101. package/dist/types/tests/core/slot.test.d.ts.map +1 -0
  102. package/dist/types/tests/core/trait_behaviors.test.d.ts +2 -0
  103. package/dist/types/tests/core/trait_behaviors.test.d.ts.map +1 -0
  104. package/dist/types/tests/tmpl/binding_map.test.d.ts +2 -0
  105. package/dist/types/tests/tmpl/binding_map.test.d.ts.map +1 -0
  106. package/dist/types/tests/tmpl/event.test.d.ts +2 -0
  107. package/dist/types/tests/tmpl/event.test.d.ts.map +1 -0
  108. package/dist/types/tests/tmpl/expression.test.d.ts +2 -0
  109. package/dist/types/tests/tmpl/expression.test.d.ts.map +1 -0
  110. package/dist/types/tests/tmpl/lvalue.test.d.ts +2 -0
  111. package/dist/types/tests/tmpl/lvalue.test.d.ts.map +1 -0
  112. package/dist/types/tests/tmpl/native_rendering.test.d.ts +2 -0
  113. package/dist/types/tests/tmpl/native_rendering.test.d.ts.map +1 -0
  114. package/dist/types/tests/tmpl/structure.test.d.ts +2 -0
  115. package/dist/types/tests/tmpl/structure.test.d.ts.map +1 -0
  116. package/dist/types/tests/types/chaining.test.d.ts +2 -0
  117. package/dist/types/tests/types/chaining.test.d.ts.map +1 -0
  118. package/dist/types/tests/types/createElement.test.d.ts +2 -0
  119. package/dist/types/tests/types/createElement.test.d.ts.map +1 -0
  120. package/dist/types/tests/types/definition.test.d.ts +2 -0
  121. package/dist/types/tests/types/definition.test.d.ts.map +1 -0
  122. package/guide/zh_CN/advanced/binding_map_update.md +32 -0
  123. package/guide/zh_CN/advanced/build_args.md +28 -0
  124. package/guide/zh_CN/advanced/component_filter.md +70 -0
  125. package/guide/zh_CN/advanced/component_space.md +124 -0
  126. package/guide/zh_CN/advanced/custom_backend.md +53 -0
  127. package/guide/zh_CN/advanced/error_listener.md +32 -0
  128. package/guide/zh_CN/advanced/external_component.md +73 -0
  129. package/guide/zh_CN/advanced/template_engine.md +61 -0
  130. package/guide/zh_CN/appendix/backend_protocol.md +501 -0
  131. package/guide/zh_CN/appendix/list_diff_algorithm.md +406 -0
  132. package/guide/zh_CN/basic/beginning.md +94 -0
  133. package/guide/zh_CN/basic/component.md +156 -0
  134. package/guide/zh_CN/basic/event.md +169 -0
  135. package/guide/zh_CN/basic/lifetime.md +66 -0
  136. package/guide/zh_CN/basic/method.md +62 -0
  137. package/guide/zh_CN/basic/template.md +135 -0
  138. package/guide/zh_CN/data_management/advanced_update.md +170 -0
  139. package/guide/zh_CN/data_management/data_deep_copy.md +157 -0
  140. package/guide/zh_CN/data_management/data_observer.md +154 -0
  141. package/guide/zh_CN/data_management/property_early_init.md +31 -0
  142. package/guide/zh_CN/data_management/pure_data_pattern.md +21 -0
  143. package/guide/zh_CN/index.md +93 -0
  144. package/guide/zh_CN/interaction/behavior.md +52 -0
  145. package/guide/zh_CN/interaction/component_path.md +37 -0
  146. package/guide/zh_CN/interaction/generic.md +73 -0
  147. package/guide/zh_CN/interaction/placeholder.md +40 -0
  148. package/guide/zh_CN/interaction/relation.md +151 -0
  149. package/guide/zh_CN/interaction/slot.md +137 -0
  150. package/guide/zh_CN/interaction/template_import.md +94 -0
  151. package/guide/zh_CN/interaction/trait_behavior.md +117 -0
  152. package/guide/zh_CN/styling/external_class.md +46 -0
  153. package/guide/zh_CN/styling/style_isolation.md +54 -0
  154. package/guide/zh_CN/styling/virtual_host.md +52 -0
  155. package/guide/zh_CN/tree/element_iterator.md +54 -0
  156. package/guide/zh_CN/tree/mutation_observer.md +52 -0
  157. package/guide/zh_CN/tree/node_tree.md +142 -0
  158. package/guide/zh_CN/tree/node_tree_modification.md +78 -0
  159. package/guide/zh_CN/tree/selector.md +66 -0
  160. package/jest.config.js +6 -0
  161. package/jest.dts.config.js +9 -0
  162. package/jest.unit.config.js +14 -0
  163. package/package.json +28 -0
  164. package/src/backend/backend_protocol.ts +313 -0
  165. package/src/backend/composed_backend_protocol.ts +252 -0
  166. package/src/backend/domlike_backend_protocol.ts +370 -0
  167. package/src/backend/mode.ts +51 -0
  168. package/src/backend/suggested_backend_protocol.ts +83 -0
  169. package/src/behavior.ts +1655 -0
  170. package/src/bootstrap_dom_dev.js +22 -0
  171. package/src/class_list.ts +376 -0
  172. package/src/component.ts +1309 -0
  173. package/src/component_params.ts +461 -0
  174. package/src/component_space.ts +547 -0
  175. package/src/data_path.ts +225 -0
  176. package/src/data_proxy.ts +670 -0
  177. package/src/data_utils.ts +50 -0
  178. package/src/element.ts +1966 -0
  179. package/src/element_iterator.ts +158 -0
  180. package/src/event.ts +401 -0
  181. package/src/external_shadow_tree.ts +27 -0
  182. package/src/func_arr.ts +198 -0
  183. package/src/global_options.ts +242 -0
  184. package/src/index.ts +187 -0
  185. package/src/mutation_observer.ts +252 -0
  186. package/src/native_node.ts +74 -0
  187. package/src/node.ts +174 -0
  188. package/src/relation.ts +380 -0
  189. package/src/render.ts +25 -0
  190. package/src/selector.ts +218 -0
  191. package/src/shadow_root.ts +766 -0
  192. package/src/template_engine.ts +45 -0
  193. package/src/text_node.ts +149 -0
  194. package/src/tmpl/index.ts +199 -0
  195. package/src/tmpl/native_rendering.ts +175 -0
  196. package/src/tmpl/proc_gen_wrapper.ts +954 -0
  197. package/src/tmpl/proc_gen_wrapper_dom.ts +230 -0
  198. package/src/tmpl/range_list_diff.ts +443 -0
  199. package/src/trait_behaviors.ts +51 -0
  200. package/src/virtual_node.ts +51 -0
  201. package/tests/backend/domlike.test.ts +254 -0
  202. package/tests/base/env.ts +78 -0
  203. package/tests/base/match.ts +185 -0
  204. package/tests/core/backend.test.ts +144 -0
  205. package/tests/core/behavior.test.ts +546 -0
  206. package/tests/core/component_space.test.ts +212 -0
  207. package/tests/core/data_update.test.ts +461 -0
  208. package/tests/core/misc.test.ts +339 -0
  209. package/tests/core/placeholder.test.ts +180 -0
  210. package/tests/core/slot.test.ts +1495 -0
  211. package/tests/core/trait_behaviors.test.ts +153 -0
  212. package/tests/legacy/README.md +3 -0
  213. package/tests/legacy/behavior.test.js +293 -0
  214. package/tests/legacy/component.test.js +1247 -0
  215. package/tests/legacy/data_path.test.js +149 -0
  216. package/tests/legacy/data_proxy.test.js +759 -0
  217. package/tests/legacy/element_iterator.test.js +148 -0
  218. package/tests/legacy/event.test.js +849 -0
  219. package/tests/legacy/external.test.js +510 -0
  220. package/tests/legacy/extra_info.test.js +109 -0
  221. package/tests/legacy/generics.test.js +176 -0
  222. package/tests/legacy/mutation_observer.test.js +210 -0
  223. package/tests/legacy/relation.test.js +517 -0
  224. package/tests/legacy/selector.test.js +263 -0
  225. package/tests/legacy/slot.test.js +915 -0
  226. package/tests/legacy/virtual.test.js +394 -0
  227. package/tests/tmpl/binding_map.test.ts +208 -0
  228. package/tests/tmpl/event.test.ts +206 -0
  229. package/tests/tmpl/expression.test.ts +429 -0
  230. package/tests/tmpl/lvalue.test.ts +160 -0
  231. package/tests/tmpl/native_rendering.test.ts +155 -0
  232. package/tests/tmpl/structure.test.ts +998 -0
  233. package/tests/types/chaining.test.ts +614 -0
  234. package/tests/types/createElement.test.ts +82 -0
  235. package/tests/types/definition.test.ts +442 -0
  236. package/tsconfig.json +11 -0
  237. 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
+ }
@@ -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
+ }