react-native-skia-box-shadow 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +147 -0
- package/lib/commonjs/Shadow.js +245 -0
- package/lib/commonjs/Shadow.js.map +1 -0
- package/lib/commonjs/index.js +26 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/types.js +6 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/module/Shadow.js +240 -0
- package/lib/module/Shadow.js.map +1 -0
- package/lib/module/index.js +4 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/types.js +4 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/Shadow.d.ts +54 -0
- package/lib/typescript/Shadow.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +3 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +79 -0
- package/lib/typescript/types.d.ts.map +1 -0
- package/package.json +81 -0
- package/src/Shadow.tsx +260 -0
- package/src/index.ts +7 -0
- package/src/types.ts +78 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import React, { useMemo, useState } from 'react';
|
|
4
|
+
import { StyleSheet, View, PixelRatio } from 'react-native';
|
|
5
|
+
import { Canvas, Group, RoundedRect, Rect, Circle, Path, Blur, Skia } from '@shopify/react-native-skia';
|
|
6
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
7
|
+
// ── Defaults (mirrors ShadowDefaults.kt) ───────────────────────
|
|
8
|
+
const DEFAULTS = {
|
|
9
|
+
fillStyle: {
|
|
10
|
+
kind: 'color',
|
|
11
|
+
color: 'rgba(0,0,0,0.10)'
|
|
12
|
+
},
|
|
13
|
+
blurRadius: 24,
|
|
14
|
+
spread: 4,
|
|
15
|
+
offsetX: 0,
|
|
16
|
+
offsetY: 0
|
|
17
|
+
};
|
|
18
|
+
const pixelRatio = PixelRatio.get();
|
|
19
|
+
|
|
20
|
+
// ── Single shadow layer renderer ────────────────────────────────
|
|
21
|
+
const ShadowLayer = ({
|
|
22
|
+
params,
|
|
23
|
+
width,
|
|
24
|
+
height,
|
|
25
|
+
defaultShape
|
|
26
|
+
}) => {
|
|
27
|
+
const {
|
|
28
|
+
fillStyle = DEFAULTS.fillStyle,
|
|
29
|
+
blurRadius = DEFAULTS.blurRadius,
|
|
30
|
+
spread = DEFAULTS.spread,
|
|
31
|
+
offsetX = DEFAULTS.offsetX,
|
|
32
|
+
offsetY = DEFAULTS.offsetY,
|
|
33
|
+
shape: shapeOverride
|
|
34
|
+
} = params;
|
|
35
|
+
const shape = shapeOverride ?? defaultShape;
|
|
36
|
+
|
|
37
|
+
// ── Paint ─────────────────────────────────────────────────────
|
|
38
|
+
const paint = useMemo(() => {
|
|
39
|
+
const p = Skia.Paint();
|
|
40
|
+
if (fillStyle.kind === 'color') {
|
|
41
|
+
p.setColor(Skia.Color(fillStyle.color));
|
|
42
|
+
} else {
|
|
43
|
+
p.setShader(fillStyle.factory(width, height));
|
|
44
|
+
}
|
|
45
|
+
return p;
|
|
46
|
+
}, [fillStyle, width, height]);
|
|
47
|
+
|
|
48
|
+
// ── Shadow sizing (spread) ────────────────────────────────────
|
|
49
|
+
const shadowWidth = width + spread * 2;
|
|
50
|
+
const shadowHeight = height + spread * 2;
|
|
51
|
+
const scaleX = width > 0 ? shadowWidth / width : 1;
|
|
52
|
+
const scaleY = height > 0 ? shadowHeight / height : 1;
|
|
53
|
+
|
|
54
|
+
// ── Blur (adjusted for pixel density) ─────────────────────────
|
|
55
|
+
const adjustedBlur = blurRadius / pixelRatio;
|
|
56
|
+
const blurChild = adjustedBlur > 0 ? /*#__PURE__*/_jsx(Blur, {
|
|
57
|
+
blur: adjustedBlur
|
|
58
|
+
}) : null;
|
|
59
|
+
|
|
60
|
+
// ── Shape element (with Blur as child) ────────────────────────
|
|
61
|
+
const shapeElement = useMemo(() => {
|
|
62
|
+
switch (shape.kind) {
|
|
63
|
+
case 'roundedRect':
|
|
64
|
+
return /*#__PURE__*/_jsx(RoundedRect, {
|
|
65
|
+
x: 0,
|
|
66
|
+
y: 0,
|
|
67
|
+
width: width,
|
|
68
|
+
height: height,
|
|
69
|
+
r: shape.radius,
|
|
70
|
+
paint: paint,
|
|
71
|
+
children: blurChild
|
|
72
|
+
});
|
|
73
|
+
case 'circle':
|
|
74
|
+
{
|
|
75
|
+
const r = Math.min(width, height) / 2;
|
|
76
|
+
return /*#__PURE__*/_jsx(Circle, {
|
|
77
|
+
cx: width / 2,
|
|
78
|
+
cy: height / 2,
|
|
79
|
+
r: r,
|
|
80
|
+
paint: paint,
|
|
81
|
+
children: blurChild
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
case 'path':
|
|
85
|
+
return /*#__PURE__*/_jsx(Path, {
|
|
86
|
+
path: shape.svgPath,
|
|
87
|
+
paint: paint,
|
|
88
|
+
children: blurChild
|
|
89
|
+
});
|
|
90
|
+
case 'rect':
|
|
91
|
+
default:
|
|
92
|
+
return /*#__PURE__*/_jsx(Rect, {
|
|
93
|
+
x: 0,
|
|
94
|
+
y: 0,
|
|
95
|
+
width: width,
|
|
96
|
+
height: height,
|
|
97
|
+
paint: paint,
|
|
98
|
+
children: blurChild
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}, [shape, width, height, paint, blurChild]);
|
|
102
|
+
return /*#__PURE__*/_jsx(Group, {
|
|
103
|
+
transform: [{
|
|
104
|
+
translateX: offsetX
|
|
105
|
+
}, {
|
|
106
|
+
translateY: offsetY
|
|
107
|
+
}],
|
|
108
|
+
children: /*#__PURE__*/_jsx(Group, {
|
|
109
|
+
transform: [{
|
|
110
|
+
scaleX
|
|
111
|
+
}, {
|
|
112
|
+
scaleY
|
|
113
|
+
}],
|
|
114
|
+
origin: {
|
|
115
|
+
x: width / 2,
|
|
116
|
+
y: height / 2
|
|
117
|
+
},
|
|
118
|
+
children: shapeElement
|
|
119
|
+
})
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* `<Shadow>` — CSS-style box shadows for React Native.
|
|
125
|
+
*
|
|
126
|
+
* Renders one or more blurred, colored shadows behind `children`.
|
|
127
|
+
* Supports blur, spread, offset, custom colors/shaders, and
|
|
128
|
+
* arbitrary shapes (rect, roundedRect, circle, SVG path).
|
|
129
|
+
*
|
|
130
|
+
* Powered by `@shopify/react-native-skia`.
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```tsx
|
|
134
|
+
* import { Shadow } from 'react-native-skia-box-shadow';
|
|
135
|
+
*
|
|
136
|
+
* <Shadow
|
|
137
|
+
* shadows={{
|
|
138
|
+
* fillStyle: { kind: 'color', color: 'rgba(0,0,0,0.15)' },
|
|
139
|
+
* blurRadius: 20,
|
|
140
|
+
* offsetY: 4,
|
|
141
|
+
* }}
|
|
142
|
+
* shape={{ kind: 'roundedRect', radius: 16 }}
|
|
143
|
+
* >
|
|
144
|
+
* <View style={styles.card}>
|
|
145
|
+
* <Text>Card with shadow</Text>
|
|
146
|
+
* </View>
|
|
147
|
+
* </Shadow>
|
|
148
|
+
* ```
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```tsx
|
|
152
|
+
* // Multiple shadow layers
|
|
153
|
+
* <Shadow
|
|
154
|
+
* shadows={[
|
|
155
|
+
* { blurRadius: 4, offsetY: 2, fillStyle: { kind: 'color', color: 'rgba(0,0,0,0.08)' } },
|
|
156
|
+
* { blurRadius: 16, offsetY: 8, fillStyle: { kind: 'color', color: 'rgba(0,0,0,0.12)' } },
|
|
157
|
+
* ]}
|
|
158
|
+
* shape={{ kind: 'roundedRect', radius: 12 }}
|
|
159
|
+
* >
|
|
160
|
+
* {children}
|
|
161
|
+
* </Shadow>
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
const Shadow = ({
|
|
165
|
+
shadows,
|
|
166
|
+
shape = {
|
|
167
|
+
kind: 'rect'
|
|
168
|
+
},
|
|
169
|
+
width: _width,
|
|
170
|
+
height: _height,
|
|
171
|
+
style,
|
|
172
|
+
children
|
|
173
|
+
}) => {
|
|
174
|
+
const [layout, setLayout] = useState(null);
|
|
175
|
+
const onLayout = e => {
|
|
176
|
+
const {
|
|
177
|
+
width,
|
|
178
|
+
height
|
|
179
|
+
} = e.nativeEvent.layout;
|
|
180
|
+
setLayout({
|
|
181
|
+
width,
|
|
182
|
+
height
|
|
183
|
+
});
|
|
184
|
+
};
|
|
185
|
+
const width = _width ?? layout?.width ?? 0;
|
|
186
|
+
const height = _height ?? layout?.height ?? 0;
|
|
187
|
+
const shadowList = Array.isArray(shadows) ? shadows : [shadows];
|
|
188
|
+
|
|
189
|
+
// ── Compute canvas padding ────────────────────────────────────
|
|
190
|
+
// The canvas must be large enough to contain blurred + spread +
|
|
191
|
+
// offset shadows without clipping.
|
|
192
|
+
const canvasPadding = useMemo(() => {
|
|
193
|
+
let maxExtent = 0;
|
|
194
|
+
for (const s of shadowList) {
|
|
195
|
+
const blur = s.blurRadius ?? DEFAULTS.blurRadius;
|
|
196
|
+
const spread = s.spread ?? DEFAULTS.spread;
|
|
197
|
+
const ox = Math.abs(s.offsetX ?? DEFAULTS.offsetX);
|
|
198
|
+
const oy = Math.abs(s.offsetY ?? DEFAULTS.offsetY);
|
|
199
|
+
const extent = blur * 3 + spread + Math.max(ox, oy);
|
|
200
|
+
if (extent > maxExtent) maxExtent = extent;
|
|
201
|
+
}
|
|
202
|
+
return Math.ceil(maxExtent);
|
|
203
|
+
}, [shadowList]);
|
|
204
|
+
const hasSize = width > 0 && height > 0;
|
|
205
|
+
return /*#__PURE__*/_jsxs(View, {
|
|
206
|
+
style: [styles.container, style],
|
|
207
|
+
onLayout: onLayout,
|
|
208
|
+
children: [hasSize && /*#__PURE__*/_jsx(Canvas, {
|
|
209
|
+
style: [styles.canvas, {
|
|
210
|
+
top: -canvasPadding,
|
|
211
|
+
left: -canvasPadding,
|
|
212
|
+
width: width + canvasPadding * 2,
|
|
213
|
+
height: height + canvasPadding * 2
|
|
214
|
+
}],
|
|
215
|
+
children: /*#__PURE__*/_jsx(Group, {
|
|
216
|
+
transform: [{
|
|
217
|
+
translateX: canvasPadding
|
|
218
|
+
}, {
|
|
219
|
+
translateY: canvasPadding
|
|
220
|
+
}],
|
|
221
|
+
children: shadowList.map((params, idx) => /*#__PURE__*/_jsx(ShadowLayer, {
|
|
222
|
+
params: params,
|
|
223
|
+
width: width,
|
|
224
|
+
height: height,
|
|
225
|
+
defaultShape: shape
|
|
226
|
+
}, idx))
|
|
227
|
+
})
|
|
228
|
+
}), children]
|
|
229
|
+
});
|
|
230
|
+
};
|
|
231
|
+
const styles = StyleSheet.create({
|
|
232
|
+
container: {},
|
|
233
|
+
canvas: {
|
|
234
|
+
position: 'absolute',
|
|
235
|
+
pointerEvents: 'none'
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
export default Shadow;
|
|
239
|
+
export { Shadow, DEFAULTS as ShadowDefaults };
|
|
240
|
+
//# sourceMappingURL=Shadow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","useMemo","useState","StyleSheet","View","PixelRatio","Canvas","Group","RoundedRect","Rect","Circle","Path","Blur","Skia","jsx","_jsx","jsxs","_jsxs","DEFAULTS","fillStyle","kind","color","blurRadius","spread","offsetX","offsetY","pixelRatio","get","ShadowLayer","params","width","height","defaultShape","shape","shapeOverride","paint","p","Paint","setColor","Color","setShader","factory","shadowWidth","shadowHeight","scaleX","scaleY","adjustedBlur","blurChild","blur","shapeElement","x","y","r","radius","children","Math","min","cx","cy","path","svgPath","transform","translateX","translateY","origin","Shadow","shadows","_width","_height","style","layout","setLayout","onLayout","e","nativeEvent","shadowList","Array","isArray","canvasPadding","maxExtent","s","ox","abs","oy","extent","max","ceil","hasSize","styles","container","canvas","top","left","map","idx","create","position","pointerEvents","ShadowDefaults"],"sourceRoot":"../../src","sources":["Shadow.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["default","Shadow","ShadowView","ShadowDefaults"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA,SAASA,OAAO,IAAIC,MAAM,EAAEA,MAAM,IAAIC,UAAU,EAAEC,cAAc,QAAQ,UAAU","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"../../src","sources":["types.ts"],"mappings":"","ignoreList":[]}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ShadowProps, ShadowFillStyle } from './types';
|
|
3
|
+
declare const DEFAULTS: {
|
|
4
|
+
readonly fillStyle: ShadowFillStyle;
|
|
5
|
+
readonly blurRadius: 24;
|
|
6
|
+
readonly spread: 4;
|
|
7
|
+
readonly offsetX: 0;
|
|
8
|
+
readonly offsetY: 0;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* `<Shadow>` — CSS-style box shadows for React Native.
|
|
12
|
+
*
|
|
13
|
+
* Renders one or more blurred, colored shadows behind `children`.
|
|
14
|
+
* Supports blur, spread, offset, custom colors/shaders, and
|
|
15
|
+
* arbitrary shapes (rect, roundedRect, circle, SVG path).
|
|
16
|
+
*
|
|
17
|
+
* Powered by `@shopify/react-native-skia`.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* import { Shadow } from 'react-native-skia-box-shadow';
|
|
22
|
+
*
|
|
23
|
+
* <Shadow
|
|
24
|
+
* shadows={{
|
|
25
|
+
* fillStyle: { kind: 'color', color: 'rgba(0,0,0,0.15)' },
|
|
26
|
+
* blurRadius: 20,
|
|
27
|
+
* offsetY: 4,
|
|
28
|
+
* }}
|
|
29
|
+
* shape={{ kind: 'roundedRect', radius: 16 }}
|
|
30
|
+
* >
|
|
31
|
+
* <View style={styles.card}>
|
|
32
|
+
* <Text>Card with shadow</Text>
|
|
33
|
+
* </View>
|
|
34
|
+
* </Shadow>
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```tsx
|
|
39
|
+
* // Multiple shadow layers
|
|
40
|
+
* <Shadow
|
|
41
|
+
* shadows={[
|
|
42
|
+
* { blurRadius: 4, offsetY: 2, fillStyle: { kind: 'color', color: 'rgba(0,0,0,0.08)' } },
|
|
43
|
+
* { blurRadius: 16, offsetY: 8, fillStyle: { kind: 'color', color: 'rgba(0,0,0,0.12)' } },
|
|
44
|
+
* ]}
|
|
45
|
+
* shape={{ kind: 'roundedRect', radius: 12 }}
|
|
46
|
+
* >
|
|
47
|
+
* {children}
|
|
48
|
+
* </Shadow>
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
declare const Shadow: React.FC<ShadowProps>;
|
|
52
|
+
export default Shadow;
|
|
53
|
+
export { Shadow, DEFAULTS as ShadowDefaults };
|
|
54
|
+
//# sourceMappingURL=Shadow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Shadow.d.ts","sourceRoot":"","sources":["../../src/Shadow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAkBjD,OAAO,KAAK,EACV,WAAW,EAGX,eAAe,EAChB,MAAM,SAAS,CAAC;AAGjB,QAAA,MAAM,QAAQ;wBAC+C,eAAe;;;;;CAKlE,CAAC;AAkGX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,QAAA,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CA6EjC,CAAC;AAUF,eAAe,MAAM,CAAC;AACtB,OAAO,EAAE,MAAM,EAAE,QAAQ,IAAI,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,IAAI,UAAU,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AACnF,YAAY,EACV,WAAW,EACX,YAAY,EACZ,WAAW,EACX,eAAe,GAChB,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { ViewStyle, StyleProp } from 'react-native';
|
|
3
|
+
/**
|
|
4
|
+
* Fill style for shadow — solid color or a Skia shader factory.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* // Solid color
|
|
8
|
+
* { kind: 'color', color: 'rgba(0,0,0,0.12)' }
|
|
9
|
+
*
|
|
10
|
+
* // Linear gradient
|
|
11
|
+
* {
|
|
12
|
+
* kind: 'shader',
|
|
13
|
+
* factory: (w, h) => Skia.Shader.MakeLinearGradient(
|
|
14
|
+
* { x: 0, y: 0 }, { x: w, y: h },
|
|
15
|
+
* [Skia.Color('#6366F1'), Skia.Color('#EC4899')],
|
|
16
|
+
* null, 0,
|
|
17
|
+
* ),
|
|
18
|
+
* }
|
|
19
|
+
*/
|
|
20
|
+
export type ShadowFillStyle = {
|
|
21
|
+
kind: 'color';
|
|
22
|
+
color: string;
|
|
23
|
+
} | {
|
|
24
|
+
kind: 'shader';
|
|
25
|
+
factory: (width: number, height: number) => import('@shopify/react-native-skia').SkShader;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Single shadow layer descriptor.
|
|
29
|
+
* All numeric values are in device-independent points.
|
|
30
|
+
*/
|
|
31
|
+
export interface ShadowParams {
|
|
32
|
+
/** Fill style: solid color string or shader factory. Default: black @ 10% */
|
|
33
|
+
fillStyle?: ShadowFillStyle;
|
|
34
|
+
/** Gaussian blur radius (in points, Figma-compatible). Default: 24 */
|
|
35
|
+
blurRadius?: number;
|
|
36
|
+
/** Expands the shadow outline beyond element bounds. Default: 4 */
|
|
37
|
+
spread?: number;
|
|
38
|
+
/** Horizontal offset. Default: 0 */
|
|
39
|
+
offsetX?: number;
|
|
40
|
+
/** Vertical offset. Default: 0 */
|
|
41
|
+
offsetY?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Shape override for this specific shadow layer.
|
|
44
|
+
* When undefined, inherits `shape` from the parent `<Shadow>`.
|
|
45
|
+
*/
|
|
46
|
+
shape?: ShadowShape;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Supported shadow shapes.
|
|
50
|
+
*/
|
|
51
|
+
export type ShadowShape = {
|
|
52
|
+
kind: 'rect';
|
|
53
|
+
} | {
|
|
54
|
+
kind: 'roundedRect';
|
|
55
|
+
radius: number;
|
|
56
|
+
} | {
|
|
57
|
+
kind: 'circle';
|
|
58
|
+
} | {
|
|
59
|
+
kind: 'path';
|
|
60
|
+
svgPath: string;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Props for the `<Shadow>` component.
|
|
64
|
+
*/
|
|
65
|
+
export interface ShadowProps {
|
|
66
|
+
/** One or more shadow layers. */
|
|
67
|
+
shadows: ShadowParams | ShadowParams[];
|
|
68
|
+
/** Default shape applied to shadows that don't specify their own. Default: rect */
|
|
69
|
+
shape?: ShadowShape;
|
|
70
|
+
/** Explicit component width. If omitted, measured via onLayout. */
|
|
71
|
+
width?: number;
|
|
72
|
+
/** Explicit component height. If omitted, measured via onLayout. */
|
|
73
|
+
height?: number;
|
|
74
|
+
/** RN style for the outer container. */
|
|
75
|
+
style?: StyleProp<ViewStyle>;
|
|
76
|
+
/** Content rendered above the shadow. */
|
|
77
|
+
children?: ReactNode;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChC;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,CACP,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,KACX,OAAO,4BAA4B,EAAE,QAAQ,CAAC;CACpD,CAAC;AAEN;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,6EAA6E;IAC7E,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,iCAAiC;IACjC,OAAO,EAAE,YAAY,GAAG,YAAY,EAAE,CAAC;IACvC,mFAAmF;IACnF,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,yCAAyC;IACzC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB"}
|
package/package.json
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-native-skia-box-shadow",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CSS-style box shadows for React Native — blur, spread, offset, colors, gradients, and arbitrary shapes. Powered by @shopify/react-native-skia.",
|
|
5
|
+
"main": "lib/commonjs/index.js",
|
|
6
|
+
"module": "lib/module/index.js",
|
|
7
|
+
"types": "lib/typescript/index.d.ts",
|
|
8
|
+
"source": "src/index.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"src",
|
|
11
|
+
"lib",
|
|
12
|
+
"!**/__tests__",
|
|
13
|
+
"!**/__fixtures__",
|
|
14
|
+
"!**/__mocks__"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "bob build",
|
|
18
|
+
"typecheck": "tsc --noEmit",
|
|
19
|
+
"lint": "eslint \"src/**/*.{ts,tsx}\"",
|
|
20
|
+
"clean": "rm -rf lib",
|
|
21
|
+
"prepare": "bob build"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"react-native",
|
|
25
|
+
"skia",
|
|
26
|
+
"shadow",
|
|
27
|
+
"box-shadow",
|
|
28
|
+
"drop-shadow",
|
|
29
|
+
"blur",
|
|
30
|
+
"spread",
|
|
31
|
+
"ios",
|
|
32
|
+
"android",
|
|
33
|
+
"react-native-skia"
|
|
34
|
+
],
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "git+https://github.com/nickstetsiuk/react-native-skia-box-shadow.git"
|
|
38
|
+
},
|
|
39
|
+
"author": {
|
|
40
|
+
"name": "Vasyl Stetsiuk",
|
|
41
|
+
"url": "https://stetsiuk.dev"
|
|
42
|
+
},
|
|
43
|
+
"license": "MIT",
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://github.com/nickstetsiuk/react-native-skia-box-shadow/issues"
|
|
46
|
+
},
|
|
47
|
+
"homepage": "https://github.com/nickstetsiuk/react-native-skia-box-shadow#readme",
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"@shopify/react-native-skia": ">=1.0.0",
|
|
50
|
+
"react": ">=18.0.0",
|
|
51
|
+
"react-native": ">=0.71.0"
|
|
52
|
+
},
|
|
53
|
+
"peerDependenciesMeta": {
|
|
54
|
+
"@shopify/react-native-skia": {
|
|
55
|
+
"optional": false
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@shopify/react-native-skia": "^1.11.0",
|
|
60
|
+
"@types/react": "^18.2.0",
|
|
61
|
+
"@types/react-native": "^0.72.0",
|
|
62
|
+
"react": "^18.2.0",
|
|
63
|
+
"react-native": "^0.75.0",
|
|
64
|
+
"react-native-builder-bob": "^0.30.0",
|
|
65
|
+
"typescript": "^5.4.0"
|
|
66
|
+
},
|
|
67
|
+
"react-native-builder-bob": {
|
|
68
|
+
"source": "src",
|
|
69
|
+
"output": "lib",
|
|
70
|
+
"targets": [
|
|
71
|
+
"commonjs",
|
|
72
|
+
"module",
|
|
73
|
+
[
|
|
74
|
+
"typescript",
|
|
75
|
+
{
|
|
76
|
+
"project": "tsconfig.build.json"
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
}
|