Skip to content

Commit

Permalink
fix(appear): resolve conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
linbudu599 committed Aug 2, 2023
2 parents 3c56678 + 8af8452 commit 1127c98
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 52 deletions.
5 changes: 5 additions & 0 deletions .changeset/dry-pets-sing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@ice/appear': minor
---

chore: weex support for ice appear
61 changes: 10 additions & 51 deletions packages/appear/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,55 +1,14 @@
import { Children, useRef, useEffect, useCallback } from 'react';
import type { Ref, RefObject } from 'react';
import { isFunction } from './type';
import { observerElement, VisibilityChangeEvent } from './visibility';
import type * as React from 'react';
import WebAppear from './web';
import WeexAppear from './weex';
import type { AppearProps } from './typings.js';

interface Node {
_nativeNode?: Node;
}

function VisibilityChange(props: any) {
const { onAppear, onDisappear, children } = props;

const defaultRef: Ref<Node> = useRef<Node>();

const ref: RefObject<Node> = children.ref
? typeof children.ref === 'object'
? children.ref
: defaultRef
: defaultRef;

useEffect(() => {
if (typeof children.ref === 'function') {
children.ref(ref.current);
}
}, [ref, children]);

const listen = useCallback(
(eventName: string, handler: EventListenerOrEventListenerObject) => {
const { current } = ref;
// Rax components will set custom ref by useImperativeHandle.
// So We should get eventTarget by _nativeNode.
// https://github.com/raxjs/rax-components/blob/master/packages/rax-textinput/src/index.tsx#L151
if (current && isFunction(handler)) {
const eventTarget = current._nativeNode || current;
observerElement(eventTarget as Element);
eventTarget.addEventListener(eventName, handler);
}
return () => {
const { current } = ref;
if (current) {
const eventTarget = current._nativeNode || current;
eventTarget.removeEventListener(eventName, handler);
}
};
},
[ref],
);

useEffect(() => listen(VisibilityChangeEvent.appear, onAppear), [ref, onAppear, listen]);
useEffect(() => listen(VisibilityChangeEvent.disappear, onDisappear), [ref, onDisappear, listen]);
let Appear: React.ForwardRefExoticComponent<AppearProps & React.RefAttributes<any>>;

return Children.only({ ...children, ref });
if (import.meta.target === 'weex') {
Appear = WeexAppear;
} else {
Appear = WebAppear as any;
}

export default VisibilityChange;
export default Appear;
11 changes: 11 additions & 0 deletions packages/appear/src/runtime.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/// <reference types="@ice/pkg/types" />

interface ImportMeta {
// The build target
target: 'weex' | 'web';
}


interface Node {
_nativeNode: Node;
}
17 changes: 17 additions & 0 deletions packages/appear/src/typings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type * as React from 'react';

export interface AppearProps {
children: React.ReactElement;
/**
* Triggered when the element enters the visible area.
* @param {CustomEvent} e
* @returns {void}
*/
onAppear?: (e: CustomEvent) => void;
/**
* Triggered when the element leaves the visible area.
* @param {CustomEvent} e
* @returns {void}
*/
onDisappear?: (e: CustomEvent) => void;
}
53 changes: 53 additions & 0 deletions packages/appear/src/web/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Children, useRef, useEffect, useCallback } from 'react';
import type { Ref, RefObject } from 'react';
import { isFunction } from './type';
import { observerElement, VisibilityChangeEvent } from './visibility';

interface Node {
_nativeNode?: Node;
}

export default function VisibilityChange(props: any) {
const { onAppear, onDisappear, children } = props;

const defaultRef: Ref<Node> = useRef<Node>();

const ref: RefObject<Node> = children.ref
? typeof children.ref === 'object'
? children.ref
: defaultRef
: defaultRef;

useEffect(() => {
if (typeof children.ref === 'function') {
children.ref(ref.current);
}
}, [ref, children]);

const listen = useCallback(
(eventName: string, handler: EventListenerOrEventListenerObject) => {
const { current } = ref;
// Rax components will set custom ref by useImperativeHandle.
// So We should get eventTarget by _nativeNode.
// https://github.com/raxjs/rax-components/blob/master/packages/rax-textinput/src/index.tsx#L151
if (current && isFunction(handler)) {
const eventTarget = current._nativeNode || current;
observerElement(eventTarget as Element);
eventTarget.addEventListener(eventName, handler);
}
return () => {
const { current } = ref;
if (current) {
const eventTarget = current._nativeNode || current;
eventTarget.removeEventListener(eventName, handler);
}
};
},
[ref],
);

useEffect(() => listen(VisibilityChangeEvent.appear, onAppear), [ref, onAppear, listen]);
useEffect(() => listen(VisibilityChangeEvent.disappear, onDisappear), [ref, onDisappear, listen]);

return Children.only({ ...children, ref });
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export function isFunction(obj: any): obj is Function {
return typeof obj === 'function';
}
}
File renamed without changes.
36 changes: 36 additions & 0 deletions packages/appear/src/weex/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { ForwardedRef } from 'react';
import { useEffect, useRef, forwardRef, cloneElement, Children } from 'react';
import type { AppearProps } from '../typings';

const WeexAppear = forwardRef<any, AppearProps>((props, ref) => {
const internalRef = useRef<HTMLDivElement>(null);
const childrenRef: ForwardedRef<HTMLDivElement> = ref ?? internalRef;

const { children, onAppear, onDisappear } = props;

useEffect(() => {
// Use copy of childrenRef to avoid ref value changed in cleanup phase.
const nodeRef = typeof childrenRef === 'object' ? childrenRef.current : null;

// Return early if onAppear callback not specified.
onAppear && nodeRef?.addEventListener('appear', (e: CustomEvent) => onAppear(e));

return () => {
onAppear && nodeRef?.removeEventListener('appear', (e: CustomEvent) => onAppear(e));
};
}, [childrenRef, onAppear]);

useEffect(() => {
const nodeRef = typeof childrenRef === 'object' ? childrenRef.current : null;

onDisappear && nodeRef?.addEventListener('disappear', (e: CustomEvent) => onDisappear(e));

return () => {
onDisappear && nodeRef?.removeEventListener('disappear', (e: CustomEvent) => onDisappear(e));
};
}, [childrenRef, onDisappear]);

return cloneElement(Children.only(children), { ref: childrenRef });
});

export default WeexAppear;

0 comments on commit 1127c98

Please sign in to comment.