chore: ruler files update

Signed-off-by: Dmytro Stanchiev <git@dmytros.dev>
This commit is contained in:
2026-05-24 21:03:49 -04:00
parent 97b3ddd653
commit abb472c83d
303 changed files with 46670 additions and 25369 deletions

View File

@@ -0,0 +1,192 @@
/**
* IosFrame — iPhone设备边框
*
* 参考iPhone 15 Pro393×852 logical pixels
* 含:灵动岛 + 状态栏(时间/信号/电池)+ Home Indicator + 圆角
*
* 用法:
* <IosFrame time="9:41" battery={85}>
* <YourAppContent />
* </IosFrame>
*
* 自定义:
* <IosFrame width={390} height={844} darkMode showKeyboard>
* ...
* </IosFrame>
*/
const iosFrameStyles = {
wrapper: {
display: 'inline-block',
padding: 12,
background: '#000',
borderRadius: 60,
boxShadow: '0 0 0 2px #1f2937, 0 20px 60px rgba(0,0,0,0.3)',
position: 'relative',
},
screen: {
position: 'relative',
borderRadius: 48,
overflow: 'hidden',
background: '#fff',
},
statusBar: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
height: 54,
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
padding: '0 32px 0 32px',
fontSize: 16,
fontWeight: 600,
fontFamily: '-apple-system, "SF Pro Text", sans-serif',
zIndex: 20,
pointerEvents: 'none',
},
dynamicIsland: {
position: 'absolute',
top: 12,
left: '50%',
transform: 'translateX(-50%)',
width: 124,
height: 36,
background: '#000',
borderRadius: 999,
zIndex: 30,
},
statusIcons: {
display: 'flex',
alignItems: 'center',
gap: 6,
},
signalIcon: {
display: 'flex',
alignItems: 'flex-end',
gap: 2,
height: 12,
},
signalBar: {
width: 3,
background: 'currentColor',
borderRadius: 1,
},
wifiIcon: {
width: 16,
height: 12,
position: 'relative',
},
batteryIcon: {
width: 26,
height: 12,
border: '1.5px solid currentColor',
borderRadius: 3,
padding: 1,
position: 'relative',
opacity: 0.8,
},
batteryCap: {
position: 'absolute',
top: 3,
right: -3,
width: 2,
height: 6,
background: 'currentColor',
borderRadius: '0 1px 1px 0',
},
content: {
position: 'absolute',
top: 54,
left: 0,
right: 0,
bottom: 34,
overflow: 'auto',
},
homeIndicator: {
position: 'absolute',
bottom: 10,
left: '50%',
transform: 'translateX(-50%)',
width: 140,
height: 5,
background: 'rgba(0,0,0,0.3)',
borderRadius: 999,
zIndex: 10,
},
homeIndicatorDark: {
background: 'rgba(255,255,255,0.5)',
},
};
function IosFrame({
children,
width = 393,
height = 852,
time = '9:41',
battery = 100,
darkMode = false,
showStatusBar = true,
showDynamicIsland = true,
showHomeIndicator = true,
}) {
const textColor = darkMode ? '#fff' : '#000';
return (
<div style={iosFrameStyles.wrapper}>
<div style={{
...iosFrameStyles.screen,
width,
height,
background: darkMode ? '#000' : '#fff',
}}>
{showStatusBar && (
<div style={{ ...iosFrameStyles.statusBar, color: textColor }}>
<span>{time}</span>
<div style={iosFrameStyles.statusIcons}>
<div style={iosFrameStyles.signalIcon}>
<div style={{ ...iosFrameStyles.signalBar, height: 4 }} />
<div style={{ ...iosFrameStyles.signalBar, height: 6 }} />
<div style={{ ...iosFrameStyles.signalBar, height: 9 }} />
<div style={{ ...iosFrameStyles.signalBar, height: 11 }} />
</div>
<svg width="16" height="12" viewBox="0 0 16 12" fill="none" style={{ color: textColor }}>
<path d="M8 11.5a1 1 0 100-2 1 1 0 000 2z" fill="currentColor" />
<path d="M3 7.5a7 7 0 0110 0" stroke="currentColor" strokeWidth="1.3" fill="none" strokeLinecap="round" />
<path d="M1 4.5a11 11 0 0114 0" stroke="currentColor" strokeWidth="1.3" fill="none" strokeLinecap="round" opacity="0.7" />
</svg>
<div style={iosFrameStyles.batteryIcon}>
<div style={{
width: `${battery}%`,
height: '100%',
background: 'currentColor',
borderRadius: 1,
opacity: 0.9,
}} />
<div style={iosFrameStyles.batteryCap} />
</div>
</div>
</div>
)}
{showDynamicIsland && <div style={iosFrameStyles.dynamicIsland} />}
<div style={iosFrameStyles.content}>
{children}
</div>
{showHomeIndicator && (
<div style={{
...iosFrameStyles.homeIndicator,
...(darkMode ? iosFrameStyles.homeIndicatorDark : {}),
}} />
)}
</div>
</div>
);
}
if (typeof window !== 'undefined') {
window.IosFrame = IosFrame;
}