@rdicons/react-native 0.6.0 → 0.8.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/README.md CHANGED
@@ -47,10 +47,32 @@ That writes one `.tsx` file per icon, with no dependency on this package. (`--fo
47
47
 
48
48
  ## Animation
49
49
 
50
- Animated icons are not in the React Native package yet. The rd icons animate on the web and in the Vue, Svelte and React packages.
50
+ The rd icons can move, with React Native's own `Animated` (no extra library):
51
+
52
+ ```tsx
53
+ import { Bell, Rocket } from '@rdicons/react-native/rd'
54
+
55
+ <Bell animate /> {/* plays once when it appears */}
56
+ <Rocket animate="loop" speed={1.5} /> {/* repeats: loading states */}
57
+
58
+ const ref = useRef<RdIconHandle>(null)
59
+ <Pressable onPress={() => ref.current?.play()}><Bell ref={ref} /></Pressable>
60
+ ```
61
+
62
+ The animation is the same as on the web (all 638 rd icons), and it stops when the device asks for reduced motion. Other libraries ignore `animate`. `@rdicons/react-native/rd-static` is the same library without the animation data, about 60% smaller, for apps that do not animate.
51
63
 
52
64
  ## Licenses
53
65
 
54
66
  The code of this package is MIT. The icons keep the license of their library (MIT, ISC, Apache-2.0, and CC BY 4.0 for Solar, which requires you to credit the author). The `LICENSES` folder has the full text for each library.
55
67
 
68
+
69
+ ## Colour effects
70
+
71
+ ```tsx
72
+ <Folder duotone color="#4f46e5" />
73
+ <Folder gradient={['#ec4899', '#4f46e5']} />
74
+ ```
75
+
76
+ `duotone` fills closed shapes with a soft second tone; `gradient` makes the line run from one color to another. Details: https://rdicons.vimalbhatt.com/docs/effects
77
+
56
78
  Needs React 17+, React Native 0.70+ and `react-native-svg` 13+. ESM, with types. Part of [rdicons](https://rdicons.vimalbhatt.com).
@@ -0,0 +1,210 @@
1
+ // ../core/src/effects.ts
2
+ var ARGS = { m: 2, l: 2, h: 1, v: 1, c: 6, s: 4, q: 4, t: 2, a: 7, z: 0 };
3
+ var NUM = /[-+]?(?:\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?/g;
4
+ function firstSubpath(d) {
5
+ let cur = { x: 0, y: 0 };
6
+ let start = null;
7
+ let closed = false;
8
+ let min = { x: Infinity, y: Infinity };
9
+ let max = { x: -Infinity, y: -Infinity };
10
+ const add = (p) => {
11
+ min = { x: Math.min(min.x, p.x), y: Math.min(min.y, p.y) };
12
+ max = { x: Math.max(max.x, p.x), y: Math.max(max.y, p.y) };
13
+ };
14
+ for (const m of d.matchAll(/([a-zA-Z])([^a-zA-Z]*)/g)) {
15
+ const cmd = m[1];
16
+ const lower = cmd.toLowerCase();
17
+ const rel = cmd === lower;
18
+ if (!(lower in ARGS)) return null;
19
+ if (lower === "z") {
20
+ if (start) {
21
+ closed = true;
22
+ cur = start;
23
+ }
24
+ break;
25
+ }
26
+ if (lower === "m" && start) break;
27
+ const args = m[2];
28
+ let pos = 0;
29
+ const number = () => {
30
+ while (pos < args.length && /[\s,]/.test(args[pos])) pos++;
31
+ const r = /[-+]?(?:\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?/y;
32
+ r.lastIndex = pos;
33
+ const x = r.exec(args);
34
+ if (!x) return null;
35
+ pos = r.lastIndex;
36
+ return parseFloat(x[0]);
37
+ };
38
+ const flag = () => {
39
+ while (pos < args.length && /[\s,]/.test(args[pos])) pos++;
40
+ if (args[pos] !== "0" && args[pos] !== "1") return null;
41
+ return Number(args[pos++]);
42
+ };
43
+ let first = true;
44
+ for (; ; ) {
45
+ const ox = rel ? cur.x : 0, oy = rel ? cur.y : 0;
46
+ if (lower === "a") {
47
+ const rx = number(), ry = number(), rot = number(), f1 = flag(), f2 = flag(), x = number(), y = number();
48
+ if ([rx, ry, rot, f1, f2, x, y].some((v) => v == null)) break;
49
+ const end = { x: ox + x, y: oy + y };
50
+ const mid = { x: (cur.x + end.x) / 2, y: (cur.y + end.y) / 2 };
51
+ add({ x: mid.x - Math.abs(rx), y: mid.y - Math.abs(ry) });
52
+ add({ x: mid.x + Math.abs(rx), y: mid.y + Math.abs(ry) });
53
+ cur = end;
54
+ add(cur);
55
+ } else {
56
+ const a = [];
57
+ for (let k = 0; k < ARGS[lower]; k++) {
58
+ const v = number();
59
+ if (v == null) break;
60
+ a.push(v);
61
+ }
62
+ if (a.length < ARGS[lower]) break;
63
+ switch (lower) {
64
+ case "m": {
65
+ cur = { x: ox + a[0], y: oy + a[1] };
66
+ if (first) start = cur;
67
+ add(cur);
68
+ break;
69
+ }
70
+ case "l":
71
+ case "t": {
72
+ cur = { x: ox + a[0], y: oy + a[1] };
73
+ add(cur);
74
+ break;
75
+ }
76
+ case "h": {
77
+ cur = { x: ox + a[0], y: cur.y };
78
+ add(cur);
79
+ break;
80
+ }
81
+ case "v": {
82
+ cur = { x: cur.x, y: oy + a[0] };
83
+ add(cur);
84
+ break;
85
+ }
86
+ case "c": {
87
+ add({ x: ox + a[0], y: oy + a[1] });
88
+ add({ x: ox + a[2], y: oy + a[3] });
89
+ cur = { x: ox + a[4], y: oy + a[5] };
90
+ add(cur);
91
+ break;
92
+ }
93
+ case "s":
94
+ case "q": {
95
+ add({ x: ox + a[0], y: oy + a[1] });
96
+ cur = { x: ox + a[2], y: oy + a[3] };
97
+ add(cur);
98
+ break;
99
+ }
100
+ }
101
+ }
102
+ first = false;
103
+ }
104
+ if (!start && lower !== "m") return null;
105
+ }
106
+ if (!start || !isFinite(min.x)) return null;
107
+ add(start);
108
+ return { start, end: cur, closed, min, max };
109
+ }
110
+ var attr = (tag, name) => {
111
+ var _a;
112
+ const m = tag.match(new RegExp(`(?:^|\\s)${name}\\s*=\\s*("([^"]*)"|'([^']*)')`));
113
+ return m ? (_a = m[2]) != null ? _a : m[3] : null;
114
+ };
115
+ var num = (v) => v == null ? null : Number.isFinite(parseFloat(v)) ? parseFloat(v) : null;
116
+ var MIN_SIDE = 5;
117
+ function fillableShapes(body) {
118
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
119
+ if (!/stroke=/.test(body)) return [];
120
+ const out = [];
121
+ let i = -1;
122
+ for (const m of body.matchAll(/<(path|circle|ellipse|rect|polygon|line|polyline)\b[^>]*>/g)) {
123
+ i++;
124
+ const tag = m[0];
125
+ const kind = m[1];
126
+ const ownFill = attr(tag, "fill");
127
+ if (ownFill && ownFill !== "none") continue;
128
+ if (kind === "circle") {
129
+ if (((_a = num(attr(tag, "r"))) != null ? _a : 0) * 2 >= MIN_SIDE) out.push(i);
130
+ } else if (kind === "ellipse") {
131
+ if (((_b = num(attr(tag, "rx"))) != null ? _b : 0) * 2 >= MIN_SIDE && ((_c = num(attr(tag, "ry"))) != null ? _c : 0) * 2 >= MIN_SIDE) out.push(i);
132
+ } else if (kind === "rect") {
133
+ if (((_d = num(attr(tag, "width"))) != null ? _d : 0) >= MIN_SIDE && ((_e = num(attr(tag, "height"))) != null ? _e : 0) >= MIN_SIDE) out.push(i);
134
+ } else if (kind === "polygon") {
135
+ const pts = (_h = (_g = ((_f = attr(tag, "points")) != null ? _f : "").match(NUM)) == null ? void 0 : _g.map(Number)) != null ? _h : [];
136
+ const xs = pts.filter((_, k) => k % 2 === 0), ys = pts.filter((_, k) => k % 2 === 1);
137
+ if (xs.length >= 3 && Math.max(...xs) - Math.min(...xs) >= MIN_SIDE && Math.max(...ys) - Math.min(...ys) >= MIN_SIDE) out.push(i);
138
+ } else if (kind === "path") {
139
+ const sp = firstSubpath((_i = attr(tag, "d")) != null ? _i : "");
140
+ if (!sp) continue;
141
+ const w = sp.max.x - sp.min.x, h = sp.max.y - sp.min.y;
142
+ if (w < MIN_SIDE || h < MIN_SIDE) continue;
143
+ const gap = Math.hypot(sp.end.x - sp.start.x, sp.end.y - sp.start.y);
144
+ if (sp.closed || gap <= Math.max(2.5, 0.35 * Math.min(w, h))) out.push(i);
145
+ }
146
+ }
147
+ return out;
148
+ }
149
+ var esc = (s) => s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;");
150
+ var safeColor = (c) => /^[#a-zA-Z0-9(),.%\s\-/]+$/.test(c) ? c : "#000000";
151
+ function gradientLine(w, h, angle = 45) {
152
+ const a = angle * Math.PI / 180;
153
+ const dx = Math.cos(a), dy = Math.sin(a);
154
+ const half = (Math.abs(w * dx) + Math.abs(h * dy)) / 2;
155
+ const cx = w / 2, cy = h / 2;
156
+ const r = (n) => Math.round(n * 100) / 100;
157
+ return { x1: r(cx - dx * half), y1: r(cy - dy * half), x2: r(cx + dx * half), y2: r(cy + dy * half) };
158
+ }
159
+ function applyEffects(body, w, h, base, o) {
160
+ var _a, _b, _c;
161
+ const id = ((_a = o.gradientId) != null ? _a : "rdg").replace(/[^a-zA-Z0-9_-]/g, "");
162
+ const g = o.gradient;
163
+ const paint = g ? `url(#${id})` : base;
164
+ let out = body.replace(/currentColor/g, paint);
165
+ if (o.duotone) {
166
+ const idx = new Set(fillableShapes(body));
167
+ if (idx.size) {
168
+ const fill = o.duotone.color ? safeColor(o.duotone.color) : paint;
169
+ const opacity = Math.min(1, Math.max(0, (_b = o.duotone.opacity) != null ? _b : 0.2));
170
+ let i = -1;
171
+ out = out.replace(/<(path|circle|ellipse|rect|polygon|line|polyline)\b([^>]*?)(\/?)>/g, (whole, tagName, rest, slash) => {
172
+ i++;
173
+ if (!idx.has(i)) return whole;
174
+ const cleaned = rest.replace(/\sfill="[^"]*"/, "");
175
+ return `<${tagName}${cleaned} fill="${esc(fill)}" fill-opacity="${opacity}"${slash}>`;
176
+ });
177
+ }
178
+ }
179
+ if (g) {
180
+ const l = gradientLine(w, h, (_c = g.angle) != null ? _c : 45);
181
+ out = `<defs><linearGradient id="${id}" gradientUnits="userSpaceOnUse" x1="${l.x1}" y1="${l.y1}" x2="${l.x2}" y2="${l.y2}"><stop offset="0" stop-color="${esc(safeColor(g.from))}"/><stop offset="1" stop-color="${esc(safeColor(g.to))}"/></linearGradient></defs>${out}`;
182
+ }
183
+ return out;
184
+ }
185
+ function parseEffectProps(p, gradientId) {
186
+ var _a, _b;
187
+ let duotone = null;
188
+ const d = p.duotone;
189
+ if (d === true || d === "" || d === "true") duotone = {};
190
+ else if (typeof d === "number") duotone = { opacity: d };
191
+ else if (typeof d === "string" && d) duotone = { color: d };
192
+ else if (d && typeof d === "object") duotone = { color: (_a = d.color) != null ? _a : null, opacity: d.opacity };
193
+ let gradient = null;
194
+ const g = p.gradient;
195
+ if (typeof g === "string" && g) {
196
+ const [from, to, angle] = g.split(",").map((x) => x.trim());
197
+ if (from && to) gradient = { from, to, angle: angle !== void 0 && Number.isFinite(Number(angle)) ? Number(angle) : 45 };
198
+ } else if (Array.isArray(g) && g.length >= 2) gradient = { from: String(g[0]), to: String(g[1]), angle: typeof g[2] === "number" ? g[2] : 45 };
199
+ else if (g && typeof g === "object" && "from" in g) gradient = { from: g.from, to: g.to, angle: (_b = g.angle) != null ? _b : 45 };
200
+ if (!duotone && !gradient) return null;
201
+ return { duotone, gradient, gradientId };
202
+ }
203
+ export {
204
+ applyEffects,
205
+ fillableShapes,
206
+ firstSubpath,
207
+ gradientLine,
208
+ parseEffectProps,
209
+ safeColor
210
+ };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  export { createIcon } from './runtime.js'
2
- export const sets = [{"prefix":"rd","label":"rd","total":638,"license":"MIT","author":"rdicons"},{"prefix":"tabler","label":"Tabler","total":6286,"license":"MIT","author":"Paweł Kuna"},{"prefix":"lucide","label":"Lucide","total":1978,"license":"ISC","author":"Lucide Contributors"},{"prefix":"ph","label":"Phosphor","total":9161,"license":"MIT","author":"Phosphor Icons"},{"prefix":"material-symbols","label":"Material Symbols","total":16442,"license":"Apache 2.0","author":"Google"},{"prefix":"fluent","label":"Fluent UI","total":5189,"license":"MIT","author":"Microsoft Corporation"},{"prefix":"heroicons","label":"Heroicons","total":1288,"license":"MIT","author":"Refactoring UI Inc"},{"prefix":"solar","label":"Solar","total":8859,"license":"CC BY 4.0","author":"480 Design"},{"prefix":"hugeicons","label":"Huge Icons","total":6091,"license":"MIT","author":"Hugeicons"},{"prefix":"mingcute","label":"Mingcute","total":3336,"license":"Apache 2.0","author":"MingCute Design"},{"prefix":"bi","label":"Bootstrap","total":2084,"license":"MIT","author":"The Bootstrap Authors"},{"prefix":"carbon","label":"Carbon","total":2776,"license":"Apache 2.0","author":"IBM"},{"prefix":"feather","label":"Feather","total":286,"license":"MIT","author":"Cole Bemis"},{"prefix":"radix-icons","label":"Radix","total":342,"license":"MIT","author":"WorkOS"},{"prefix":"iconoir","label":"Iconoir","total":1682,"license":"MIT","author":"Luca Burgio"},{"prefix":"majesticons","label":"Majesticons","total":1045,"license":"MIT","author":"Gerrit Halfmann"},{"prefix":"octicon","label":"Octicons","total":957,"license":"MIT","author":"GitHub"},{"prefix":"ri","label":"Remix Icon","total":3229,"license":"Apache 2.0","author":"Remix Design"},{"prefix":"mdi","label":"Material Design Icons","total":7638,"license":"Apache 2.0","author":"Pictogrammers"}]
2
+ export const sets = [{"prefix":"rd","label":"rd","total":702,"license":"MIT","author":"rdicons"},{"prefix":"tabler","label":"Tabler","total":6286,"license":"MIT","author":"Paweł Kuna"},{"prefix":"lucide","label":"Lucide","total":1978,"license":"ISC","author":"Lucide Contributors"},{"prefix":"ph","label":"Phosphor","total":9161,"license":"MIT","author":"Phosphor Icons"},{"prefix":"material-symbols","label":"Material Symbols","total":16442,"license":"Apache 2.0","author":"Google"},{"prefix":"fluent","label":"Fluent UI","total":5189,"license":"MIT","author":"Microsoft Corporation"},{"prefix":"heroicons","label":"Heroicons","total":1288,"license":"MIT","author":"Refactoring UI Inc"},{"prefix":"solar","label":"Solar","total":8859,"license":"CC BY 4.0","author":"480 Design"},{"prefix":"hugeicons","label":"Huge Icons","total":6091,"license":"MIT","author":"Hugeicons"},{"prefix":"mingcute","label":"Mingcute","total":3336,"license":"Apache 2.0","author":"MingCute Design"},{"prefix":"bi","label":"Bootstrap","total":2084,"license":"MIT","author":"The Bootstrap Authors"},{"prefix":"carbon","label":"Carbon","total":2776,"license":"Apache 2.0","author":"IBM"},{"prefix":"feather","label":"Feather","total":286,"license":"MIT","author":"Cole Bemis"},{"prefix":"radix-icons","label":"Radix","total":342,"license":"MIT","author":"WorkOS"},{"prefix":"iconoir","label":"Iconoir","total":1682,"license":"MIT","author":"Luca Burgio"},{"prefix":"majesticons","label":"Majesticons","total":1045,"license":"MIT","author":"Gerrit Halfmann"},{"prefix":"octicon","label":"Octicons","total":957,"license":"MIT","author":"GitHub"},{"prefix":"ri","label":"Remix Icon","total":3229,"license":"Apache 2.0","author":"Remix Design"},{"prefix":"mdi","label":"Material Design Icons","total":7638,"license":"Apache 2.0","author":"Pictogrammers"}]
package/dist/motion.js ADDED
@@ -0,0 +1,106 @@
1
+ /**
2
+ * The maths of the rd animations, with no React Native in it: easing curves, and the keyframes of one property turned into a
3
+ * piecewise-linear table (inputRange / outputRange) that Animated.Value.interpolate can play. The easing of each keyframe interval
4
+ * is baked into the table by sampling it, which is how CSS applies it too (per interval, not over the whole animation).
5
+ */
6
+
7
+ /** cubic-bezier(x1, y1, x2, y2) as a function of time (0..1) to progress */
8
+ export function bezier(x1, y1, x2, y2) {
9
+ const cx = 3 * x1, bx = 3 * (x2 - x1) - cx, ax = 1 - cx - bx
10
+ const cy = 3 * y1, by = 3 * (y2 - y1) - cy, ay = 1 - cy - by
11
+ const sx = (t) => ((ax * t + bx) * t + cx) * t
12
+ const sy = (t) => ((ay * t + by) * t + cy) * t
13
+ const dx = (t) => (3 * ax * t + 2 * bx) * t + cx
14
+ return (x) => {
15
+ if (x <= 0) return 0
16
+ if (x >= 1) return 1
17
+ let t = x
18
+ for (let i = 0; i < 8; i++) {
19
+ const e = sx(t) - x
20
+ if (Math.abs(e) < 1e-6) return sy(t)
21
+ const d = dx(t)
22
+ if (Math.abs(d) < 1e-6) break
23
+ t -= e / d
24
+ }
25
+ let lo = 0, hi = 1
26
+ t = x
27
+ while (lo < hi) {
28
+ const e = sx(t)
29
+ if (Math.abs(e - x) < 1e-6) break
30
+ if (x > e) lo = t
31
+ else hi = t
32
+ t = (hi + lo) / 2
33
+ if (hi - lo < 1e-7) break
34
+ }
35
+ return sy(t)
36
+ }
37
+ }
38
+
39
+ const IO = bezier(0.42, 0, 0.58, 1)
40
+ const OUT = bezier(0, 0, 0.58, 1)
41
+
42
+ /** 'io' | 'o' | 'l' | 's' | [x1, y1, x2, y2] to an easing function */
43
+ export function easing(e) {
44
+ if (e === 'io') return IO
45
+ if (e === 'o') return OUT
46
+ if (e === 'l') return (u) => u
47
+ if (e === 's') return (u) => (u >= 1 ? 1 : 0) // steps(1, end)
48
+ if (Array.isArray(e)) return bezier(e[0], e[1], e[2], e[3])
49
+ return IO
50
+ }
51
+
52
+ const resolve = (v, vars) => (v !== null && typeof v === 'object' ? v.s * (vars.s ?? 1) : v)
53
+
54
+ /**
55
+ * The values of one property over the animation, as { inputRange, outputRange } for Animated.Value.interpolate.
56
+ * frames = [[offset, { tx, ty, r, sx, sy, o, d }], ...] key = 'tx' | 'ty' | 'r' | 'sx' | 'sy' | 'o' | 'd'
57
+ * vars = the element's custom properties ({ s })
58
+ * Returns null when no keyframe sets the property.
59
+ */
60
+ export function trackOf(frames, key, ease, vars = {}, samples = 12) {
61
+ const own = frames.filter(([, f]) => key in f)
62
+ if (!own.length) return null
63
+ const fn = easing(ease)
64
+ const input = []
65
+ const output = []
66
+ const push = (x, y) => {
67
+ if (input.length && x <= input[input.length - 1]) x = input[input.length - 1] + 1e-6 // strictly increasing, as interpolate needs
68
+ input.push(x)
69
+ output.push(y)
70
+ }
71
+ push(own[0][0], resolve(own[0][1][key], vars))
72
+ for (let i = 1; i < own.length; i++) {
73
+ const [o0, f0] = own[i - 1]
74
+ const [o1, f1] = own[i]
75
+ const v0 = resolve(f0[key], vars)
76
+ const v1 = resolve(f1[key], vars)
77
+ if (ease === 's') {
78
+ // steps(1, end): hold the value of this keyframe until the next one, then jump
79
+ push(o1 - 1e-5, v0)
80
+ push(o1, v1)
81
+ continue
82
+ }
83
+ const n = ease === 'l' || v0 === v1 ? 1 : samples
84
+ for (let s = 1; s <= n; s++) {
85
+ const u = s / n
86
+ push(o0 + (o1 - o0) * u, v0 + (v1 - v0) * fn(u))
87
+ }
88
+ }
89
+ if (input[0] > 0) { input.unshift(0); output.unshift(output[0]) }
90
+ if (input[input.length - 1] < 1) { input.push(1); output.push(output[output.length - 1]) }
91
+ return { inputRange: input, outputRange: output }
92
+ }
93
+
94
+ /** Evaluates a table at progress u (what interpolate does), for tests and for non-animated previews. */
95
+ export function sample(track, u) {
96
+ const { inputRange: x, outputRange: y } = track
97
+ if (u <= x[0]) return y[0]
98
+ if (u >= x[x.length - 1]) return y[y.length - 1]
99
+ let i = 1
100
+ while (x[i] < u) i++
101
+ const t = (u - x[i - 1]) / (x[i] - x[i - 1])
102
+ return y[i - 1] + (y[i] - y[i - 1]) * t
103
+ }
104
+
105
+ /** Delay in seconds of one animation for an element: the fixed part plus the per-index part (--k), which staggers lists of strokes. */
106
+ export const delayOf = (a, vars = {}) => (a.l ?? 0) + (a.lk ?? 0) * (vars.k ?? 0)