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,547 @@
1
+ import {
2
+ ComponentParams,
3
+ DataList,
4
+ PropertyList,
5
+ MethodList,
6
+ ComponentInstance,
7
+ Empty,
8
+ } from './component_params'
9
+ import {
10
+ Behavior,
11
+ BehaviorBuilder,
12
+ GeneralBehavior,
13
+ } from './behavior'
14
+ import {
15
+ ComponentDefinition,
16
+ GeneralComponentDefinition,
17
+ Component,
18
+ GeneralComponent,
19
+ } from './component'
20
+ import {
21
+ ComponentOptions,
22
+ normalizeComponentOptions,
23
+ NormalizedComponentOptions,
24
+ } from './global_options'
25
+ import {
26
+ StyleScopeManager,
27
+ } from './class_list'
28
+ import {
29
+ GeneralBackendContext,
30
+ } from '.'
31
+ import { TraitBehavior } from './trait_behaviors'
32
+
33
+ const normalizePath = (path: string, basePath: string): string => {
34
+ let slices: string[]
35
+ if (path[0] !== '/') {
36
+ slices = basePath.split('/').slice(0, -1).concat(path.split('/'))
37
+ } else {
38
+ slices = path.split('/')
39
+ }
40
+ const finalSlices = [] as string[]
41
+ for (let i = 0; i < slices.length; i += 1) {
42
+ const slice = slices[i]!
43
+ if (slice === '' || slice === '.') continue
44
+ if (slice === '..') {
45
+ finalSlices.pop()
46
+ continue
47
+ }
48
+ finalSlices.push(slice)
49
+ }
50
+ return finalSlices.join('/')
51
+ }
52
+
53
+ export const normalizeUrl = (
54
+ path: string,
55
+ relPath: string,
56
+ ): { domain: string | null, absPath: string } => {
57
+ const protoSep = path.indexOf('://')
58
+ if (protoSep > 0) {
59
+ const domainSep = path.indexOf('/', protoSep + 3)
60
+ if (domainSep > 0) {
61
+ const domain = path.slice(0, domainSep)
62
+ const absPath = normalizePath(path.slice(domainSep + 1), '')
63
+ return {
64
+ domain,
65
+ absPath,
66
+ }
67
+ }
68
+ // HACK for invalid URL like `a://the-comp` , provide some compatibility
69
+ const domain = path.slice(0, protoSep + 3)
70
+ const absPath = normalizePath(path.slice(protoSep + 3), '')
71
+ return {
72
+ domain,
73
+ absPath,
74
+ }
75
+ }
76
+ return {
77
+ domain: null,
78
+ absPath: normalizePath(path, relPath),
79
+ }
80
+ }
81
+
82
+ export class ComponentWaitingList {
83
+ /** @internal */
84
+ private _$callbacks: ((c: GeneralComponentDefinition) => void)[] = []
85
+
86
+ add(callback: (c: GeneralComponentDefinition) => void) {
87
+ this._$callbacks.push(callback)
88
+ }
89
+
90
+ remove(callback: (c: GeneralComponentDefinition) => void) {
91
+ const index = this._$callbacks.indexOf(callback)
92
+ // must gurrantee order here (cannot swap-remove)
93
+ this._$callbacks.splice(index, 1)
94
+ }
95
+
96
+ call(c: GeneralComponentDefinition) {
97
+ const cbs = this._$callbacks
98
+ this._$callbacks = []
99
+ for (let i = 0; i < cbs.length; i += 1) {
100
+ const f = cbs[i]!
101
+ f(c)
102
+ }
103
+ }
104
+ }
105
+
106
+ /** A group of components for cross-component using */
107
+ export class ComponentSpace {
108
+ /** @internal */
109
+ private _$behaviorList = Object.create(null) as { [path: string]: GeneralBehavior }
110
+ /** @internal */
111
+ private _$pubBehaviorList = Object.create(null) as { [path: string]: GeneralBehavior }
112
+ /** @internal */
113
+ private _$list = Object.create(null) as { [path: string]: GeneralComponentDefinition }
114
+ /** @internal */
115
+ private _$pubList = Object.create(null) as { [path: string]: GeneralComponentDefinition }
116
+ /** @internal */
117
+ private _$importedSpaces = Object.create(null) as {
118
+ [path: string]: {
119
+ space: ComponentSpace,
120
+ privateUse: boolean,
121
+ }
122
+ }
123
+ /** @internal */
124
+ private _$defaultComponent: string
125
+ /** @internal */
126
+ private _$componentOptions: NormalizedComponentOptions
127
+ styleScopeManager: StyleScopeManager
128
+ /** @internal */
129
+ private _$listWaiting = Object.create(null) as {
130
+ [path: string]: ComponentWaitingList
131
+ }
132
+ /** @internal */
133
+ private _$pubListWaiting = Object.create(null) as {
134
+ [path: string]: ComponentWaitingList
135
+ }
136
+
137
+ /**
138
+ * Create a new component space
139
+ *
140
+ * The `defaultComponent` is the default component path.
141
+ * It should be defined soon after creation.
142
+ * A `baseSpace` can be provided as a "base" component space -
143
+ * every component alias (and behavior alias) in the space will be imported when creation.
144
+ * However, if any new component is added to the base space after the creation,
145
+ * it will not be added to the created space.
146
+ */
147
+ constructor(
148
+ defaultComponent?: string,
149
+ baseSpace?: ComponentSpace,
150
+ styleScopeManager?: StyleScopeManager,
151
+ ) {
152
+ if (baseSpace) {
153
+ Object.assign(this._$list, baseSpace._$pubList)
154
+ Object.assign(this._$behaviorList, baseSpace._$pubBehaviorList)
155
+ }
156
+ this._$defaultComponent = defaultComponent ?? ''
157
+ this._$componentOptions = normalizeComponentOptions({}, baseSpace?._$componentOptions)
158
+ this.styleScopeManager = styleScopeManager || new StyleScopeManager()
159
+ }
160
+
161
+ /**
162
+ * Update the default component options for this space
163
+ *
164
+ * The new options will be merged with existing options.
165
+ */
166
+ updateComponentOptions(componentOptions: ComponentOptions) {
167
+ this._$componentOptions = normalizeComponentOptions(componentOptions, this._$componentOptions)
168
+ }
169
+
170
+ getComponentOptions(): NormalizedComponentOptions {
171
+ return this._$componentOptions
172
+ }
173
+
174
+ /**
175
+ * Update the base component space
176
+ *
177
+ * This will add the components in `baseSpace` if there is no components with the same names.
178
+ */
179
+ updateBaseSpace(baseSpace: ComponentSpace) {
180
+ this._$list = Object.assign(
181
+ Object.create(null) as { [path: string]: GeneralComponentDefinition },
182
+ baseSpace._$pubList,
183
+ this._$list,
184
+ )
185
+ this._$behaviorList = Object.assign(
186
+ Object.create(null) as { [path: string]: GeneralBehavior },
187
+ baseSpace._$pubBehaviorList,
188
+ this._$behaviorList,
189
+ )
190
+ }
191
+
192
+ /**
193
+ * Import another component space
194
+ *
195
+ * The components in the imported space can be used by components in this space.
196
+ * The `protoDomain` should be URL-like, i.e. `space://another-space` .
197
+ * When using, the components in the imported space should be specified with `protoDomain` .
198
+ * For example, if `protoDomain` is `space://another-space` and one imported component has alias `my-comp` ,
199
+ * then it should be specified with `space://another-space/my-comp` .
200
+ * If `privateUse` set to false, only component alias in the imported space can be used;
201
+ * the original name of components is imported otherwise.
202
+ */
203
+ importSpace(
204
+ protoDomain: string,
205
+ space: ComponentSpace,
206
+ privateUse: boolean,
207
+ ) {
208
+ this._$importedSpaces[protoDomain] = {
209
+ space,
210
+ privateUse,
211
+ }
212
+ }
213
+
214
+ /**
215
+ * Get a component by the `path`
216
+ *
217
+ * The component `is` is actually treated as the "path" of the component.
218
+ * In other words, the component `is` field can be a string like `path/to/the/component` .
219
+ * Other components can be used by the component with "relative path" spacified.
220
+ * In this method, if the `path` is given as a relative path (not started with `/` ),
221
+ * it will be converted according to the `basePath` .
222
+ * If the `path` is given as a URL-like format,
223
+ * the component will be searched in imported comopnent spaces ( `importSpace()` for details).
224
+ */
225
+ getComponentByUrl(path: string, basePath: string): GeneralComponentDefinition {
226
+ const { domain, absPath } = normalizeUrl(path, basePath)
227
+ const comp = this.getComponent(absPath, true, domain)
228
+ if (!comp) {
229
+ throw new Error(`There is no component "${absPath}" in the space and no default component can be used`)
230
+ }
231
+ return comp
232
+ }
233
+
234
+ /**
235
+ * Get a component by the `path`
236
+ *
237
+ * Similar to `getComponentByUrl()` ,
238
+ * but returns `null` instead of the default component if no compnent was found.
239
+ */
240
+ getComponentByUrlWithoutDefault(
241
+ path: string,
242
+ relPath: string,
243
+ ): GeneralComponentDefinition | null {
244
+ const { domain, absPath } = normalizeUrl(path, relPath)
245
+ const comp = this.getComponent(absPath, false, domain)
246
+ return comp || null
247
+ }
248
+
249
+ private getComponent(
250
+ absPath: string,
251
+ withDefault = true,
252
+ domain: string | null = null,
253
+ ): GeneralComponentDefinition | undefined {
254
+ let list: { [is: string]: GeneralComponentDefinition } | undefined
255
+ if (domain) {
256
+ const target = this._$importedSpaces[domain]
257
+ if (target) {
258
+ const { space, privateUse } = target
259
+ if (privateUse) {
260
+ list = space._$list
261
+ } else {
262
+ list = space._$pubList
263
+ }
264
+ }
265
+ } else {
266
+ list = this._$list
267
+ }
268
+ if (list) {
269
+ const def = list[absPath]
270
+ if (def) return def
271
+ }
272
+ if (withDefault) {
273
+ return this._$list[this._$defaultComponent]
274
+ }
275
+ return undefined
276
+ }
277
+
278
+ getDefaultComponent(): GeneralComponentDefinition | null {
279
+ return this._$list[this._$defaultComponent] || null
280
+ }
281
+
282
+ isDefaultComponent(def: GeneralComponentDefinition) {
283
+ return this._$list[this._$defaultComponent] === def
284
+ }
285
+
286
+ /**
287
+ * Get a behavior by the `path`
288
+ *
289
+ * Similar to `getComponentByUrlWithoutDefault()` but for behaviors.
290
+ */
291
+ getBehaviorByUrl(path: string, relPath: string): GeneralBehavior | null {
292
+ const { domain, absPath } = normalizeUrl(path, relPath)
293
+ return this._$getBehavior(absPath, domain) || null
294
+ }
295
+
296
+ /** @internal */
297
+ _$getBehavior(
298
+ absPath: string,
299
+ domain: string | null = null,
300
+ ): GeneralBehavior | undefined {
301
+ let list: { [is: string]: GeneralBehavior } | undefined
302
+ if (domain) {
303
+ const target = this._$importedSpaces[domain]
304
+ if (target) {
305
+ const { space, privateUse } = target
306
+ if (privateUse) {
307
+ list = space._$behaviorList
308
+ } else {
309
+ list = space._$pubBehaviorList
310
+ }
311
+ }
312
+ } else {
313
+ list = this._$behaviorList
314
+ }
315
+ if (list) {
316
+ const def = list[absPath]
317
+ if (def) return def
318
+ }
319
+ return undefined
320
+ }
321
+
322
+ /** Register a component in this space */
323
+ defineComponent<
324
+ TData extends DataList,
325
+ TProperty extends PropertyList,
326
+ TMethod extends MethodList,
327
+ >(
328
+ def: ComponentParams<TData, TProperty, TMethod> &
329
+ ThisType<ComponentInstance<TData, TProperty, TMethod>>,
330
+ ): ComponentDefinition<TData, TProperty, TMethod> {
331
+ const is = def.is
332
+ const ret = new BehaviorBuilder(is, this).definition(def).registerComponent()
333
+ return ret
334
+ }
335
+
336
+ /** Register a behavior in this space */
337
+ defineBehavior<
338
+ TData extends DataList,
339
+ TProperty extends PropertyList,
340
+ TMethod extends MethodList,
341
+ >(
342
+ def: ComponentParams<TData, TProperty, TMethod> &
343
+ ThisType<ComponentInstance<TData, TProperty, TMethod>>,
344
+ ): Behavior<TData, TProperty, TMethod, never> {
345
+ const is = def.is
346
+ const ret = new BehaviorBuilder(is, this).definition(def).registerBehavior()
347
+ return ret
348
+ }
349
+
350
+ /** Register a component or a behavior with chaining API */
351
+ define(is?: string): BehaviorBuilder {
352
+ return new BehaviorBuilder(is, this)
353
+ }
354
+
355
+ /**
356
+ * Register a component or a behavior with chaining API (with method caller type specified)
357
+ *
358
+ * This API is generally designed for adapters which require special method callers.
359
+ */
360
+ defineWithMethodCaller(is?: string): BehaviorBuilder<
361
+ Empty,
362
+ Empty,
363
+ Empty,
364
+ Empty,
365
+ never,
366
+ never
367
+ > {
368
+ return new BehaviorBuilder(is, this)
369
+ }
370
+
371
+ /** @internal */
372
+ _$registerComponent(is: string, comp: GeneralComponentDefinition) {
373
+ this._$list[is] = comp
374
+ this._$behaviorList[is] = comp.behavior as unknown as GeneralBehavior
375
+ const arr = this._$listWaiting[is]
376
+ if (arr) {
377
+ delete this._$listWaiting[is]
378
+ arr.call(comp)
379
+ }
380
+ }
381
+
382
+ /** @internal */
383
+ _$registerBehavior(is: string, beh: GeneralBehavior) {
384
+ this._$behaviorList[is] = beh
385
+ }
386
+
387
+ /**
388
+ * Assign a public alias to a component
389
+ *
390
+ * The alias can be used in other component spaces which imported this component space.
391
+ * One component may have multiple aliases.
392
+ */
393
+ exportComponent(alias: string, is: string) {
394
+ const comp = this._$list[is]
395
+ if (!comp) {
396
+ throw new Error(`There is no component "${is}" for aliasing`)
397
+ }
398
+ this._$pubList[alias] = comp
399
+ const arr = this._$pubListWaiting[is]
400
+ if (arr) {
401
+ delete this._$pubListWaiting[is]
402
+ arr.call(comp)
403
+ }
404
+ }
405
+
406
+ /**
407
+ * Assign a public alias to a behavior
408
+ *
409
+ * The alias can be used in other component spaces which imported this component space.
410
+ * One behavior may have multiple aliases.
411
+ */
412
+ exportBehavior(alias: string, is: string) {
413
+ const beh = this._$behaviorList[is]
414
+ if (!beh) {
415
+ throw new Error(`There is no behavior "${is}" for aliasing`)
416
+ }
417
+ this._$pubBehaviorList[alias] = beh
418
+ }
419
+
420
+ /** @internal */
421
+ _$componentWaitingList(
422
+ path: string,
423
+ relPath: string,
424
+ ): ComponentWaitingList | null {
425
+ const { domain, absPath } = normalizeUrl(path, relPath)
426
+ let waiting: {
427
+ [path: string]: ComponentWaitingList
428
+ } | null
429
+ if (domain) {
430
+ const target = this._$importedSpaces[domain]
431
+ if (target) {
432
+ const { space, privateUse } = target
433
+ if (privateUse) {
434
+ if (space._$list[absPath]) {
435
+ return null
436
+ }
437
+ waiting = space._$listWaiting
438
+ } else {
439
+ if (space._$pubList[absPath]) {
440
+ return null
441
+ }
442
+ waiting = space._$pubListWaiting
443
+ }
444
+ } else {
445
+ return null
446
+ }
447
+ } else {
448
+ if (this._$list[absPath]) {
449
+ return null
450
+ }
451
+ waiting = this._$listWaiting
452
+ }
453
+ let wl = waiting[absPath]
454
+ if (wl) return wl
455
+ wl = waiting[absPath] = new ComponentWaitingList()
456
+ return wl
457
+ }
458
+
459
+ getWaitingComponents() {
460
+ return Object.keys(this._$listWaiting)
461
+ }
462
+
463
+ /**
464
+ * Create a component by URL
465
+ *
466
+ * This `url` can contain params (started with "?" character).
467
+ * The params will try to be set to component properties (if matches the property name).
468
+ */
469
+ createComponentByUrl(
470
+ tagName: string,
471
+ url: string,
472
+ genericTargets: { [name: string]: string } | null,
473
+ backendContext: GeneralBackendContext | null,
474
+ ): GeneralComponent {
475
+ let domainPath = url
476
+ let paramStr: string | null = null
477
+
478
+ // parse URL
479
+ const hashSepIndex = domainPath.indexOf('#')
480
+ if (hashSepIndex >= 0) {
481
+ domainPath = domainPath.slice(0, hashSepIndex)
482
+ }
483
+ const paramSepIndex = domainPath.indexOf('?')
484
+ if (paramSepIndex >= 0) {
485
+ paramStr = domainPath.slice(paramSepIndex + 1)
486
+ domainPath = domainPath.slice(0, paramSepIndex)
487
+ }
488
+
489
+ // find target components
490
+ const compDef = this.getComponentByUrl(domainPath, '')
491
+ let genericImpls: { [key: string]: GeneralComponentDefinition } | null = null
492
+ if (genericTargets) {
493
+ genericImpls = Object.create(null) as { [key: string]: GeneralComponentDefinition }
494
+ Object.keys(genericTargets).forEach((key) => {
495
+ const url = genericTargets[key]!
496
+ const compDef = this.getComponentByUrl(url, '')
497
+ genericImpls![key] = compDef
498
+ })
499
+ }
500
+
501
+ // create the component
502
+ const comp = Component.createWithGenericsAndContext(
503
+ tagName,
504
+ compDef,
505
+ genericImpls,
506
+ backendContext,
507
+ (comp) => {
508
+ // set params if provided
509
+ if (paramStr) {
510
+ let needApplyUpdates = false
511
+ paramStr.split('&').forEach((kv) => {
512
+ const kvSepIndex = kv.indexOf('=')
513
+ if (kvSepIndex >= 0) {
514
+ const key = decodeURIComponent(kv.slice(0, kvSepIndex))
515
+ const value = decodeURIComponent(kv.slice(kvSepIndex + 1))
516
+ if (comp._$dataGroup.replaceProperty(key, value)) {
517
+ needApplyUpdates = true
518
+ }
519
+ }
520
+ })
521
+ if (needApplyUpdates) comp.applyDataUpdates()
522
+ }
523
+ },
524
+ ) as GeneralComponent
525
+
526
+ return comp
527
+ }
528
+
529
+ /**
530
+ * Define a trait behavior
531
+ *
532
+ * A trait behavior
533
+ * Optionally, the trait behavior can add a conversion function.
534
+ * This function can convert the implementation to another interface.
535
+ */
536
+ defineTraitBehavior<TIn extends { [key: string]: any }>(): TraitBehavior<TIn, TIn>;
537
+ defineTraitBehavior<
538
+ TIn extends { [key: string]: any },
539
+ TOut extends { [key: string]: any },
540
+ >(trans: (impl: TIn) => TOut): TraitBehavior<TIn, TOut>;
541
+ defineTraitBehavior<
542
+ TIn extends { [key: string]: any },
543
+ TOut extends { [key: string]: any },
544
+ >(trans?: (impl: TIn) => TOut): TraitBehavior<TIn, TOut> {
545
+ return new TraitBehavior<TIn, TOut>(this, trans)
546
+ }
547
+ }