press-pix
Version:
基于 PixUI 的 Press 组件库
122 lines (108 loc) • 3.14 kB
text/typescript
import { useEffect, useState } from 'preact/hooks';
import { getSafeAreaInfo, getSafeAreaStyle, isSafeAreaReady, subscribeSafeAreaChange, tryGetSafeAreaInfo } from './safe-area';
/**
* React Hook:获取 Safe Area 信息
* 自动处理异步数据获取和状态更新
*
* @example
* function MyComponent() {
* const safeArea = useSafeArea();
* return (
* <div>
* Left: {safeArea.left}px
* Right: {safeArea.right}px
* </div>
* );
* }
*/
export function useSafeArea() {
const [safeArea, setSafeArea] = useState(() => getSafeAreaInfo());
useEffect(() => {
let mounted = true;
// 如果数据还未准备好,等待数据准备完成
if (!isSafeAreaReady()) {
tryGetSafeAreaInfo().then(() => {
if (mounted) {
setSafeArea(getSafeAreaInfo());
}
});
}
// 订阅数据变化,当数据更新时自动刷新
const unsubscribe = subscribeSafeAreaChange(() => {
if (mounted) {
setSafeArea(getSafeAreaInfo());
}
});
return () => {
mounted = false;
unsubscribe();
};
}, []);
return safeArea;
}
/**
* React Hook:获取 Safe Area 样式对象
* 自动处理异步数据获取和状态更新
*
* @param options - 可选配置
* @param options.left - 是否包含 paddingLeft,默认 true
* @param options.right - 是否包含 paddingRight,默认 true
* @param options.position - 定位方式,'left' 或 'right'
*
* @example
* // 基本用法(左右都设置)
* function MyComponent() {
* const safeAreaStyle = useSafeAreaStyle();
* return <div style={safeAreaStyle}>内容</div>;
* }
*
* @example
* // 只设置左边距
* function MyComponent() {
* const safeAreaStyle = useSafeAreaStyle({ right: false });
* return <div style={safeAreaStyle}>内容</div>;
* }
*
* @example
* // 设置右侧定位
* function MyComponent() {
* const safeAreaStyle = useSafeAreaStyle({ position: 'right' });
* return <div style={safeAreaStyle}>内容</div>;
* }
*
* @example
* // 与其他样式合并
* function MyComponent() {
* const safeAreaStyle = useSafeAreaStyle();
* return (
* <div style={{ ...safeAreaStyle, backgroundColor: 'red' }}>
* 内容
* </div>
* );
* }
*/
export function useSafeAreaStyle(options?: { left?: boolean; right?: boolean; position?: 'left' | 'right' }) {
const [safeAreaStyle, setSafeAreaStyle] = useState(() => getSafeAreaStyle(options));
useEffect(() => {
let mounted = true;
// 如果数据还未准备好,等待数据准备完成
if (!isSafeAreaReady()) {
tryGetSafeAreaInfo().then(() => {
if (mounted) {
setSafeAreaStyle(getSafeAreaStyle(options));
}
});
}
// 订阅数据变化,当数据更新时自动刷新样式
const unsubscribe = subscribeSafeAreaChange(() => {
if (mounted) {
setSafeAreaStyle(getSafeAreaStyle(options));
}
});
return () => {
mounted = false;
unsubscribe();
};
}, [options?.left, options?.right, options?.position]);
return safeAreaStyle;
}