UNPKG

react-native-figma-squircle

Version:
132 lines (128 loc) 4.02 kB
"use strict"; import * as React from 'react'; import { View, StyleSheet, Platform } from 'react-native'; import { useState, useRef, useLayoutEffect } from 'react'; import Svg, { Path } from 'react-native-svg'; import { getSvgPath } from 'figma-squircle'; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; function SquircleView({ squircleParams, children, ...rest }) { return /*#__PURE__*/_jsxs(View, { ...rest, children: [/*#__PURE__*/_jsx(SquircleBackground, { ...squircleParams }), children] }); } function SquircleBackground({ cornerRadius = 0, topLeftCornerRadius, topRightCornerRadius, bottomRightCornerRadius, bottomLeftCornerRadius, cornerSmoothing, fillColor = '#000', strokeColor = '#000', strokeWidth = 0 }) { return /*#__PURE__*/_jsx(Rect, { style: StyleSheet.absoluteFill, children: ({ width, height }) => { const hasStroke = strokeWidth > 0; if (!hasStroke) { const squirclePath = getSvgPath({ width, height, cornerSmoothing, cornerRadius, topLeftCornerRadius, topRightCornerRadius, bottomRightCornerRadius, bottomLeftCornerRadius }); return /*#__PURE__*/_jsx(Svg, { width: "100%", height: "100%", viewBox: `0 0 ${width} ${height}`, children: /*#__PURE__*/_jsx(Path, { d: squirclePath, fill: fillColor }) }); } else { const cornerRadii = [cornerRadius, topLeftCornerRadius, topRightCornerRadius, bottomLeftCornerRadius, bottomRightCornerRadius].filter(cornerRadius => cornerRadius && cornerRadius > 0); const maxStrokeWidth = Math.min(...cornerRadii); strokeWidth = Math.min(strokeWidth, maxStrokeWidth); const insetAmount = strokeWidth / 2; const insetSquirclePath = getSvgPath({ width: width - strokeWidth, height: height - strokeWidth, cornerSmoothing, cornerRadius: getInnerRadius(cornerRadius, insetAmount), topLeftCornerRadius: getInnerRadius(topLeftCornerRadius, insetAmount), topRightCornerRadius: getInnerRadius(topRightCornerRadius, insetAmount), bottomRightCornerRadius: getInnerRadius(bottomRightCornerRadius, insetAmount), bottomLeftCornerRadius: getInnerRadius(bottomLeftCornerRadius, insetAmount) }); return /*#__PURE__*/_jsx(Svg, { width: "100%", height: "100%", viewBox: `0 0 ${width} ${height}`, children: /*#__PURE__*/_jsx(Path, { d: insetSquirclePath, fill: fillColor, stroke: strokeColor, strokeWidth: strokeWidth, translate: insetAmount }) }); } } }); } function getInnerRadius(radius, insetAmount) { if (radius) { return Math.max(0, radius - insetAmount); } return radius; } // Inspired by https://reach.tech/rect/ function Rect({ children, ...rest }) { const [rect, setRect] = useState(null); const ref = useRef(null); useLayoutEffect(() => { if (!isSyncLayoutAccessAvailable()) { throw new Error("This library requires React Native's new architecture."); } // TODO: Maybe use `getBoundingClientRect` instead when it's stable https://gist.github.com/lunaleaps/148756563999c83220887757f2e549a3#file-tooltip-uselayouteffect-js-L77 // From my testing, `measureInWindow` is still faster than `unstable_getBoundingClientRect` ref.current?.measureInWindow((_x, _y, width, height) => { setRect({ width, height }); }); }, []); return /*#__PURE__*/_jsx(View, { ref: ref, ...rest, children: rect ? children(rect) : null }); } function isSyncLayoutAccessAvailable() { if (Platform.OS === 'web') { return true; } return globalThis.RN$Bridgeless === true; } export { SquircleView, getSvgPath }; //# sourceMappingURL=index.js.map