@tarojs/react 4.0.1 → 4.0.3-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -154,15 +154,8 @@ See `/LICENSE` for details of the license.
154
154
 
155
155
  ==================
156
156
 
157
- MIT (stencil-vue2-output-target):
158
- The following files embed [stencil-vue2-output-target](https://github.com/diondree/stencil-vue2-output-target) MIT:
159
- `/packages/taro-components-library-vue2/src/vue-component-lib/utils.ts`
160
- See `/LICENSE` for details of the license.
161
-
162
- ==================
163
-
164
157
  MIT (weui):
165
- The following files embed [stencil-vue2-output-target](https://github.com/Tencent/weui) MIT:
158
+ The following files embed [weui](https://github.com/Tencent/weui) MIT:
166
159
  `/packages/taro-components/src/components/*.scss`
167
160
  See `/LICENSE.txt` for details of the license.
168
161
 
@@ -172,3 +165,10 @@ Apache-2.0 (intersection-observer):
172
165
  The following files embed [intersection-observer](https://github.com/GoogleChromeLabs/intersection-observer) Apache-2.0:
173
166
  `/packages/taro-api/src/polyfill/intersection-observer.ts`
174
167
  See `/LICENSE.txt` for details of the license.
168
+
169
+ ==================
170
+
171
+ MIT (babel-plugin-jsx-dom-expressions):
172
+ The following files embed [babel-plugin-jsx-dom-expressions](https://github.com/ryansolid/dom-expressions/blob/main/packages/babel-plugin-jsx-dom-expressions) MIT:
173
+ `/packages/babel-plugin-transform-solid-jsx/src/*`
174
+ See `/LICENSE` for details of the license.
@@ -0,0 +1,19 @@
1
+ import type { TaroElement, TaroText } from '@tarojs/runtime';
2
+ import type { Fiber } from 'react-reconciler';
3
+ import type { Props } from './props';
4
+ export declare function precacheFiberNode(hostInst: Fiber, node: TaroElement | TaroText): void;
5
+ export declare function markContainerAsRoot(hostRoot: Fiber, node: TaroElement | TaroText): void;
6
+ export declare function unmarkContainerAsRoot(node: TaroElement | TaroText): void;
7
+ export declare function isContainerMarkedAsRoot(node: TaroElement | TaroText): boolean;
8
+ /**
9
+ * Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent
10
+ * instance, or null if the node was not rendered by this React.
11
+ */
12
+ export declare function getInstanceFromNode(node: TaroElement | TaroText): Fiber | null;
13
+ /**
14
+ * Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding
15
+ * DOM node.
16
+ */
17
+ export declare function getNodeFromInstance(inst: Fiber): any;
18
+ export declare function getFiberCurrentPropsFromNode(node: TaroElement | TaroText): Props;
19
+ export declare function updateFiberProps(node: TaroElement | TaroText, props: Props): void;
@@ -0,0 +1,7 @@
1
+ export declare const supportedInputTypes: {
2
+ [key: string]: boolean;
3
+ };
4
+ export declare function getEventPriority(domEventName: any): 1 | 4 | 16;
5
+ export declare const internalPropsKey: string;
6
+ export declare const internalInstanceKey: string;
7
+ export declare const internalContainerInstanceKey: string;
@@ -0,0 +1,12 @@
1
+ import { Props } from './props';
2
+ import type { FormElement, TaroElement } from '@tarojs/runtime';
3
+ import type { RestoreType } from './event';
4
+ declare function updateInputWrapper(element: TaroElement, oldValue: RestoreType, props: Props): void;
5
+ export declare function getToStringValue(value: any): any;
6
+ export declare function toString(value: any): string;
7
+ export declare function updateWrapper(element: TaroElement, oldValue: RestoreType, props: Props): void;
8
+ export declare function setNodeValue(node: FormElement, oldValue: RestoreType, value: any, type?: string): void;
9
+ export declare function isTextInputElement(elem: TaroElement): boolean;
10
+ export declare const ReactDOMTextareaRestoreControlledState: typeof updateWrapper;
11
+ export declare const ReactDOMInputRestoreControlledState: typeof updateInputWrapper;
12
+ export {};
@@ -0,0 +1,13 @@
1
+ import type { TaroElement, TaroEvent } from '@tarojs/runtime';
2
+ import type { Fiber } from 'react-reconciler';
3
+ export type RestoreType = string | number | boolean | any[];
4
+ interface RestoreItem {
5
+ target: TaroElement;
6
+ value: RestoreType;
7
+ }
8
+ export declare function getTargetInstForInputOrChangeEvent(e: TaroEvent, node: TaroElement): false | Fiber | undefined;
9
+ export declare function enqueueStateRestore(target: RestoreItem): void;
10
+ export declare function needsStateRestore(): boolean;
11
+ export declare function finishEventHandler(): void;
12
+ export declare function restoreStateIfNeeded(): void;
13
+ export {};
package/dist/index.d.ts CHANGED
@@ -1,30 +1,10 @@
1
- import { TaroElement, TaroText } from '@tarojs/runtime';
2
- import { ReactNode } from 'react';
3
- import Reconciler from "react-reconciler";
4
- import { OpaqueRoot } from "react-reconciler";
5
- declare const TaroReconciler: Reconciler.Reconciler<TaroElement, TaroElement, TaroText, TaroElement, TaroElement>;
6
- type Renderer = typeof TaroReconciler;
7
- type CreateRootOptions = {
8
- unstable_strictMode?: boolean;
9
- unstable_concurrentUpdatesByDefault?: boolean;
10
- unstable_transitionCallbacks?: any;
11
- identifierPrefix?: string;
12
- onRecoverableError?: (error: any) => void;
13
- };
14
- type Callback = () => void | null | undefined;
15
- declare class Root {
16
- private renderer;
17
- internalRoot: OpaqueRoot;
18
- constructor(renderer: Renderer, domContainer: TaroElement, options?: CreateRootOptions);
19
- private initInternalRoot;
20
- render(children: ReactNode, cb: Callback): TaroElement | import("react").Component<any, any, any> | null;
21
- unmount(cb: Callback): void;
22
- }
23
- declare function render(element: ReactNode, domContainer: TaroElement, cb: Callback): TaroElement | import("react").Component<any, any, any> | null;
24
- declare function createRoot(domContainer: TaroElement, options?: CreateRootOptions): Root;
1
+ import { internalInstanceKey } from './constant';
2
+ import { createRoot, render } from './render';
3
+ import type { TaroElement } from '@tarojs/runtime';
4
+ import type { ReactNode } from 'react';
25
5
  declare const unstable_batchedUpdates: (fn: any, a: any) => any;
26
6
  declare function unmountComponentAtNode(dom: TaroElement): boolean;
27
- declare function findDOMNode(comp?: TaroElement | ReactNode): string | number | boolean | TaroElement | import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | import("react").ReactFragment | null;
7
+ declare function findDOMNode(comp?: TaroElement | ReactNode): string | number | boolean | TaroElement | import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null;
28
8
  declare function createPortal(children: ReactNode, containerInfo: TaroElement, key?: string): {
29
9
  $$typeof: number | symbol;
30
10
  key: string | null;
@@ -32,12 +12,22 @@ declare function createPortal(children: ReactNode, containerInfo: TaroElement, k
32
12
  containerInfo: TaroElement;
33
13
  implementation: null;
34
14
  };
15
+ declare const flushSync: {
16
+ (): void;
17
+ <R>(fn: () => R): R;
18
+ };
19
+ export { createPortal, createRoot, findDOMNode, flushSync, internalInstanceKey, render, unmountComponentAtNode, unstable_batchedUpdates, };
35
20
  declare const _default: {
36
21
  render: typeof render;
22
+ flushSync: {
23
+ (): void;
24
+ <R>(fn: () => R): R;
25
+ };
37
26
  createRoot: typeof createRoot;
38
27
  unstable_batchedUpdates: (fn: any, a: any) => any;
39
28
  unmountComponentAtNode: typeof unmountComponentAtNode;
40
29
  findDOMNode: typeof findDOMNode;
41
30
  createPortal: typeof createPortal;
31
+ internalInstanceKey: string;
42
32
  };
43
- export { _default as default, createPortal, createRoot, findDOMNode, render, unmountComponentAtNode, unstable_batchedUpdates };
33
+ export default _default;
@@ -0,0 +1,3 @@
1
+ export declare function track(node: any): void;
2
+ export declare function updateValueIfChanged(node: any, nextValue: string): boolean;
3
+ export declare function stopTracking(node: any): void;
@@ -0,0 +1,5 @@
1
+ import { type TaroElement } from '@tarojs/runtime';
2
+ export type Props = Record<string, unknown>;
3
+ export declare function updateProps(dom: TaroElement, oldProps: Props, newProps: Props): void;
4
+ export declare function updatePropsByPayload(dom: TaroElement, oldProps: Props, updatePayload: any[]): void;
5
+ export declare function getUpdatePayload(dom: TaroElement, oldProps: Props, newProps: Props): any[] | null;
package/dist/react.esm.js CHANGED
@@ -1,5 +1,5 @@
1
- import { isString, isObject, isFunction, capitalize, toCamelCase, internalComponents, isNumber, noop, isUndefined, isBoolean, ensure } from '@tarojs/shared';
2
- import { FormElement, document, hooks } from '@tarojs/runtime';
1
+ import { isObject, isString, isFunction, capitalize, toCamelCase, internalComponents, isNumber, noop, isUndefined, isBoolean, hooks, ensure } from '@tarojs/shared';
2
+ import { FormElement, convertNumber2PX, document } from '@tarojs/runtime';
3
3
  import Reconciler from 'react-reconciler';
4
4
  import { DefaultEventPriority as DefaultEventPriority$1 } from 'react-reconciler/constants';
5
5
 
@@ -134,6 +134,10 @@ function getFiberCurrentPropsFromNode(node) {
134
134
  }
135
135
  function updateFiberProps(node, props) {
136
136
  node[internalPropsKey] = props;
137
+ if (process.env.TARO_PLATFORM === 'harmony') {
138
+ // @ts-ignore
139
+ node.updateTextNode();
140
+ }
137
141
  }
138
142
 
139
143
  // 从 props 中,更新 input 组件的 value 值
@@ -173,10 +177,10 @@ function updateWrapper(element, oldValue, props) {
173
177
  function setNodeValue(node, oldValue, value, type = 'string') {
174
178
  if (value != null) {
175
179
  if (type === 'number') {
176
- if ((value === 0 && node.value === '') ||
180
+ if ((value === 0 && node.value === '')
177
181
  // We explicitly want to coerce to number here if possible.
178
182
  // eslint-disable-next-line
179
- oldValue != value) {
183
+ || oldValue != value) {
180
184
  node.value = toString(value);
181
185
  }
182
186
  }
@@ -280,10 +284,37 @@ function updateValueIfChanged(node, nextValue) {
280
284
  return false;
281
285
  }
282
286
 
287
+ const isHarmony = process.env.TARO_PLATFORM === 'harmony';
288
+ const IS_NON_DIMENSIONAL = /max|aspect|acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;
283
289
  function isEventName(s) {
284
290
  return s[0] === 'o' && s[1] === 'n';
285
291
  }
286
- const IS_NON_DIMENSIONAL = /aspect|acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;
292
+ function isEqual(obj1, obj2) {
293
+ // 首先检查引用是否相同
294
+ if (obj1 === obj2) {
295
+ return true;
296
+ }
297
+ // 如果两者中有一个不是对象,或者为 null,直接返回 false
298
+ if (typeof obj1 !== 'object' || obj1 === null || typeof obj2 !== 'object' || obj2 === null) {
299
+ return false;
300
+ }
301
+ // 获取两个对象键的数组
302
+ const keys1 = Object.keys(obj1);
303
+ const keys2 = Object.keys(obj2);
304
+ // 如果键的数量不相同,对象显然不相等
305
+ if (keys1.length !== keys2.length) {
306
+ return false;
307
+ }
308
+ // 遍历对象的每个键,比较两个对象同一键的值
309
+ for (let i = 0; i < keys1.length; i++) {
310
+ const key = keys1[i];
311
+ if (obj1[key] !== obj2[key]) {
312
+ return false;
313
+ }
314
+ }
315
+ // 如果所有键的值都相等,返回 true
316
+ return true;
317
+ }
287
318
  function updateProps(dom, oldProps, newProps) {
288
319
  const updatePayload = getUpdatePayload(dom, oldProps, newProps);
289
320
  if (updatePayload) {
@@ -291,11 +322,36 @@ function updateProps(dom, oldProps, newProps) {
291
322
  }
292
323
  }
293
324
  function updatePropsByPayload(dom, oldProps, updatePayload) {
294
- for (let i = 0; i < updatePayload.length; i += 2) { // key, value 成对出现
325
+ const handlers = [];
326
+ let fixedHandler = null;
327
+ for (let i = 0; i < updatePayload.length; i += 2) {
328
+ // key, value 成对出现
295
329
  const key = updatePayload[i];
296
330
  const newProp = updatePayload[i + 1];
297
331
  const oldProp = oldProps[key];
298
- setProperty(dom, key, newProp, oldProp);
332
+ if (isHarmony) {
333
+ if (key === '__fixed') {
334
+ // hack: __fixed最先识别
335
+ fixedHandler = () => setProperty(dom, key, newProp, oldProp);
336
+ continue;
337
+ }
338
+ // 鸿蒙样式前置插入,防止覆盖style
339
+ if (key === '__hmStyle') {
340
+ handlers.splice(0, 0, () => setHarmonyStyle(dom, newProp, oldProp));
341
+ }
342
+ else {
343
+ handlers.push(() => setProperty(dom, key, newProp, oldProp));
344
+ }
345
+ }
346
+ else {
347
+ setProperty(dom, key, newProp, oldProp);
348
+ }
349
+ }
350
+ if (isHarmony) {
351
+ fixedHandler && fixedHandler();
352
+ for (let i = 0; i < handlers.length; i++) {
353
+ handlers[i]();
354
+ }
299
355
  }
300
356
  }
301
357
  function getUpdatePayload(dom, oldProps, newProps) {
@@ -309,6 +365,9 @@ function getUpdatePayload(dom, oldProps, newProps) {
309
365
  const isFormElement = dom instanceof FormElement;
310
366
  for (i in newProps) {
311
367
  if (oldProps[i] !== newProps[i] || (isFormElement && i === 'value')) {
368
+ // 如果都是 style,且 style 里面的值相等,则无需记录到 payload 中
369
+ if (i === 'style' && isObject(oldProps[i]) && isObject(newProps[i]) && isEqual(oldProps[i], newProps[i]))
370
+ continue;
312
371
  (updatePayload = updatePayload || []).push(i, newProps[i]);
313
372
  }
314
373
  }
@@ -326,16 +385,16 @@ function setEvent(dom, name, value, oldValue) {
326
385
  eventName = eventName.slice(0, -7);
327
386
  }
328
387
  const compName = capitalize(toCamelCase(dom.tagName.toLowerCase()));
329
- if (eventName === 'click' && compName in internalComponents) {
388
+ if (eventName === 'click' && !isHarmony && compName in internalComponents) {
330
389
  eventName = 'tap';
331
390
  }
332
391
  if (isFunction(value)) {
333
392
  if (oldValue) {
334
- dom.removeEventListener(eventName, oldValue, false);
335
- dom.addEventListener(eventName, value, { isCapture, sideEffect: false });
393
+ dom.removeEventListener(eventName, oldValue, !isHarmony ? false : undefined);
394
+ dom.addEventListener(eventName, value, !isHarmony ? { isCapture, sideEffect: false } : undefined);
336
395
  }
337
396
  else {
338
- dom.addEventListener(eventName, value, isCapture);
397
+ dom.addEventListener(eventName, value, !isHarmony ? isCapture : undefined);
339
398
  }
340
399
  }
341
400
  else {
@@ -343,18 +402,86 @@ function setEvent(dom, name, value, oldValue) {
343
402
  }
344
403
  }
345
404
  function setStyle(style, key, value) {
346
- if (key[0] === '-') {
347
- style.setProperty(key, value.toString());
405
+ if (key[0] === '-' && !isHarmony) {
348
406
  // css variables need not further judgment
407
+ style.setProperty(key, value.toString());
349
408
  return;
350
409
  }
351
410
  style[key] =
352
411
  isNumber(value) && IS_NON_DIMENSIONAL.test(key) === false
353
- ? value + 'px'
354
- : value == null
412
+ ? (isHarmony ? value + 'px' : convertNumber2PX(value))
413
+ : value === null
355
414
  ? ''
356
415
  : value;
357
416
  }
417
+ // 鸿蒙样式特殊处理,需要在插入顺序中前置插入,防止覆盖了style
418
+ function setHarmonyStyle(dom, value, oldValue) {
419
+ // @ts-ignore
420
+ const style = dom._st.hmStyle; // __hmStyle是已经被处理过的鸿蒙样式,可以直接塞进hmStyle对象内
421
+ if (isObject(oldValue)) {
422
+ for (const i in oldValue) {
423
+ if (!(value && i in value)) {
424
+ // 鸿蒙伪类特殊处理
425
+ if (isHarmony) {
426
+ if (i === '::after' || i === '::before') {
427
+ setPseudo(dom, i, null);
428
+ }
429
+ else if (['::first-child', '::last-child', '::empty'].includes(i) || `${i}`.indexOf('::nth-child') === 0) {
430
+ // @ts-ignore
431
+ dom.set_pseudo_class(i, null);
432
+ }
433
+ else {
434
+ if (i === 'position' && oldValue[i] === 'fixed') {
435
+ // @ts-ignore
436
+ dom.setLayer(0);
437
+ }
438
+ else if (i === 'animationName') {
439
+ // @ts-ignore
440
+ dom.setAnimation(false);
441
+ }
442
+ style[i] = '';
443
+ }
444
+ }
445
+ else {
446
+ style[i] = '';
447
+ }
448
+ }
449
+ }
450
+ }
451
+ if (isObject(value)) {
452
+ for (const i in value) {
453
+ if (!oldValue || !isEqual(value[i], oldValue[i])) {
454
+ // 鸿蒙伪类特殊处理
455
+ if (isHarmony) {
456
+ if (i === '::after' || i === '::before') {
457
+ setPseudo(dom, i, value[i]);
458
+ }
459
+ else if (['::first-child', '::last-child', '::empty'].includes(i) || i.startsWith('::nth-child')) {
460
+ // @ts-ignore
461
+ dom.set_pseudo_class(i, value[i]);
462
+ }
463
+ else {
464
+ if (i === 'position') {
465
+ if (value[i] === 'fixed' || (value[i] !== 'fixed' && (oldValue === null || oldValue === void 0 ? void 0 : oldValue[i]))) {
466
+ // @ts-ignore
467
+ dom.setLayer(value[i] === 'fixed' ? 1 : 0);
468
+ }
469
+ }
470
+ else if (i === 'animationName') {
471
+ // @ts-ignore
472
+ dom.setAnimation(true);
473
+ }
474
+ style[i] = value[i];
475
+ }
476
+ }
477
+ else {
478
+ style[i] = value[i];
479
+ }
480
+ }
481
+ }
482
+ }
483
+ dom.setAttribute('__hmStyle', value);
484
+ }
358
485
  function setProperty(dom, name, value, oldValue) {
359
486
  var _a, _b;
360
487
  name = name === 'className' ? 'class' : name;
@@ -374,13 +501,25 @@ function setProperty(dom, name, value, oldValue) {
374
501
  if (isObject(oldValue)) {
375
502
  for (const i in oldValue) {
376
503
  if (!(value && i in value)) {
504
+ // Harmony特殊处理
505
+ if (isHarmony && i === 'position' && oldValue[i] === 'fixed') {
506
+ // @ts-ignore
507
+ dom.setLayer(0);
508
+ }
377
509
  setStyle(style, i, '');
378
510
  }
379
511
  }
380
512
  }
381
513
  if (isObject(value)) {
382
514
  for (const i in value) {
383
- if (!oldValue || value[i] !== oldValue[i]) {
515
+ if (!oldValue || !isEqual(value[i], oldValue[i])) {
516
+ // Harmony特殊处理
517
+ if (isHarmony && i === 'position') {
518
+ if (value[i] === 'fixed' || (value[i] !== 'fixed' && (oldValue === null || oldValue === void 0 ? void 0 : oldValue[i]))) {
519
+ // @ts-ignore
520
+ dom.setLayer(value[i] === 'fixed' ? 1 : 0);
521
+ }
522
+ }
384
523
  setStyle(style, i, value[i]);
385
524
  }
386
525
  }
@@ -408,6 +547,17 @@ function setProperty(dom, name, value, oldValue) {
408
547
  }
409
548
  }
410
549
  }
550
+ // 设置鸿蒙伪类属性(特殊设置)
551
+ function setPseudo(dom, name, value) {
552
+ if (name === '::after') {
553
+ // @ts-ignore
554
+ dom.set_pseudo_after(value);
555
+ }
556
+ else if (name === '::before') {
557
+ // @ts-ignore
558
+ dom.set_pseudo_before(value);
559
+ }
560
+ }
411
561
 
412
562
  /* eslint-disable @typescript-eslint/indent */
413
563
  const hostConfig = {
@@ -510,6 +660,11 @@ const hostConfig = {
510
660
  },
511
661
  commitMount: noop,
512
662
  commitUpdate(dom, updatePayload, _, oldProps, newProps) {
663
+ if (!updatePayload)
664
+ return;
665
+ // payload 只包含 children 的时候,不应该再继续触发后续的属性比较和更新的逻辑了
666
+ if (updatePayload.length === 2 && updatePayload.includes('children'))
667
+ return;
513
668
  updatePropsByPayload(dom, oldProps, updatePayload);
514
669
  updateFiberProps(dom, newProps);
515
670
  },
@@ -729,6 +884,7 @@ function createRoot(domContainer, options = {}) {
729
884
  return root;
730
885
  }
731
886
 
887
+ /* eslint-disable @typescript-eslint/no-unused-vars */
732
888
  let isInsideEventHandler = false;
733
889
  // 重新包裹 batchedUpdates,使其可以在触发事件后执行 finishEventHandler
734
890
  const unstable_batchedUpdates = (fn, a) => {
@@ -778,14 +934,17 @@ function createPortal(children, containerInfo, key) {
778
934
  implementation: null
779
935
  };
780
936
  }
937
+ const flushSync = TaroReconciler.flushSync;
781
938
  var index = {
782
939
  render,
940
+ flushSync,
783
941
  createRoot,
784
942
  unstable_batchedUpdates,
785
943
  unmountComponentAtNode,
786
944
  findDOMNode,
787
- createPortal
945
+ createPortal,
946
+ internalInstanceKey
788
947
  };
789
948
 
790
- export { createPortal, createRoot, index as default, findDOMNode, render, unmountComponentAtNode, unstable_batchedUpdates };
949
+ export { createPortal, createRoot, index as default, findDOMNode, flushSync, internalInstanceKey, render, unmountComponentAtNode, unstable_batchedUpdates };
791
950
  //# sourceMappingURL=react.esm.js.map