@tarojs/plugin-platform-harmony-ets 4.0.0-alpha.2 → 4.0.0-alpha.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/apis/base/system.ts +73 -20
- package/dist/apis/canvas/index.ts +10 -1
- package/dist/apis/device/clipboard.ts +16 -8
- package/dist/apis/framework/index.ts +1 -5
- package/dist/apis/index.ts +25 -17
- package/dist/apis/media/image/index.ts +1 -1
- package/dist/apis/storage/index.ts +146 -78
- package/dist/apis/ui/animation/animation.ts +71 -29
- package/dist/apis/ui/background.ts +2 -1
- package/dist/apis/ui/interaction/index.ts +42 -59
- package/dist/apis/ui/navigation-bar/index.ts +1 -1
- package/dist/apis/ui/pull-down-refresh.ts +9 -3
- package/dist/apis/ui/scroll/index.ts +5 -5
- package/dist/apis/ui/tab-bar.ts +3 -3
- package/dist/apis/utils/index.ts +2 -1
- package/dist/apis/wxml/IntersectionObserver.ts +18 -10
- package/dist/apis/wxml/selectorQuery.ts +26 -13
- package/dist/components-harmony-ets/button.ets +64 -34
- package/dist/components-harmony-ets/canvas.ets +51 -0
- package/dist/components-harmony-ets/checkbox.ets +72 -61
- package/dist/components-harmony-ets/form.ets +51 -29
- package/dist/components-harmony-ets/icon.ets +31 -19
- package/dist/components-harmony-ets/image.ets +34 -14
- package/dist/components-harmony-ets/index.ets +92 -0
- package/dist/components-harmony-ets/innerHtml.ets +11 -6
- package/dist/components-harmony-ets/input.ets +49 -41
- package/dist/components-harmony-ets/label.ets +71 -44
- package/dist/components-harmony-ets/listView.ets +26 -0
- package/dist/components-harmony-ets/movableArea.ets +126 -0
- package/dist/components-harmony-ets/movableView.ets +93 -0
- package/dist/components-harmony-ets/navigationBar.ets +65 -0
- package/dist/components-harmony-ets/pageMeta.ets +94 -0
- package/dist/components-harmony-ets/picker.ets +42 -38
- package/dist/components-harmony-ets/progress.ets +52 -0
- package/dist/components-harmony-ets/pseudo.ets +80 -0
- package/dist/components-harmony-ets/radio.ets +74 -64
- package/dist/components-harmony-ets/richText.ets +14 -30
- package/dist/components-harmony-ets/scrollList.ets +94 -0
- package/dist/components-harmony-ets/scrollView.ets +61 -57
- package/dist/components-harmony-ets/slider.ets +18 -14
- package/dist/components-harmony-ets/stickySection.ets +42 -0
- package/dist/components-harmony-ets/style.ets +381 -130
- package/dist/components-harmony-ets/swiper.ets +61 -20
- package/dist/components-harmony-ets/switch.ets +36 -32
- package/dist/components-harmony-ets/{index.ts → tag.ts} +6 -0
- package/dist/components-harmony-ets/text.ets +135 -49
- package/dist/components-harmony-ets/textArea.ets +50 -35
- package/dist/components-harmony-ets/utils/AttributeManager.ets +1 -1
- package/dist/components-harmony-ets/utils/DynamicCenter.ts +2 -2
- package/dist/components-harmony-ets/utils/flexManager.ets +49 -19
- package/dist/components-harmony-ets/utils/helper.ets +18 -5
- package/dist/components-harmony-ets/utils/htmlParser/HarmonyHTMLParser.ts +1 -2
- package/dist/components-harmony-ets/utils/htmlParser/index.ts +1 -1
- package/dist/components-harmony-ets/utils/index.ts +54 -50
- package/dist/components-harmony-ets/utils/styles.ets +170 -93
- package/dist/components-harmony-ets/video.ets +34 -21
- package/dist/components-harmony-ets/view.ets +63 -52
- package/dist/components-harmony-ets/webView.ets +40 -34
- package/dist/index.d.ts +152 -0
- package/dist/index.js +99 -55
- package/dist/index.js.map +1 -1
- package/dist/runtime-ets/bom/document.ts +6 -4
- package/dist/runtime-ets/bom/getComputedStyle.ts +2 -2
- package/dist/runtime-ets/bom/window.ts +7 -0
- package/dist/runtime-ets/current.ts +3 -0
- package/dist/runtime-ets/dom/bind.ts +28 -12
- package/dist/runtime-ets/dom/class-list.ts +2 -2
- package/dist/runtime-ets/dom/cssNesting.ts +419 -0
- package/dist/runtime-ets/dom/cssStyleDeclaration.ts +28 -42
- package/dist/runtime-ets/dom/document.ts +8 -11
- package/dist/runtime-ets/dom/element/canvas.ts +136 -0
- package/dist/runtime-ets/dom/element/element.ts +348 -57
- package/dist/runtime-ets/dom/element/form.ts +31 -26
- package/dist/runtime-ets/dom/element/index.ts +30 -2
- package/dist/runtime-ets/dom/element/movableArea.ts +11 -0
- package/dist/runtime-ets/dom/element/movableView.ts +244 -0
- package/dist/runtime-ets/dom/element/normal.ts +35 -8
- package/dist/runtime-ets/dom/element/progress.ts +11 -0
- package/dist/runtime-ets/dom/element/scrollView.ts +1 -0
- package/dist/runtime-ets/dom/element/text.ts +1 -8
- package/dist/runtime-ets/dom/element/video.ts +5 -4
- package/dist/runtime-ets/dom/element/webView.ts +12 -5
- package/dist/runtime-ets/dom/event.ts +2 -4
- package/dist/runtime-ets/dom/eventTarget.ts +2 -3
- package/dist/runtime-ets/dom/node.ts +54 -29
- package/dist/runtime-ets/dom/stylesheet/covertWeb2Hm.ts +416 -235
- package/dist/runtime-ets/dom/stylesheet/index.ts +29 -311
- package/dist/runtime-ets/dom/stylesheet/type.ts +51 -9
- package/dist/runtime-ets/dom/stylesheet/util.ts +33 -27
- package/dist/runtime-ets/index.ts +2 -1
- package/dist/runtime-ets/interface/event.ts +1 -1
- package/dist/runtime-ets/utils/index.ts +73 -13
- package/dist/runtime-ets/utils/info.ts +2 -2
- package/dist/runtime-framework/react/app.ts +9 -4
- package/dist/runtime-framework/react/hooks.ts +0 -1
- package/dist/runtime-framework/react/index.ts +0 -2
- package/dist/runtime-framework/react/native-page.ts +154 -77
- package/dist/runtime-framework/react/page.ts +3 -8
- package/dist/runtime-framework/solid/app.ts +25 -45
- package/dist/runtime-framework/solid/connect.ts +21 -3
- package/dist/runtime-framework/solid/hooks.ts +16 -11
- package/dist/runtime-framework/solid/index.ts +6 -2
- package/dist/runtime-framework/solid/page.ts +84 -30
- package/dist/runtime-framework/solid/reconciler/props.ts +70 -25
- package/dist/runtime-framework/solid/reconciler/render.ts +16 -6
- package/dist/runtime-framework/solid/reconciler/use.ts +0 -1
- package/dist/runtime-framework/solid/utils/index.ts +0 -2
- package/dist/runtime-utils.d.ts +827 -0
- package/dist/runtime-utils.js +435 -218
- package/dist/runtime-utils.js.map +1 -1
- package/dist/runtime.d.ts +1 -0
- package/dist/runtime.js +435 -218
- package/dist/runtime.js.map +1 -1
- package/index.js +3 -1
- package/package.json +14 -15
- package/static/media/cancel.svg +1 -1
- package/static/media/circle.svg +1 -1
- package/static/media/clear.svg +1 -1
- package/static/media/download.svg +1 -1
- package/static/media/info.svg +1 -1
- package/static/media/info_circle.svg +1 -1
- package/static/media/search.svg +1 -1
- package/static/media/success.svg +1 -1
- package/static/media/success_no_circle.svg +1 -1
- package/static/media/warn.svg +1 -1
- package/types/harmony.d.ts +4 -0
- package/types/index.d.ts +4 -0
- package/types/runtime.d.ts +1 -1
- /package/dist/runtime-framework/solid/{contant.ts → constant.ts} +0 -0
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
import { parseClasses } from '../utils'
|
|
2
|
+
|
|
3
|
+
import type { CSSProperties, ReactElement } from 'react'
|
|
4
|
+
// 抽出来的嵌套查询
|
|
5
|
+
// const __nesting_style__ = [
|
|
6
|
+
// {
|
|
7
|
+
// selectors: ['container', '>', 'hello', ' ', 'txt'],
|
|
8
|
+
// declaration: {
|
|
9
|
+
// _color: "#00F00F",
|
|
10
|
+
// _fontSize: convertNumber2VP(40),
|
|
11
|
+
// }
|
|
12
|
+
// },
|
|
13
|
+
// ]
|
|
14
|
+
//
|
|
15
|
+
// function Index() {
|
|
16
|
+
// return __combine_nesting_style__(jsx(TaroViewTagName, {
|
|
17
|
+
// className: "container aaa",
|
|
18
|
+
// style: calcDynamicStyle(__inner_style__(), "container", null),
|
|
19
|
+
// children: [
|
|
20
|
+
// jsx(TaroTextTagName, {
|
|
21
|
+
// className: "txt cc",
|
|
22
|
+
// style: calcDynamicStyle(__inner_style__(), "txt", null),
|
|
23
|
+
// children: "Hello!"
|
|
24
|
+
// }),
|
|
25
|
+
// jsx(TaroViewTagName, {
|
|
26
|
+
// className: "hello",
|
|
27
|
+
// style: calcDynamicStyle(__inner_style__(), "hello", null),
|
|
28
|
+
// children: [
|
|
29
|
+
// jsx(TaroTextTagName, {
|
|
30
|
+
// className: "txt",
|
|
31
|
+
// style: calcDynamicStyle(__inner_style__(), "txt", null),
|
|
32
|
+
// children: "wo2rld!"
|
|
33
|
+
// }),
|
|
34
|
+
// jsx(TaroTextTagName, {
|
|
35
|
+
// className: "txt2",
|
|
36
|
+
// style: calcDynamicStyle(__inner_style__(), "txt2", null),
|
|
37
|
+
// children: "Hello wo2rld!"
|
|
38
|
+
// })
|
|
39
|
+
// ]
|
|
40
|
+
// })
|
|
41
|
+
// ]
|
|
42
|
+
// }), __nesting_style__);
|
|
43
|
+
// }
|
|
44
|
+
|
|
45
|
+
type TMappingNode = {
|
|
46
|
+
node: ReactElement
|
|
47
|
+
children: TMapping
|
|
48
|
+
descendants: TMapping
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
type TMapping = Record<string, TMappingNode>
|
|
52
|
+
|
|
53
|
+
type TSelectorNode = {
|
|
54
|
+
mapping: TMapping
|
|
55
|
+
node: ReactElement
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export type NestingStyle = {
|
|
59
|
+
node: ReactElement
|
|
60
|
+
selectors: string[]
|
|
61
|
+
declaration: Record<string, any>
|
|
62
|
+
}[]
|
|
63
|
+
|
|
64
|
+
// 构建映射表
|
|
65
|
+
function depthTraversal(root: ReactElement) {
|
|
66
|
+
const class_mapping: TMapping = {}
|
|
67
|
+
// 记录别名,防止冲突
|
|
68
|
+
const selector_alias: Record<string, string[]> = {}
|
|
69
|
+
// 统计重名次数:{ txt: 1, cc: 2 }
|
|
70
|
+
const selector_alias_count: Record<string, number> = {}
|
|
71
|
+
|
|
72
|
+
const traverse = (tree) => {
|
|
73
|
+
const result: Record<string, TMapping> = {}
|
|
74
|
+
if (tree && tree.props) {
|
|
75
|
+
// 兜底适配:如果Taro组件被原封不动的再别的地方导出使用,导致无法在编译环境添加__hmStyle
|
|
76
|
+
// import { View } from '../../../~/components'
|
|
77
|
+
// hack:如果是taro节点,但是被赋予了__styleSheet,则走一下__styleSheet转__hmStyle
|
|
78
|
+
if (tree.props.__styleSheet && typeof tree.type !== 'function') {
|
|
79
|
+
tree.props.__hmStyle = Object.assign({}, tree.props.__hmStyle, tree.props.__styleSheet.value)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// 后代选择器
|
|
83
|
+
const descendant_map = {
|
|
84
|
+
node: tree,
|
|
85
|
+
children: {},
|
|
86
|
+
descendants: {}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (tree.props.children) {
|
|
90
|
+
// 遍历叶子节点
|
|
91
|
+
if (tree.props.children instanceof Array) {
|
|
92
|
+
for (let i = 0; i < tree.props.children.length; i++) {
|
|
93
|
+
// 收集叶子节点所拥有的类名
|
|
94
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
95
|
+
processLeaf(tree.props.children[i], descendant_map)
|
|
96
|
+
}
|
|
97
|
+
} else if (typeof tree.props.children !== 'string') {
|
|
98
|
+
// 收集叶子节点所拥有的类名
|
|
99
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
100
|
+
processLeaf(tree.props.children, descendant_map)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// 拆分classnames
|
|
104
|
+
const classnames = parseClasses(tree.props.className || '')
|
|
105
|
+
for (let i = 0; i < classnames.length; i++) {
|
|
106
|
+
const cls = classnames[i]
|
|
107
|
+
let name = cls
|
|
108
|
+
if (selector_alias_count[name]) {
|
|
109
|
+
// 存在重名,需要使用别名替代
|
|
110
|
+
const oldName = name
|
|
111
|
+
name = `___${name}${selector_alias_count[oldName]}`
|
|
112
|
+
selector_alias_count[oldName] = selector_alias_count[oldName] + 1
|
|
113
|
+
selector_alias[oldName] ? selector_alias[oldName].push(name) : (selector_alias[oldName] = [name])
|
|
114
|
+
}
|
|
115
|
+
selector_alias_count[name] = 1
|
|
116
|
+
|
|
117
|
+
class_mapping[name] = descendant_map
|
|
118
|
+
result[name] = {
|
|
119
|
+
ref: descendant_map,
|
|
120
|
+
node: tree
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return result
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const processLeaf = (leaf, descendant_map: TMappingNode) => {
|
|
128
|
+
if (!leaf) return
|
|
129
|
+
|
|
130
|
+
const queue = [leaf]
|
|
131
|
+
|
|
132
|
+
while (queue.length > 0) {
|
|
133
|
+
const current = queue.shift()
|
|
134
|
+
|
|
135
|
+
if (current instanceof Array) {
|
|
136
|
+
for (let i = 0; i < current.length; i++) {
|
|
137
|
+
queue.push(current[i])
|
|
138
|
+
}
|
|
139
|
+
continue
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const leaf_map = traverse(current)
|
|
143
|
+
if (!leaf_map) continue
|
|
144
|
+
|
|
145
|
+
// 直接后代
|
|
146
|
+
Object.assign(descendant_map.children, leaf_map)
|
|
147
|
+
|
|
148
|
+
// 子孙后代
|
|
149
|
+
const grandchild: (Record<string, TMapping> | TMapping)[] = [leaf_map]
|
|
150
|
+
Object.keys(leaf_map).forEach(key => {
|
|
151
|
+
const leaf_child_map = class_mapping[key]
|
|
152
|
+
if (leaf_child_map?.descendants) {
|
|
153
|
+
grandchild.push(leaf_child_map.descendants)
|
|
154
|
+
}
|
|
155
|
+
})
|
|
156
|
+
Object.assign(descendant_map.descendants, ...grandchild)
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
traverse(root)
|
|
161
|
+
return {
|
|
162
|
+
mapping: class_mapping,
|
|
163
|
+
alias: selector_alias
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// 将嵌套样式与节点合并
|
|
168
|
+
function combineStyle(nestingStyle: NestingStyle, class_mapping: TMapping, alias: Record<string, string[]>) {
|
|
169
|
+
const findElement = (selector_string, combinator_type, selector_mapping, remainder_selector, declaration) => {
|
|
170
|
+
// 防止修改原数组
|
|
171
|
+
if (selector_string instanceof Array) {
|
|
172
|
+
selector_string = selector_string.slice()
|
|
173
|
+
}
|
|
174
|
+
let selector_list = [selector_string]
|
|
175
|
+
const selector_nodes: TSelectorNode[] = []
|
|
176
|
+
let shouldUseCombinations = false
|
|
177
|
+
// 判断是否存在别名
|
|
178
|
+
if (selector_string instanceof Array) {
|
|
179
|
+
// 多类选择器类名,需要进行排列组合选择了,一对多的查找 ['a', 'b'],需要找出所有a和b都指向同一个node的节点
|
|
180
|
+
selector_string.forEach((item, i) => {
|
|
181
|
+
if (alias[item]) {
|
|
182
|
+
selector_string[i] = [item, ...alias[item]]
|
|
183
|
+
}
|
|
184
|
+
})
|
|
185
|
+
shouldUseCombinations = true
|
|
186
|
+
} else if (alias[selector_string]) {
|
|
187
|
+
selector_list = selector_list.concat(alias[selector_string])
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
for (let i = 0; i < selector_list.length; i++) {
|
|
191
|
+
const selector = selector_list[i]
|
|
192
|
+
if (selector instanceof Array) {
|
|
193
|
+
let hitElements: any
|
|
194
|
+
// 如果是数组,说明他是一个多类选择器:.a.b,我们需要搜索这两个类名都指向同一个node
|
|
195
|
+
if (shouldUseCombinations) {
|
|
196
|
+
hitElements = generateCombinations(selector, (combination) => {
|
|
197
|
+
// combination 是组合后的选择器['parent', 'child']
|
|
198
|
+
const _obj = findSendNode(combination, selector_mapping)
|
|
199
|
+
if (_obj) return _obj
|
|
200
|
+
})
|
|
201
|
+
} else {
|
|
202
|
+
hitElements = findSendNode(selector, selector_mapping)
|
|
203
|
+
}
|
|
204
|
+
// 找出最后搜寻出来的node
|
|
205
|
+
if (hitElements) {
|
|
206
|
+
let objs = [hitElements]
|
|
207
|
+
objs = flattenArray(objs)
|
|
208
|
+
objs.forEach(obj => {
|
|
209
|
+
if (typeof obj.node.type === 'function') {
|
|
210
|
+
// 自定义组件,往下传递需要搜寻的内容向里面搜寻
|
|
211
|
+
const nestingData = {
|
|
212
|
+
selectors: [selector_string, combinator_type, ...remainder_selector.slice()],
|
|
213
|
+
declaration: declaration
|
|
214
|
+
}
|
|
215
|
+
obj.node.props.__nesting = obj.node.props.__nesting
|
|
216
|
+
? [...obj.node.props.__nesting, nestingData] : [nestingData]
|
|
217
|
+
}
|
|
218
|
+
selector_nodes.push({
|
|
219
|
+
// @ts-ignore
|
|
220
|
+
mapping: (obj.ref || obj)[combinator_type === ' > ' ? 'children' : 'descendants'],
|
|
221
|
+
node: obj.node
|
|
222
|
+
})
|
|
223
|
+
})
|
|
224
|
+
}
|
|
225
|
+
} else {
|
|
226
|
+
// 查询选择器的节点
|
|
227
|
+
const object = selector_mapping[selector]
|
|
228
|
+
if (object) {
|
|
229
|
+
if (typeof object.node.type === 'function') {
|
|
230
|
+
// 自定义组件,往下传递需要搜寻的内容向里面搜寻
|
|
231
|
+
const nestingData = {
|
|
232
|
+
selectors: [selector_string, combinator_type, ...remainder_selector.slice()],
|
|
233
|
+
declaration: declaration
|
|
234
|
+
}
|
|
235
|
+
object.node.props.__nesting = object.node.props.__nesting
|
|
236
|
+
? [...object.node.props.__nesting, nestingData] : [nestingData]
|
|
237
|
+
}
|
|
238
|
+
selector_nodes.push({
|
|
239
|
+
mapping: (object.ref || object)[combinator_type === ' > ' ? 'children' : 'descendants'],
|
|
240
|
+
node: object.node
|
|
241
|
+
})
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return selector_nodes
|
|
246
|
+
}
|
|
247
|
+
const findSelector = (selectors: string[], current_mapping: any, declaration: any): TSelectorNode[] => {
|
|
248
|
+
const workQueue: { selectors: string[], current_mapping: any }[] = [{ selectors, current_mapping }]
|
|
249
|
+
let resultElements: TSelectorNode[] = []
|
|
250
|
+
while (workQueue.length > 0) {
|
|
251
|
+
const { selectors: currentSelectors, current_mapping: currentMapping } = workQueue.shift()!
|
|
252
|
+
const new_selectors = currentSelectors.slice()
|
|
253
|
+
const selector_string = new_selectors.shift()
|
|
254
|
+
const combinator_type = new_selectors.shift()
|
|
255
|
+
|
|
256
|
+
const _elements = findElement(selector_string, combinator_type, currentMapping, new_selectors, declaration)
|
|
257
|
+
|
|
258
|
+
if (_elements.length) {
|
|
259
|
+
if (new_selectors.length) {
|
|
260
|
+
_elements.forEach(element => {
|
|
261
|
+
workQueue.push({ selectors: new_selectors.slice(), current_mapping: element.mapping })
|
|
262
|
+
})
|
|
263
|
+
} else {
|
|
264
|
+
resultElements = resultElements.concat(_elements)
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return resultElements
|
|
270
|
+
}
|
|
271
|
+
if (nestingStyle && nestingStyle instanceof Array) {
|
|
272
|
+
// 合并样式
|
|
273
|
+
nestingStyle.forEach(({ selectors, declaration }) => {
|
|
274
|
+
// 获取选中的节点列表
|
|
275
|
+
const selectors_elements = findSelector(selectors, class_mapping, declaration)
|
|
276
|
+
for (let i = 0; i < selectors_elements.length; i++) {
|
|
277
|
+
const ele = selectors_elements[i].node
|
|
278
|
+
if (ele && typeof ele !== 'function') {
|
|
279
|
+
// 直接注入到__hmStyle
|
|
280
|
+
// Hack: ReactElement会在dev模式下被冻结,所以在dev模式下,我们会将Object.freeze覆盖使其失效
|
|
281
|
+
if (ele.props.__hmStyle) {
|
|
282
|
+
ele.props.__hmStyle = Object.assign({}, ele.props.__hmStyle, declaration)
|
|
283
|
+
} else {
|
|
284
|
+
ele.props.__hmStyle = declaration
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
})
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// 排列组合选择器,找出符合的组合
|
|
293
|
+
// let arrayA = [1, 2, 3];
|
|
294
|
+
// let arrayB = [4, 5, 6];
|
|
295
|
+
// let arrayC = 'abc'
|
|
296
|
+
// let result = generateCombinations([arrayA, arrayB, arrayC], (combination) => { if (combination[0] == 3 ) { return combination }})
|
|
297
|
+
// console.log(result) => [3, 4, "abc"]
|
|
298
|
+
function generateCombinations (arrays: (string[] | string)[], cbFn, currentCombination: (string[] | string)[] = []) {
|
|
299
|
+
if (arrays.length === 0) {
|
|
300
|
+
// 当所有数组都被处理完时,将当前组合添加到结果中
|
|
301
|
+
return cbFn(currentCombination.slice())
|
|
302
|
+
}
|
|
303
|
+
// 取出当前数组
|
|
304
|
+
const currentArray = arrays[0]
|
|
305
|
+
if (currentArray instanceof Array) {
|
|
306
|
+
// 遍历当前数组的每个元素
|
|
307
|
+
const eles: TMappingNode[] = []
|
|
308
|
+
for (let i = 0; i < currentArray.length; i++) {
|
|
309
|
+
// 将当前元素添加到当前组合中
|
|
310
|
+
currentCombination.push(currentArray[i])
|
|
311
|
+
// 递归处理剩余的数组
|
|
312
|
+
const shouldStop = generateCombinations(arrays.slice(1), cbFn, currentCombination)
|
|
313
|
+
if (shouldStop) {
|
|
314
|
+
eles.push(shouldStop)
|
|
315
|
+
}
|
|
316
|
+
// 回溯,移除最后一个元素,尝试其他组合
|
|
317
|
+
currentCombination.pop()
|
|
318
|
+
}
|
|
319
|
+
return eles
|
|
320
|
+
} else {
|
|
321
|
+
// 如果不是数组,直接将当前元素添加到当前组合中
|
|
322
|
+
currentCombination.push(currentArray)
|
|
323
|
+
// 递归处理剩余的数组
|
|
324
|
+
const shouldStop = generateCombinations(arrays.slice(1), cbFn, currentCombination)
|
|
325
|
+
if (shouldStop) {
|
|
326
|
+
return shouldStop
|
|
327
|
+
}
|
|
328
|
+
// 回溯,移除最后一个元素,尝试其他组合
|
|
329
|
+
currentCombination.pop()
|
|
330
|
+
}
|
|
331
|
+
return false
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// 多类选择器辅助函数:.a.b => 这里的.a .b其实都是指向同一个node
|
|
335
|
+
// 匹配寻找所有选择器都指向同一个node
|
|
336
|
+
function findSendNode (selectorArr: string[], selector_mapping: TMapping) {
|
|
337
|
+
let obj: any = null
|
|
338
|
+
for (let i = 0; i < selectorArr.length; i++) {
|
|
339
|
+
// 查询选择器的节点
|
|
340
|
+
const object = selector_mapping[selectorArr[i]]
|
|
341
|
+
if (object) {
|
|
342
|
+
if (!obj) { obj = object }
|
|
343
|
+
if (object.node === obj.node) continue
|
|
344
|
+
}
|
|
345
|
+
obj = null
|
|
346
|
+
break
|
|
347
|
+
}
|
|
348
|
+
return obj
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function insertParentStyle(data: {key: string, value: CSSProperties}, class_mapping: TMapping, alias: Record<string, string[]>) {
|
|
352
|
+
const { key, value } = data
|
|
353
|
+
key.split(' ').forEach(key => {
|
|
354
|
+
let classnames = [key]
|
|
355
|
+
if (alias[key]) {
|
|
356
|
+
classnames = classnames.concat(alias[key])
|
|
357
|
+
}
|
|
358
|
+
classnames.forEach(name => {
|
|
359
|
+
if (class_mapping[name]) {
|
|
360
|
+
// 插入样式
|
|
361
|
+
const ele = class_mapping[key].node
|
|
362
|
+
if (ele) {
|
|
363
|
+
// 直接注入到__hmStyle
|
|
364
|
+
// Hack: ReactElement会在dev模式下被冻结,所以在dev模式下,我们会将Object.freeze覆盖使其失效
|
|
365
|
+
if (ele.props.__hmStyle) {
|
|
366
|
+
ele.props.__hmStyle = Object.assign({}, ele.props.__hmStyle, value)
|
|
367
|
+
} else {
|
|
368
|
+
ele.props.__hmStyle = value
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
})
|
|
373
|
+
})
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// 合并嵌套样式
|
|
377
|
+
// 1、构建映射表,生成一份扁平的样式表结构
|
|
378
|
+
// 2、遍历嵌套样式,根据选择器查找节点,合并样式
|
|
379
|
+
export function __combine_nesting_style__(react_tree: ReactElement, styles: NestingStyle | null = null) {
|
|
380
|
+
if (react_tree) {
|
|
381
|
+
let newStyle = styles
|
|
382
|
+
const parentProps: {
|
|
383
|
+
__styleSheet?: {key: string, value: CSSProperties}
|
|
384
|
+
__nesting?: NestingStyle
|
|
385
|
+
} = // @ts-ignore
|
|
386
|
+
react_tree._owner?.pendingProps // Hack:取出父组件的props,考虑版本问题,取的内部属性,可能会有问题
|
|
387
|
+
|
|
388
|
+
if (newStyle || (parentProps && (parentProps.__styleSheet || parentProps.__nesting))) {
|
|
389
|
+
// 1、循环一遍,构建出一颗JSX映射表
|
|
390
|
+
const { mapping, alias } = depthTraversal(react_tree)
|
|
391
|
+
if (parentProps) {
|
|
392
|
+
// 2、如果自定义节点,则增加合成__stylesheet步骤,将父节点的样式合并到当前节点
|
|
393
|
+
if (parentProps.__styleSheet) {
|
|
394
|
+
insertParentStyle(parentProps.__styleSheet, mapping, alias)
|
|
395
|
+
// @ts-ignore
|
|
396
|
+
parentProps.__styleSheet = null // 释放内存
|
|
397
|
+
}
|
|
398
|
+
// 3、如果自定节点,存在需要往下查询的嵌套样式,需要合并到子组件
|
|
399
|
+
if (parentProps.__nesting) {
|
|
400
|
+
newStyle = (newStyle || []).concat(parentProps.__nesting)
|
|
401
|
+
// @ts-ignore
|
|
402
|
+
parentProps.__nesting = null // 释放内存
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
// 4、合并嵌套样式样式
|
|
406
|
+
if (newStyle && newStyle.length) {
|
|
407
|
+
combineStyle(newStyle, mapping, alias)
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
return react_tree
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// 拍平数组
|
|
415
|
+
function flattenArray(arr) {
|
|
416
|
+
return arr.reduce((acc, val) => {
|
|
417
|
+
return acc.concat(Array.isArray(val) ? flattenArray(val) : val)
|
|
418
|
+
}, [])
|
|
419
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { isObject, toCamelCase, toDashed } from '@tarojs/shared'
|
|
1
|
+
import { isObject, isUndefined, toCamelCase, toDashed } from '@tarojs/shared'
|
|
2
2
|
|
|
3
3
|
import { TaroElement } from './element/element'
|
|
4
|
-
import convertWebStyle2HmStyle
|
|
4
|
+
import convertWebStyle2HmStyle from './stylesheet/covertWeb2Hm'
|
|
5
5
|
|
|
6
6
|
class CSSStyleDeclaration {
|
|
7
7
|
// eslint-disable-next-line no-useless-constructor
|
|
@@ -23,9 +23,11 @@ class CSSStyleDeclaration {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
public set cssText (value: string) {
|
|
26
|
+
// 复制,防止被篡改到attr上的原始内容
|
|
27
|
+
this._st.hmStyle = Object.assign({}, this.el._attrs?.__hmStyle) || {}
|
|
26
28
|
if (value === '' || value === undefined || value === null) {
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
+
// 清空style,只保留class的样式
|
|
30
|
+
return
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
const rules = value.split(';')
|
|
@@ -40,7 +42,7 @@ class CSSStyleDeclaration {
|
|
|
40
42
|
const [propName, ...valList] = rule.split(':')
|
|
41
43
|
const val = valList.join(':')
|
|
42
44
|
|
|
43
|
-
if (typeof val === undefined) {
|
|
45
|
+
if (typeof val === 'undefined') {
|
|
44
46
|
continue
|
|
45
47
|
}
|
|
46
48
|
this.setProperty(propName.trim(), val.trim())
|
|
@@ -48,65 +50,49 @@ class CSSStyleDeclaration {
|
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
public setProperty (prop: string, value: any): void {
|
|
51
|
-
const node = this.el
|
|
52
|
-
|
|
53
53
|
prop = prop.includes('-') ? toCamelCase(prop) : prop
|
|
54
|
-
|
|
55
|
-
const webStyleList = WEB_STYLE_MAP[prop]
|
|
56
|
-
const needUpdateProperty = !prop.startsWith('_') && webStyleList && webStyleList.length > 0
|
|
57
|
-
|
|
54
|
+
const node = this.el
|
|
58
55
|
if ((typeof value === 'string' && value.length) || typeof value === 'number' || isObject(value)) {
|
|
59
|
-
|
|
60
|
-
const newProperty = convertWebStyle2HmStyle({ [prop]: value })
|
|
61
|
-
|
|
62
|
-
Object.keys(newProperty).forEach(key => {
|
|
63
|
-
node._st[key] = newProperty[key]
|
|
64
|
-
})
|
|
65
|
-
} else {
|
|
66
|
-
node._st[prop] = value
|
|
67
|
-
}
|
|
56
|
+
convertWebStyle2HmStyle({ [prop]: value }, node)
|
|
68
57
|
} else if (!value) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
webStyleList.forEach(key => {
|
|
72
|
-
this.removeProperty(key)
|
|
73
|
-
})
|
|
74
|
-
} else {
|
|
58
|
+
if (value === '') {
|
|
59
|
+
// value设置为null或者''了
|
|
75
60
|
this.removeProperty(prop)
|
|
61
|
+
return
|
|
76
62
|
}
|
|
63
|
+
// 判断class的样式表中是否存在该属性
|
|
64
|
+
// 如果存在,则style删除,无需把hmStyle的值删除
|
|
65
|
+
// 如果不存在,则hmStyle上该样式是style设置的,需要删除
|
|
66
|
+
if (isUndefined(this.el._attrs?.__hmStyle?.[prop])) {
|
|
67
|
+
if (this.el && this.el._st) {
|
|
68
|
+
this.el._st.hmStyle[prop] = this.el._attrs?.__hmStyle?.[prop]
|
|
69
|
+
}
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
this.removeProperty(prop)
|
|
77
73
|
}
|
|
78
74
|
}
|
|
79
75
|
|
|
80
76
|
public getPropertyValue (prop: string): string | number {
|
|
81
|
-
const node = this.el
|
|
82
77
|
prop = prop.includes('-') ? toCamelCase(prop) : prop
|
|
78
|
+
const node = this.el
|
|
83
79
|
const value = node._st[prop]
|
|
84
80
|
return value === undefined ? '' : value
|
|
85
81
|
}
|
|
86
82
|
|
|
87
83
|
public removeProperty (prop: string): string | number {
|
|
88
|
-
const node = this.el
|
|
89
84
|
prop = prop.includes('-') ? toCamelCase(prop) : prop
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (value === undefined) {
|
|
95
|
-
// node._st[prop] = undefined
|
|
96
|
-
delete node._st.hmStyle[prop]
|
|
97
|
-
return ''
|
|
98
|
-
} else {
|
|
99
|
-
delete node._st.hmStyle[prop]
|
|
100
|
-
// node._st[prop] = undefined
|
|
101
|
-
// node._st = { ...node._st }
|
|
102
|
-
return value
|
|
103
|
-
}
|
|
85
|
+
const node = this.el
|
|
86
|
+
const value = node._st.hmStyle[prop]
|
|
87
|
+
delete node._st.hmStyle[prop]
|
|
88
|
+
return value
|
|
104
89
|
}
|
|
105
90
|
}
|
|
106
91
|
|
|
107
92
|
type ICSSStyleDeclaration = CSSStyleDeclaration & Record<string, any>
|
|
108
93
|
|
|
109
94
|
function createCSSStyleDeclaration (node: TaroElement): CSSStyleDeclaration {
|
|
95
|
+
// FIXME 临时使用 Proxy 代理,后续需要优化
|
|
110
96
|
return new Proxy(new CSSStyleDeclaration(node), {
|
|
111
97
|
set (target, prop: string, value) {
|
|
112
98
|
if (prop === 'cssText') {
|
|
@@ -4,7 +4,6 @@ import { isUndefined } from '@tarojs/shared'
|
|
|
4
4
|
import { Current } from '../current'
|
|
5
5
|
import { findChildNodeWithDFS, getPageScrollerOrNode } from '../utils'
|
|
6
6
|
import { TaroComment } from './comment'
|
|
7
|
-
import { createCSSStyleDeclaration } from './cssStyleDeclaration'
|
|
8
7
|
import { TaroElement } from './element/element'
|
|
9
8
|
import { NodeType, TaroNode, TaroTextNode } from './node'
|
|
10
9
|
|
|
@@ -36,6 +35,7 @@ class TaroDocument extends TaroNode {
|
|
|
36
35
|
case 'div': tagName = 'view'; break
|
|
37
36
|
case 'p': tagName = 'text'; break
|
|
38
37
|
case 'span': tagName = 'text'; break
|
|
38
|
+
case 'a': tagName = 'text'; break
|
|
39
39
|
}
|
|
40
40
|
// @ts-ignore
|
|
41
41
|
if (Current?.createHarmonyElement) {
|
|
@@ -45,8 +45,6 @@ class TaroDocument extends TaroNode {
|
|
|
45
45
|
node = new TaroElement(tagName)
|
|
46
46
|
}
|
|
47
47
|
node._doc = this
|
|
48
|
-
// Hack: 此 Proxy 不能放在 Element 类内定义,否则响应式更新会失效
|
|
49
|
-
node._style = createCSSStyleDeclaration(node)
|
|
50
48
|
return node
|
|
51
49
|
}
|
|
52
50
|
|
|
@@ -63,7 +61,6 @@ class TaroDocument extends TaroNode {
|
|
|
63
61
|
return new TaroComment(data)
|
|
64
62
|
}
|
|
65
63
|
|
|
66
|
-
|
|
67
64
|
public getElementById<T extends TaroElement> (id: string | undefined | null): T | null {
|
|
68
65
|
const el = eventSource.get(id)
|
|
69
66
|
return isUndefined(el) ? null : el as unknown as T
|
|
@@ -72,20 +69,20 @@ class TaroDocument extends TaroNode {
|
|
|
72
69
|
public querySelector (selectors: string): TaroElement | null {
|
|
73
70
|
const taro = (Current as any).taro
|
|
74
71
|
const page = taro.getCurrentInstance().page
|
|
75
|
-
const element = getPageScrollerOrNode(page
|
|
76
|
-
|
|
77
|
-
if (element
|
|
78
|
-
|
|
72
|
+
const element = getPageScrollerOrNode(page?.node, page)
|
|
73
|
+
|
|
74
|
+
if (!element) return null
|
|
75
|
+
|
|
79
76
|
return findChildNodeWithDFS(element, selectors)
|
|
80
77
|
}
|
|
81
78
|
|
|
82
79
|
public querySelectorAll (selectors: string): TaroElement[] {
|
|
83
80
|
const taro = (Current as any).taro
|
|
84
81
|
const page = taro.getCurrentInstance().page
|
|
85
|
-
const element = getPageScrollerOrNode(page
|
|
86
|
-
|
|
82
|
+
const element = getPageScrollerOrNode(page?.node, page)
|
|
83
|
+
|
|
87
84
|
if (element == null) return []
|
|
88
|
-
|
|
85
|
+
|
|
89
86
|
return findChildNodeWithDFS(element, selectors, true) || []
|
|
90
87
|
}
|
|
91
88
|
// @Todo
|