@miot-rn/common-component 1.0.2 → 1.0.4

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 (39) hide show
  1. package/dist/service/specs/index.js +63 -32
  2. package/dist/service/specs/spec.js +6 -0
  3. package/dist/service/specs/std-spec.js +31 -22
  4. package/dist/service/specs/subscribe-logging.test.d.ts +17 -0
  5. package/dist/service/specs/subscribe-logging.test.js +217 -0
  6. package/dist/service/track/TrackFlatList.d.ts +3 -0
  7. package/dist/service/track/TrackFlatList.js +19 -0
  8. package/dist/service/track/TrackScrollContext.d.ts +10 -0
  9. package/dist/service/track/TrackScrollContext.js +2 -0
  10. package/dist/service/track/TrackScrollView.d.ts +3 -0
  11. package/dist/service/track/TrackScrollView.js +20 -0
  12. package/dist/service/track/TrackService.d.ts +10 -0
  13. package/dist/service/track/TrackService.js +104 -0
  14. package/dist/service/track/index.d.ts +12 -0
  15. package/dist/service/track/index.js +9 -0
  16. package/dist/service/track/intersect.d.ts +8 -0
  17. package/dist/service/track/intersect.js +15 -0
  18. package/dist/service/track/intersect.test.d.ts +1 -0
  19. package/dist/service/track/intersect.test.js +189 -0
  20. package/dist/service/track/types.d.ts +16 -0
  21. package/dist/service/track/types.js +1 -0
  22. package/dist/service/track/useCardTrack.d.ts +14 -0
  23. package/dist/service/track/useCardTrack.js +61 -0
  24. package/dist/service/track/useExposeOnVisible.d.ts +11 -0
  25. package/dist/service/track/useExposeOnVisible.js +74 -0
  26. package/dist/service/track/usePageTrack.d.ts +7 -0
  27. package/dist/service/track/usePageTrack.js +101 -0
  28. package/dist/service/track/useTrack.d.ts +7 -0
  29. package/dist/service/track/useTrack.js +23 -0
  30. package/dist/service/track/useTrackScrollProvider.d.ts +24 -0
  31. package/dist/service/track/useTrackScrollProvider.js +81 -0
  32. package/dist/specs/instance-parser.js +13 -11
  33. package/dist/store/useGlobalSpecManager.d.ts +5 -2
  34. package/dist/store/useGlobalSpecManager.js +402 -63
  35. package/dist/store/useGlobalSpecManager.test.d.ts +1 -0
  36. package/dist/store/useGlobalSpecManager.test.js +247 -0
  37. package/dist/utils/subscribe-log.d.ts +1 -0
  38. package/dist/utils/subscribe-log.js +37 -0
  39. package/package.json +2 -2
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import type { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';
3
+ import { TrackScrollContextValue } from './TrackScrollContext';
4
+ interface ForwardedHandlers {
5
+ onScroll?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
6
+ onLayout?: () => void;
7
+ onMomentumScrollEnd?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
8
+ }
9
+ interface ScrollProps {
10
+ ref: React.MutableRefObject<any>;
11
+ onScroll: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
12
+ onLayout: () => void;
13
+ onMomentumScrollEnd: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
14
+ scrollEventThrottle: number;
15
+ }
16
+ interface ProviderHandle {
17
+ scrollProps: ScrollProps;
18
+ ctxValue: TrackScrollContextValue;
19
+ Provider: React.FC<{
20
+ children: React.ReactNode;
21
+ }>;
22
+ }
23
+ export declare function useTrackScrollProvider(forwarded?: ForwardedHandlers): ProviderHandle;
24
+ export {};
@@ -0,0 +1,81 @@
1
+ import React, { useCallback, useMemo, useRef } from 'react';
2
+ import { TrackScrollContext } from "./TrackScrollContext";
3
+ /**
4
+ * 用法:
5
+ * const tracker = useTrackScrollProvider({ onScroll: myOnScroll });
6
+ * return (
7
+ * <tracker.Provider>
8
+ * <SubpageLayout
9
+ * scrollRef={tracker.scrollProps.ref}
10
+ * onScroll={tracker.scrollProps.onScroll}
11
+ * >...</SubpageLayout>
12
+ * </tracker.Provider>
13
+ * );
14
+ *
15
+ * RAF 合并通知:scroll 16ms × N listeners × 2 次 measureInWindow 容易形成 native bridge 风暴。
16
+ * RAF 合并到每帧最多一次广播;listener 命中即 unsubscribe,稳态后只剩未曝光的卡片。
17
+ * onMomentumScrollEnd 兜底:RAF 节流可能丢最后一帧,滚动停止时再补一次。
18
+ */
19
+ export function useTrackScrollProvider(forwarded = {}) {
20
+ const containerRef = useRef(null);
21
+ const listeners = useRef(new Set());
22
+ const rafScheduled = useRef(false);
23
+ const forwardedRef = useRef(forwarded);
24
+ forwardedRef.current = forwarded;
25
+ const notify = useCallback(() => {
26
+ if (rafScheduled.current) return;
27
+ rafScheduled.current = true;
28
+ requestAnimationFrame(() => {
29
+ rafScheduled.current = false;
30
+ Array.from(listeners.current).forEach(cb => {
31
+ try {
32
+ cb();
33
+ } catch (e) {
34
+ // listener 自身异常不能阻断其它卡片曝光
35
+ // eslint-disable-next-line no-console
36
+ console.warn('[TrackScroll] listener error', e);
37
+ }
38
+ });
39
+ });
40
+ }, []);
41
+ const subscribe = useCallback(cb => {
42
+ listeners.current.add(cb);
43
+ return () => {
44
+ listeners.current.delete(cb);
45
+ };
46
+ }, []);
47
+ const onScroll = useCallback(e => {
48
+ notify();
49
+ forwardedRef.current.onScroll?.(e);
50
+ }, [notify]);
51
+ const onLayout = useCallback(() => {
52
+ notify();
53
+ forwardedRef.current.onLayout?.();
54
+ }, [notify]);
55
+ const onMomentumScrollEnd = useCallback(e => {
56
+ notify();
57
+ forwardedRef.current.onMomentumScrollEnd?.(e);
58
+ }, [notify]);
59
+ const ctxValue = useMemo(() => ({
60
+ containerRef,
61
+ subscribe
62
+ }), [subscribe]);
63
+ const Provider = useMemo(() => function TrackScrollProviderImpl({
64
+ children
65
+ }) {
66
+ return /*#__PURE__*/React.createElement(TrackScrollContext.Provider, {
67
+ value: ctxValue
68
+ }, children);
69
+ }, [ctxValue]);
70
+ return {
71
+ scrollProps: {
72
+ ref: containerRef,
73
+ onScroll,
74
+ onLayout,
75
+ onMomentumScrollEnd,
76
+ scrollEventThrottle: 16
77
+ },
78
+ ctxValue,
79
+ Provider
80
+ };
81
+ }
@@ -132,7 +132,7 @@ function getIidsGetter() {
132
132
  }
133
133
 
134
134
  // 获取目标模块
135
- const targetModule = findModuleByKeyAndDescription(normalizedMKey, normalizedMDescription);
135
+ const targetModule = findModule(normalizedMKey, normalizedMDescription);
136
136
  // console.log('targetModule---', targetModule);
137
137
 
138
138
  if (!targetModule && mkey) {
@@ -226,8 +226,10 @@ function getIidsGetter() {
226
226
  // 添加模块信息
227
227
  if (mkey && targetModule) {
228
228
  spec.miid = targetModule?.iid;
229
- spec.mkey = mkey || parseSpecType(targetModule?.type).key;
230
- spec.mDescription = normalizedMDescription;
229
+ spec.mkey = parseSpecType(targetModule?.type).key || mkey;
230
+ if (normalizedMDescription) {
231
+ spec.mDescription = normalizedMDescription;
232
+ }
231
233
  }
232
234
 
233
235
  // 将最新版本的结果添加到数组开头
@@ -557,25 +559,25 @@ function getTargetModule(miid) {
557
559
  }
558
560
 
559
561
  /**
560
- * 根据mkey和mDescription查找模块
562
+ * 查找匹配的模块。
563
+ * - mkey 通过 module.type 解析(与 service/property 保持一致口径)
564
+ * - mDescription 仅在提供时用于二次消歧(同 name 存在多个 module 的场景)
561
565
  * @param {string} mkey - 模块键
562
566
  * @param {string} mDescription - 模块描述(可选)
563
567
  * @returns {Object|null} - 返回目标模块对象或null
564
568
  */
565
- function findModuleByKeyAndDescription(mkey, mDescription) {
569
+ function findModule(mkey, mDescription) {
566
570
  const normalizedMKey = safeTrim(mkey);
567
571
  const normalizedMDescription = safeTrim(mDescription);
568
572
  // 如果是版本3
569
573
  if (CachedSpecVersion === 3) {
570
574
  return (CachedInstance.modules || []).find(module => {
571
- const moduleDescription = safeTrim(module?.description);
572
- const moduleName = safeTrim(module?.name);
573
- // 如果提供了mDescription,同时匹配mkey和mDescription
575
+ if (parseSpecType(module?.type).key !== normalizedMKey) return false;
576
+ // 提供了 mDescription 时同时匹配 module.description
574
577
  if (normalizedMDescription) {
575
- return moduleName === normalizedMKey && moduleDescription === normalizedMDescription;
578
+ return safeTrim(module?.description) === normalizedMDescription;
576
579
  }
577
- // 只匹配mkey
578
- return moduleName === normalizedMKey;
580
+ return true;
579
581
  });
580
582
  }
581
583
  // 如果是版本2,返回整个实例
@@ -4,11 +4,14 @@ export { toKey };
4
4
  declare const useGlobalSpecManager: import("zustand").UseBoundStore<import("zustand").StoreApi<{
5
5
  specsMetaInfo: {};
6
6
  specsState: {};
7
+ pendingKeys: Set<unknown>;
7
8
  eventListeners: {};
8
9
  subscribedSpecs: Set<unknown>;
9
10
  specUpdateListeners: never[];
10
11
  addSpecUpdateListener: (listener: any) => () => void;
11
- fetchSpecs: (specs: any, fromSource?: boolean, batchUpdate?: boolean) => Promise<({
12
+ _deferRemovePendingKey: (key: string) => void;
13
+ _rollbackOptimisticSpec: (key: string, failedValue: any) => boolean;
14
+ fetchSpecs: (specs: any, datasource?: number, batchUpdate?: boolean) => Promise<({
12
15
  code: number;
13
16
  message: string;
14
17
  spec: any;
@@ -167,7 +170,7 @@ export declare const useSpecMetaInfo: (spec: any) => any;
167
170
  export declare const useSpecUpdateListener: (listener: any) => void;
168
171
  export declare const useEventListener: (eventSpec: any, listener: any) => () => void;
169
172
  export declare const addSpecUpdateListener: (listener: any) => () => void;
170
- export declare const fetchSpecs: (specs: any, fromSource?: boolean, batchUpdate?: boolean) => Promise<({
173
+ export declare const fetchSpecs: (specs: any, datasource?: number, batchUpdate?: boolean) => Promise<({
171
174
  code: number;
172
175
  message: string;
173
176
  spec: any;