react-native-figma-squircle
Version:
Figma-flavored squircles for React Native
143 lines (139 loc) • 5.32 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.SquircleView = SquircleView;
Object.defineProperty(exports, "getSvgPath", {
enumerable: true,
get: function () {
return _figmaSquircle.getSvgPath;
}
});
var _react = _interopRequireWildcard(require("react"));
var React = _react;
var _reactNative = require("react-native");
var _reactNativeSvg = _interopRequireWildcard(require("react-native-svg"));
var _figmaSquircle = require("figma-squircle");
var _jsxRuntime = require("react/jsx-runtime");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function SquircleView({
squircleParams,
children,
...rest
}) {
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
...rest,
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(SquircleBackground, {
...squircleParams
}), children]
});
}
function SquircleBackground({
cornerRadius = 0,
topLeftCornerRadius,
topRightCornerRadius,
bottomRightCornerRadius,
bottomLeftCornerRadius,
cornerSmoothing,
fillColor = '#000',
strokeColor = '#000',
strokeWidth = 0
}) {
return /*#__PURE__*/(0, _jsxRuntime.jsx)(Rect, {
style: _reactNative.StyleSheet.absoluteFill,
children: ({
width,
height
}) => {
const hasStroke = strokeWidth > 0;
if (!hasStroke) {
const squirclePath = (0, _figmaSquircle.getSvgPath)({
width,
height,
cornerSmoothing,
cornerRadius,
topLeftCornerRadius,
topRightCornerRadius,
bottomRightCornerRadius,
bottomLeftCornerRadius
});
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.default, {
width: "100%",
height: "100%",
viewBox: `0 0 ${width} ${height}`,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.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 = (0, _figmaSquircle.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__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.default, {
width: "100%",
height: "100%",
viewBox: `0 0 ${width} ${height}`,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.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] = (0, _react.useState)(null);
const ref = (0, _react.useRef)(null);
(0, _react.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__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
ref: ref,
...rest,
children: rect ? children(rect) : null
});
}
function isSyncLayoutAccessAvailable() {
if (_reactNative.Platform.OS === 'web') {
return true;
}
return globalThis.RN$Bridgeless === true;
}
//# sourceMappingURL=index.js.map