@syraui/core 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/dist/index.mjs ADDED
@@ -0,0 +1,232 @@
1
+ import { useRef, useLayoutEffect } from 'react';
2
+ import { jsx } from 'react/jsx-runtime';
3
+
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __objRest = (source, exclude) => {
8
+ var target = {};
9
+ for (var prop in source)
10
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
11
+ target[prop] = source[prop];
12
+ if (source != null && __getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(source)) {
14
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
15
+ target[prop] = source[prop];
16
+ }
17
+ return target;
18
+ };
19
+ var _injected = false;
20
+ function injectKeyframes() {
21
+ if (_injected || typeof document === "undefined") return;
22
+ _injected = true;
23
+ const el = document.createElement("style");
24
+ el.textContent = `
25
+ @keyframes _sx { 0% { background-position: 100% 50% } 100% { background-position: 0% 50% } }
26
+ @keyframes _sx-rtl { 0% { background-position: 0% 50% } 100% { background-position: 100% 50% } }
27
+ @keyframes _sx-pulse { 0%, 100% { opacity: 1 } 50% { opacity: 0.45 } }
28
+ @keyframes _sx-fadein { from { opacity: 0 } to { opacity: 1 } }
29
+ [data-sx] * { visibility: hidden !important; }
30
+ [data-sx-cover] { background: transparent !important; background-image: none !important; }
31
+ .syra-fadein { animation: _sx-fadein var(--sx-fade, 250ms) ease-out forwards; }
32
+ `;
33
+ document.head.appendChild(el);
34
+ }
35
+ var MEDIA = /* @__PURE__ */ new Set(["img", "svg", "video", "picture", "canvas"]);
36
+ var LEAF = /* @__PURE__ */ new Set(["button", "input", "textarea", "select"]);
37
+ var TEXT = /* @__PURE__ */ new Set([
38
+ "p",
39
+ "span",
40
+ "h1",
41
+ "h2",
42
+ "h3",
43
+ "h4",
44
+ "h5",
45
+ "h6",
46
+ "label",
47
+ "li",
48
+ "a",
49
+ "strong",
50
+ "em",
51
+ "small",
52
+ "time",
53
+ "code"
54
+ ]);
55
+ function classify(el) {
56
+ var _a, _b;
57
+ const tag = el.tagName.toLowerCase();
58
+ const cs = window.getComputedStyle(el);
59
+ if (cs.display === "none") return "skip";
60
+ const rect = el.getBoundingClientRect();
61
+ if (rect.width < 2 || rect.height < 2) return "skip";
62
+ if (MEDIA.has(tag)) return "media";
63
+ if (LEAF.has(tag)) return "leaf";
64
+ if (TEXT.has(tag)) {
65
+ const hasVisibleChildren = Array.from(el.children).some(
66
+ (c) => window.getComputedStyle(c).display !== "none"
67
+ );
68
+ return hasVisibleChildren ? "cover" : "leaf";
69
+ }
70
+ if (!el.children.length && ((_a = el.textContent) == null ? void 0 : _a.trim())) return "leaf";
71
+ const bgImg = cs.backgroundImage;
72
+ if (bgImg && bgImg !== "none") return "leaf";
73
+ const cls = (_b = el.className) != null ? _b : "";
74
+ if (typeof cls === "string" && (cls.includes("bg-gradient") || cls.includes("from-")))
75
+ return "leaf";
76
+ if (!el.children.length) {
77
+ const bg = cs.backgroundColor;
78
+ if (bg && bg !== "rgba(0, 0, 0, 0)" && bg !== "transparent") return "leaf";
79
+ }
80
+ return "cover";
81
+ }
82
+ var SAVED = /* @__PURE__ */ new WeakMap();
83
+ function saveEl(el) {
84
+ var _a;
85
+ SAVED.set(el, {
86
+ style: (_a = el.getAttribute("style")) != null ? _a : "",
87
+ src: el.src,
88
+ srcset: el.srcset
89
+ });
90
+ }
91
+ function restoreAll(tagged, fade, fadeDuration) {
92
+ var _a;
93
+ tagged.forEach((el) => {
94
+ var _a2;
95
+ el.removeAttribute("data-sx");
96
+ el.removeAttribute("data-sx-cover");
97
+ const saved = SAVED.get(el);
98
+ if (!saved) return;
99
+ const h = el;
100
+ if (el.tagName.toLowerCase() === "img" && saved.src) {
101
+ el.src = saved.src;
102
+ el.srcset = (_a2 = saved.srcset) != null ? _a2 : "";
103
+ }
104
+ saved.style ? h.setAttribute("style", saved.style) : h.removeAttribute("style");
105
+ SAVED.delete(el);
106
+ });
107
+ if (!fade || tagged.length === 0 || fadeDuration <= 0) return;
108
+ const root = (_a = tagged[0]) == null ? void 0 : _a.closest("[aria-busy]");
109
+ if (!root) return;
110
+ root.style.setProperty("--sx-fade", `${fadeDuration}ms`);
111
+ root.classList.add("syra-fadein");
112
+ root.addEventListener(
113
+ "animationend",
114
+ () => {
115
+ root.classList.remove("syra-fadein");
116
+ root.style.removeProperty("--sx-fade");
117
+ },
118
+ { once: true }
119
+ );
120
+ }
121
+ function shimmerStyle(base, hl, speed, br, anim, dir) {
122
+ const base_props = [
123
+ `color: transparent`,
124
+ `overflow: hidden`,
125
+ `border-radius: ${br}`
126
+ ];
127
+ if (anim === "pulse")
128
+ return [
129
+ ...base_props,
130
+ `background: ${base}`,
131
+ `animation: _sx-pulse ${speed}s ease-in-out infinite`
132
+ ].join("; ");
133
+ if (anim === "none") return [...base_props, `background: ${base}`].join("; ");
134
+ const kf = dir === "rtl" ? "_sx-rtl" : "_sx";
135
+ const pos = dir === "rtl" ? "0% 50%" : "100% 50%";
136
+ return [
137
+ ...base_props,
138
+ `background: linear-gradient(90deg, ${base} 0%, ${base} 30%, ${hl} 50%, ${base} 70%, ${base} 100%)`,
139
+ `background-size: 300% 100%`,
140
+ `background-position: ${pos}`,
141
+ `animation: ${kf} ${speed}s ease-in-out infinite`
142
+ ].join("; ");
143
+ }
144
+ function applyAll(root, theme) {
145
+ var _a, _b, _c, _d, _e, _f, _g;
146
+ const tagged = [];
147
+ const base = (_a = theme.baseColor) != null ? _a : "#EAECF0";
148
+ const hl = (_b = theme.highlightColor) != null ? _b : "#F8F9FB";
149
+ const speed = (_c = theme.speed) != null ? _c : 1.8;
150
+ const anim = (_d = theme.animation) != null ? _d : "shimmer";
151
+ const dir = (_e = theme.direction) != null ? _e : "ltr";
152
+ const defaultBr = typeof theme.borderRadius === "number" ? `${theme.borderRadius}px` : (_f = theme.borderRadius) != null ? _f : "6px";
153
+ const textBr = typeof theme.borderRadius === "number" ? `${theme.borderRadius}px` : (_g = theme.borderRadius) != null ? _g : "4px";
154
+ function walk(el) {
155
+ const type = classify(el);
156
+ if (type === "skip") return;
157
+ const h = el;
158
+ if (type === "media") {
159
+ const cs = window.getComputedStyle(el);
160
+ const rect = el.getBoundingClientRect();
161
+ const isCircle = Math.abs(rect.width - rect.height) < 4 && parseInt(cs.borderRadius) >= rect.width / 2 - 2;
162
+ const br = isCircle ? "50%" : cs.borderRadius !== "0px" ? cs.borderRadius : defaultBr;
163
+ saveEl(el);
164
+ if (el.tagName.toLowerCase() === "img") {
165
+ el.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
166
+ el.srcset = "";
167
+ }
168
+ el.setAttribute("data-sx", "");
169
+ h.style.cssText = shimmerStyle(base, hl, speed, br, anim, dir);
170
+ tagged.push(el);
171
+ return;
172
+ }
173
+ if (type === "leaf") {
174
+ const cs = window.getComputedStyle(el);
175
+ const tag = el.tagName.toLowerCase();
176
+ const br = cs.borderRadius !== "0px" ? cs.borderRadius : TEXT.has(tag) ? textBr : defaultBr;
177
+ saveEl(el);
178
+ el.setAttribute("data-sx", "");
179
+ h.style.cssText = shimmerStyle(base, hl, speed, br, anim, dir);
180
+ tagged.push(el);
181
+ return;
182
+ }
183
+ saveEl(el);
184
+ el.setAttribute("data-sx-cover", "");
185
+ h.style.setProperty("background", "transparent", "important");
186
+ h.style.setProperty("background-image", "none", "important");
187
+ tagged.push(el);
188
+ Array.from(el.children).forEach(walk);
189
+ }
190
+ Array.from(root.children).forEach((card) => {
191
+ const type = classify(card);
192
+ if (type === "skip") return;
193
+ if (type === "media" || type === "leaf") {
194
+ walk(card);
195
+ return;
196
+ }
197
+ tagged.push(card);
198
+ Array.from(card.children).forEach(walk);
199
+ });
200
+ return tagged;
201
+ }
202
+ function Skeleton(_a) {
203
+ var _b = _a, {
204
+ loading,
205
+ children,
206
+ className,
207
+ style
208
+ } = _b, theme = __objRest(_b, [
209
+ "loading",
210
+ "children",
211
+ "className",
212
+ "style"
213
+ ]);
214
+ injectKeyframes();
215
+ const wrapRef = useRef(null);
216
+ const taggedRef = useRef([]);
217
+ const prevRef = useRef(null);
218
+ useLayoutEffect(() => {
219
+ var _a2;
220
+ const el = wrapRef.current;
221
+ if (!el || prevRef.current === loading) return;
222
+ prevRef.current = loading;
223
+ restoreAll(taggedRef.current, !loading, (_a2 = theme.fadeDuration) != null ? _a2 : 250);
224
+ taggedRef.current = [];
225
+ if (loading) taggedRef.current = applyAll(el, theme);
226
+ });
227
+ return /* @__PURE__ */ jsx("div", { ref: wrapRef, className, style, "aria-busy": loading, children });
228
+ }
229
+
230
+ export { Skeleton };
231
+ //# sourceMappingURL=index.mjs.map
232
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/skeleton/Skeleton.web.tsx"],"names":["_a"],"mappings":"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","file":"index.mjs","sourcesContent":["\"use client\";\n\nimport {\n useLayoutEffect,\n useRef,\n type CSSProperties,\n type ReactNode,\n} from \"react\";\nimport type { SkeletonTheme } from \"../types/skeleton\";\n\nlet _injected = false;\n\nfunction injectKeyframes() {\n if (_injected || typeof document === \"undefined\") return;\n _injected = true;\n const el = document.createElement(\"style\");\n el.textContent = `\n @keyframes _sx { 0% { background-position: 100% 50% } 100% { background-position: 0% 50% } }\n @keyframes _sx-rtl { 0% { background-position: 0% 50% } 100% { background-position: 100% 50% } }\n @keyframes _sx-pulse { 0%, 100% { opacity: 1 } 50% { opacity: 0.45 } }\n @keyframes _sx-fadein { from { opacity: 0 } to { opacity: 1 } }\n [data-sx] * { visibility: hidden !important; }\n [data-sx-cover] { background: transparent !important; background-image: none !important; }\n .syra-fadein { animation: _sx-fadein var(--sx-fade, 250ms) ease-out forwards; }\n `;\n document.head.appendChild(el);\n}\n\nconst MEDIA = new Set([\"img\", \"svg\", \"video\", \"picture\", \"canvas\"]);\nconst LEAF = new Set([\"button\", \"input\", \"textarea\", \"select\"]);\nconst TEXT = new Set([\n \"p\",\n \"span\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"h5\",\n \"h6\",\n \"label\",\n \"li\",\n \"a\",\n \"strong\",\n \"em\",\n \"small\",\n \"time\",\n \"code\",\n]);\n\ntype ElType = \"media\" | \"leaf\" | \"cover\" | \"skip\";\n\nfunction classify(el: Element): ElType {\n const tag = el.tagName.toLowerCase();\n const cs = window.getComputedStyle(el);\n if (cs.display === \"none\") return \"skip\";\n const rect = el.getBoundingClientRect();\n if (rect.width < 2 || rect.height < 2) return \"skip\";\n if (MEDIA.has(tag)) return \"media\";\n if (LEAF.has(tag)) return \"leaf\";\n if (TEXT.has(tag)) {\n const hasVisibleChildren = Array.from(el.children).some(\n (c) => window.getComputedStyle(c).display !== \"none\",\n );\n return hasVisibleChildren ? \"cover\" : \"leaf\";\n }\n if (!el.children.length && el.textContent?.trim()) return \"leaf\";\n\n // Element with a background-image (gradient, url) — treat as leaf\n // Works for both CSS classes (Tailwind bg-*) and inline styles\n const bgImg = cs.backgroundImage;\n if (bgImg && bgImg !== \"none\") return \"leaf\";\n\n // Tailwind gradient classes use background-image — catch them via className\n // e.g. bg-gradient-to-r, from-*, via-*, to-*\n const cls = (el as HTMLElement).className ?? \"\";\n if (\n typeof cls === \"string\" &&\n (cls.includes(\"bg-gradient\") || cls.includes(\"from-\"))\n )\n return \"leaf\";\n\n // Non-transparent background-color with no children = decorative block (banner, divider)\n if (!el.children.length) {\n const bg = cs.backgroundColor;\n if (bg && bg !== \"rgba(0, 0, 0, 0)\" && bg !== \"transparent\") return \"leaf\";\n }\n\n return \"cover\";\n}\n\ninterface Saved {\n style: string;\n src?: string;\n srcset?: string;\n}\nconst SAVED = new WeakMap<Element, Saved>();\n\nfunction saveEl(el: Element) {\n SAVED.set(el, {\n style: (el as HTMLElement).getAttribute(\"style\") ?? \"\",\n src: (el as HTMLImageElement).src,\n srcset: (el as HTMLImageElement).srcset,\n });\n}\n\nfunction restoreAll(tagged: Element[], fade: boolean, fadeDuration: number) {\n tagged.forEach((el) => {\n el.removeAttribute(\"data-sx\");\n el.removeAttribute(\"data-sx-cover\");\n const saved = SAVED.get(el);\n if (!saved) return;\n const h = el as HTMLElement;\n if (el.tagName.toLowerCase() === \"img\" && saved.src) {\n (el as HTMLImageElement).src = saved.src;\n (el as HTMLImageElement).srcset = saved.srcset ?? \"\";\n }\n saved.style\n ? h.setAttribute(\"style\", saved.style)\n : h.removeAttribute(\"style\");\n SAVED.delete(el);\n });\n if (!fade || tagged.length === 0 || fadeDuration <= 0) return;\n const root = tagged[0]?.closest(\"[aria-busy]\") as HTMLElement | null;\n if (!root) return;\n root.style.setProperty(\"--sx-fade\", `${fadeDuration}ms`);\n root.classList.add(\"syra-fadein\");\n root.addEventListener(\n \"animationend\",\n () => {\n root.classList.remove(\"syra-fadein\");\n root.style.removeProperty(\"--sx-fade\");\n },\n { once: true },\n );\n}\n\nfunction shimmerStyle(\n base: string,\n hl: string,\n speed: number,\n br: string,\n anim: \"shimmer\" | \"pulse\" | \"none\",\n dir: \"ltr\" | \"rtl\",\n): string {\n const base_props = [\n `color: transparent`,\n `overflow: hidden`,\n `border-radius: ${br}`,\n ];\n if (anim === \"pulse\")\n return [\n ...base_props,\n `background: ${base}`,\n `animation: _sx-pulse ${speed}s ease-in-out infinite`,\n ].join(\"; \");\n if (anim === \"none\") return [...base_props, `background: ${base}`].join(\"; \");\n const kf = dir === \"rtl\" ? \"_sx-rtl\" : \"_sx\";\n const pos = dir === \"rtl\" ? \"0% 50%\" : \"100% 50%\";\n return [\n ...base_props,\n `background: linear-gradient(90deg, ${base} 0%, ${base} 30%, ${hl} 50%, ${base} 70%, ${base} 100%)`,\n `background-size: 300% 100%`,\n `background-position: ${pos}`,\n `animation: ${kf} ${speed}s ease-in-out infinite`,\n ].join(\"; \");\n}\n\nfunction applyAll(root: HTMLElement, theme: SkeletonTheme): Element[] {\n const tagged: Element[] = [];\n const base = theme.baseColor ?? \"#EAECF0\";\n const hl = theme.highlightColor ?? \"#F8F9FB\";\n const speed = theme.speed ?? 1.8;\n const anim = theme.animation ?? \"shimmer\";\n const dir = theme.direction ?? \"ltr\";\n const defaultBr =\n typeof theme.borderRadius === \"number\"\n ? `${theme.borderRadius}px`\n : (theme.borderRadius ?? \"6px\");\n const textBr =\n typeof theme.borderRadius === \"number\"\n ? `${theme.borderRadius}px`\n : (theme.borderRadius ?? \"4px\");\n\n function walk(el: Element) {\n const type = classify(el);\n if (type === \"skip\") return;\n const h = el as HTMLElement;\n\n if (type === \"media\") {\n const cs = window.getComputedStyle(el);\n const rect = el.getBoundingClientRect();\n const isCircle =\n Math.abs(rect.width - rect.height) < 4 &&\n parseInt(cs.borderRadius) >= rect.width / 2 - 2;\n const br = isCircle\n ? \"50%\"\n : cs.borderRadius !== \"0px\"\n ? cs.borderRadius\n : defaultBr;\n saveEl(el);\n if (el.tagName.toLowerCase() === \"img\") {\n (el as HTMLImageElement).src =\n \"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\";\n (el as HTMLImageElement).srcset = \"\";\n }\n el.setAttribute(\"data-sx\", \"\");\n h.style.cssText = shimmerStyle(base, hl, speed, br, anim, dir);\n tagged.push(el);\n return;\n }\n\n if (type === \"leaf\") {\n const cs = window.getComputedStyle(el);\n const tag = el.tagName.toLowerCase();\n const br =\n cs.borderRadius !== \"0px\"\n ? cs.borderRadius\n : TEXT.has(tag)\n ? textBr\n : defaultBr;\n saveEl(el);\n el.setAttribute(\"data-sx\", \"\");\n h.style.cssText = shimmerStyle(base, hl, speed, br, anim, dir);\n tagged.push(el);\n return;\n }\n\n saveEl(el);\n el.setAttribute(\"data-sx-cover\", \"\");\n h.style.setProperty(\"background\", \"transparent\", \"important\");\n h.style.setProperty(\"background-image\", \"none\", \"important\");\n tagged.push(el);\n Array.from(el.children).forEach(walk);\n }\n\n Array.from(root.children).forEach((card) => {\n const type = classify(card);\n if (type === \"skip\") return;\n if (type === \"media\" || type === \"leaf\") {\n walk(card);\n return;\n }\n tagged.push(card);\n Array.from(card.children).forEach(walk);\n });\n\n return tagged;\n}\n\nexport interface SkeletonProps extends SkeletonTheme {\n loading: boolean;\n children: ReactNode;\n className?: string;\n style?: CSSProperties;\n}\n\nexport function Skeleton({\n loading,\n children,\n className,\n style,\n ...theme\n}: SkeletonProps) {\n injectKeyframes();\n\n const wrapRef = useRef<HTMLDivElement>(null);\n const taggedRef = useRef<Element[]>([]);\n const prevRef = useRef<boolean | null>(null);\n\n useLayoutEffect(() => {\n const el = wrapRef.current;\n if (!el || prevRef.current === loading) return;\n prevRef.current = loading;\n restoreAll(taggedRef.current, !loading, theme.fadeDuration ?? 250);\n taggedRef.current = [];\n if (loading) taggedRef.current = applyAll(el, theme);\n });\n\n return (\n <div ref={wrapRef} className={className} style={style} aria-busy={loading}>\n {children}\n </div>\n );\n}\n"]}
@@ -0,0 +1,54 @@
1
+ import React from 'react';
2
+ import { ViewStyle } from 'react-native';
3
+
4
+ interface SkeletonTheme {
5
+ baseColor?: string;
6
+ highlightColor?: string;
7
+ speed?: number;
8
+ animation?: "shimmer" | "pulse" | "none";
9
+ borderRadius?: string | number;
10
+ fadeDuration?: number;
11
+ direction?: "ltr" | "rtl";
12
+ }
13
+ interface SkeletonBlock {
14
+ x: number;
15
+ y: number;
16
+ width: number;
17
+ height: number;
18
+ borderRadius: number;
19
+ }
20
+
21
+ interface SkeletonItemProps {
22
+ /** The element to shimmer. Its style is read automatically. */
23
+ children: React.ReactElement;
24
+ /** Override border radius. Defaults to the child's style borderRadius. */
25
+ borderRadius?: number;
26
+ }
27
+ /**
28
+ * Marks an element to be shimmer'd by the parent `<Skeleton>`.
29
+ * Reads dimensions directly from the child's style — no duplication needed.
30
+ *
31
+ * @example
32
+ * <Skeleton loading={loading}>
33
+ * <View style={s.card}>
34
+ * <SkeletonItem><Image source={...} style={s.avatar} /></SkeletonItem>
35
+ * <SkeletonItem><Text style={s.name}>{name}</Text></SkeletonItem>
36
+ * </View>
37
+ * </Skeleton>
38
+ */
39
+ declare function SkeletonItem({ children, borderRadius: brOverride, }: SkeletonItemProps): React.JSX.Element;
40
+ interface NativeSkeletonProps extends SkeletonTheme {
41
+ /** Toggle between skeleton and real content. */
42
+ loading: boolean;
43
+ /** Your component — wrap elements to shimmer with `<SkeletonItem>`. */
44
+ children: React.ReactNode;
45
+ /** Optional style for the outer container. */
46
+ style?: ViewStyle;
47
+ }
48
+ /**
49
+ * Wraps a component and renders shimmer blocks over elements
50
+ * marked with `<SkeletonItem>`.
51
+ */
52
+ declare function Skeleton({ loading, children, style, ...theme }: NativeSkeletonProps): React.JSX.Element;
53
+
54
+ export { type NativeSkeletonProps, Skeleton, type SkeletonBlock, SkeletonItem, type SkeletonItemProps, type SkeletonTheme };
@@ -0,0 +1,54 @@
1
+ import React from 'react';
2
+ import { ViewStyle } from 'react-native';
3
+
4
+ interface SkeletonTheme {
5
+ baseColor?: string;
6
+ highlightColor?: string;
7
+ speed?: number;
8
+ animation?: "shimmer" | "pulse" | "none";
9
+ borderRadius?: string | number;
10
+ fadeDuration?: number;
11
+ direction?: "ltr" | "rtl";
12
+ }
13
+ interface SkeletonBlock {
14
+ x: number;
15
+ y: number;
16
+ width: number;
17
+ height: number;
18
+ borderRadius: number;
19
+ }
20
+
21
+ interface SkeletonItemProps {
22
+ /** The element to shimmer. Its style is read automatically. */
23
+ children: React.ReactElement;
24
+ /** Override border radius. Defaults to the child's style borderRadius. */
25
+ borderRadius?: number;
26
+ }
27
+ /**
28
+ * Marks an element to be shimmer'd by the parent `<Skeleton>`.
29
+ * Reads dimensions directly from the child's style — no duplication needed.
30
+ *
31
+ * @example
32
+ * <Skeleton loading={loading}>
33
+ * <View style={s.card}>
34
+ * <SkeletonItem><Image source={...} style={s.avatar} /></SkeletonItem>
35
+ * <SkeletonItem><Text style={s.name}>{name}</Text></SkeletonItem>
36
+ * </View>
37
+ * </Skeleton>
38
+ */
39
+ declare function SkeletonItem({ children, borderRadius: brOverride, }: SkeletonItemProps): React.JSX.Element;
40
+ interface NativeSkeletonProps extends SkeletonTheme {
41
+ /** Toggle between skeleton and real content. */
42
+ loading: boolean;
43
+ /** Your component — wrap elements to shimmer with `<SkeletonItem>`. */
44
+ children: React.ReactNode;
45
+ /** Optional style for the outer container. */
46
+ style?: ViewStyle;
47
+ }
48
+ /**
49
+ * Wraps a component and renders shimmer blocks over elements
50
+ * marked with `<SkeletonItem>`.
51
+ */
52
+ declare function Skeleton({ loading, children, style, ...theme }: NativeSkeletonProps): React.JSX.Element;
53
+
54
+ export { type NativeSkeletonProps, Skeleton, type SkeletonBlock, SkeletonItem, type SkeletonItemProps, type SkeletonTheme };
@@ -0,0 +1,273 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+ var reactNative = require('react-native');
5
+
6
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
+
8
+ var React__default = /*#__PURE__*/_interopDefault(React);
9
+
10
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
11
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
12
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
13
+ var __objRest = (source, exclude) => {
14
+ var target = {};
15
+ for (var prop in source)
16
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
17
+ target[prop] = source[prop];
18
+ if (source != null && __getOwnPropSymbols)
19
+ for (var prop of __getOwnPropSymbols(source)) {
20
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
21
+ target[prop] = source[prop];
22
+ }
23
+ return target;
24
+ };
25
+ function ShimmerBlock({
26
+ block,
27
+ theme,
28
+ progress,
29
+ containerWidth
30
+ }) {
31
+ var _a, _b, _c, _d, _e;
32
+ const base = (_a = theme.baseColor) != null ? _a : "#EAECF0";
33
+ const highlight = (_b = theme.highlightColor) != null ? _b : "#F8F9FB";
34
+ const anim = (_c = theme.animation) != null ? _c : "shimmer";
35
+ const br = typeof theme.borderRadius === "number" ? theme.borderRadius : (_d = block.borderRadius) != null ? _d : 6;
36
+ if (anim === "pulse") {
37
+ return /* @__PURE__ */ React__default.default.createElement(
38
+ reactNative.Animated.View,
39
+ {
40
+ style: {
41
+ position: "absolute",
42
+ top: block.y,
43
+ left: block.x,
44
+ width: block.width,
45
+ height: block.height,
46
+ borderRadius: br,
47
+ backgroundColor: base,
48
+ opacity: progress.interpolate({
49
+ inputRange: [0, 0.5, 1],
50
+ outputRange: [1, 0.4, 1]
51
+ })
52
+ }
53
+ }
54
+ );
55
+ }
56
+ if (anim === "none") {
57
+ return /* @__PURE__ */ React__default.default.createElement(
58
+ reactNative.View,
59
+ {
60
+ style: {
61
+ position: "absolute",
62
+ top: block.y,
63
+ left: block.x,
64
+ width: block.width,
65
+ height: block.height,
66
+ borderRadius: br,
67
+ backgroundColor: base
68
+ }
69
+ }
70
+ );
71
+ }
72
+ const dir = (_e = theme.direction) != null ? _e : "ltr";
73
+ const translateX = progress.interpolate({
74
+ inputRange: [0, 1],
75
+ outputRange: dir === "rtl" ? [containerWidth, -containerWidth] : [-containerWidth, containerWidth]
76
+ });
77
+ return /* @__PURE__ */ React__default.default.createElement(
78
+ reactNative.View,
79
+ {
80
+ style: {
81
+ position: "absolute",
82
+ top: block.y,
83
+ left: block.x,
84
+ width: block.width,
85
+ height: block.height,
86
+ borderRadius: br,
87
+ backgroundColor: base,
88
+ overflow: "hidden"
89
+ }
90
+ },
91
+ /* @__PURE__ */ React__default.default.createElement(
92
+ reactNative.Animated.View,
93
+ {
94
+ style: [
95
+ reactNative.StyleSheet.absoluteFill,
96
+ {
97
+ backgroundColor: highlight,
98
+ opacity: 0.7,
99
+ transform: [{ translateX }]
100
+ }
101
+ ]
102
+ }
103
+ )
104
+ );
105
+ }
106
+ var SkeletonContext = React__default.default.createContext(null);
107
+ var sx = reactNative.StyleSheet.create({
108
+ hidden: { opacity: 0 },
109
+ visible: { opacity: 1 }
110
+ });
111
+ function SkeletonItem({
112
+ children,
113
+ borderRadius: brOverride
114
+ }) {
115
+ var _a, _b, _c, _d;
116
+ const ctx = React__default.default.useContext(SkeletonContext);
117
+ const wrapRef = React.useRef(null);
118
+ const childProps = children.props;
119
+ const flatStyle = Array.isArray(childProps.style) ? Object.assign({}, ...childProps.style) : (_a = childProps.style) != null ? _a : {};
120
+ const br = (_b = brOverride != null ? brOverride : flatStyle.borderRadius) != null ? _b : 6;
121
+ const measure = React.useCallback(() => {
122
+ if (!ctx) return;
123
+ const self = wrapRef.current;
124
+ const container = ctx.containerRef.current;
125
+ if (!self || !container) return;
126
+ self.measureLayout(
127
+ container,
128
+ (x, y, width, height) => {
129
+ if (width > 1 && height > 1)
130
+ ctx.register({ x, y, width, height, borderRadius: br });
131
+ },
132
+ () => {
133
+ }
134
+ );
135
+ }, [ctx, br]);
136
+ React.useEffect(() => {
137
+ if (!(ctx == null ? void 0 : ctx.loading)) return;
138
+ const t = setTimeout(measure, 50);
139
+ return () => clearTimeout(t);
140
+ }, [ctx == null ? void 0 : ctx.loading, measure]);
141
+ const loading = (_c = ctx == null ? void 0 : ctx.loading) != null ? _c : false;
142
+ const base = (_d = ctx == null ? void 0 : ctx.theme.baseColor) != null ? _d : "#EAECF0";
143
+ return /* @__PURE__ */ React__default.default.createElement(
144
+ reactNative.View,
145
+ {
146
+ ref: wrapRef,
147
+ collapsable: false,
148
+ onLayout: measure,
149
+ style: flatStyle
150
+ },
151
+ /* @__PURE__ */ React__default.default.createElement(reactNative.View, { style: loading ? sx.hidden : sx.visible }, children),
152
+ loading && /* @__PURE__ */ React__default.default.createElement(
153
+ reactNative.View,
154
+ {
155
+ pointerEvents: "none",
156
+ style: [
157
+ reactNative.StyleSheet.absoluteFill,
158
+ { backgroundColor: base, borderRadius: br }
159
+ ]
160
+ }
161
+ )
162
+ );
163
+ }
164
+ function Skeleton(_a) {
165
+ var _b = _a, {
166
+ loading,
167
+ children,
168
+ style
169
+ } = _b, theme = __objRest(_b, [
170
+ "loading",
171
+ "children",
172
+ "style"
173
+ ]);
174
+ var _a2;
175
+ const progress = React.useRef(new reactNative.Animated.Value(0)).current;
176
+ const animRef = React.useRef(null);
177
+ const containerRef = React.useRef(null);
178
+ const blocksMapRef = React.useRef(/* @__PURE__ */ new Map());
179
+ const childrenKeyRef = React.useRef("");
180
+ const [blocks, setBlocks] = React.useState([]);
181
+ const [containerWidth, setContainerWidth] = React.useState(320);
182
+ const register = React.useCallback((block) => {
183
+ const key = `${Math.round(block.x)}-${Math.round(block.y)}-${Math.round(block.width)}-${Math.round(block.height)}`;
184
+ blocksMapRef.current.set(key, block);
185
+ setBlocks(Array.from(blocksMapRef.current.values()));
186
+ }, []);
187
+ React.useEffect(() => {
188
+ const key = React__default.default.Children.count(children).toString();
189
+ if (childrenKeyRef.current !== key) {
190
+ childrenKeyRef.current = key;
191
+ blocksMapRef.current.clear();
192
+ setBlocks([]);
193
+ }
194
+ });
195
+ React.useEffect(() => {
196
+ var _a3, _b2, _c;
197
+ if (!loading) {
198
+ (_a3 = animRef.current) == null ? void 0 : _a3.stop();
199
+ return;
200
+ }
201
+ progress.setValue(0);
202
+ (_b2 = animRef.current) == null ? void 0 : _b2.stop();
203
+ animRef.current = reactNative.Animated.loop(
204
+ reactNative.Animated.timing(progress, {
205
+ toValue: 1,
206
+ duration: ((_c = theme.speed) != null ? _c : 1.8) * 1e3,
207
+ easing: reactNative.Easing.inOut(reactNative.Easing.ease),
208
+ useNativeDriver: true
209
+ })
210
+ );
211
+ animRef.current.start();
212
+ return () => {
213
+ var _a4;
214
+ (_a4 = animRef.current) == null ? void 0 : _a4.stop();
215
+ };
216
+ }, [loading, theme.speed, theme.animation, progress]);
217
+ return /* @__PURE__ */ React__default.default.createElement(
218
+ SkeletonContext.Provider,
219
+ {
220
+ value: { loading, containerRef, register, theme }
221
+ },
222
+ /* @__PURE__ */ React__default.default.createElement(
223
+ reactNative.View,
224
+ {
225
+ ref: containerRef,
226
+ style: [{ position: "relative" }, style],
227
+ onLayout: (e) => setContainerWidth(e.nativeEvent.layout.width),
228
+ accessible: true,
229
+ accessibilityLabel: loading ? "Loading" : void 0
230
+ },
231
+ children,
232
+ loading && blocks.length > 0 && /* @__PURE__ */ React__default.default.createElement(
233
+ reactNative.View,
234
+ {
235
+ style: reactNative.StyleSheet.absoluteFill,
236
+ pointerEvents: "none",
237
+ accessibilityRole: "progressbar"
238
+ },
239
+ blocks.map((block, i) => /* @__PURE__ */ React__default.default.createElement(
240
+ ShimmerBlock,
241
+ {
242
+ key: i,
243
+ block,
244
+ theme,
245
+ progress,
246
+ containerWidth
247
+ }
248
+ ))
249
+ ),
250
+ loading && blocks.length === 0 && /* @__PURE__ */ React__default.default.createElement(reactNative.View, { style: reactNative.StyleSheet.absoluteFill, pointerEvents: "none" }, /* @__PURE__ */ React__default.default.createElement(
251
+ reactNative.Animated.View,
252
+ {
253
+ style: [
254
+ reactNative.StyleSheet.absoluteFill,
255
+ {
256
+ backgroundColor: (_a2 = theme.baseColor) != null ? _a2 : "#EAECF0",
257
+ borderRadius: typeof theme.borderRadius === "number" ? theme.borderRadius : 6,
258
+ opacity: progress.interpolate({
259
+ inputRange: [0, 0.5, 1],
260
+ outputRange: [0.4, 0.9, 0.4]
261
+ })
262
+ }
263
+ ]
264
+ }
265
+ ))
266
+ )
267
+ );
268
+ }
269
+
270
+ exports.Skeleton = Skeleton;
271
+ exports.SkeletonItem = SkeletonItem;
272
+ //# sourceMappingURL=index.js.map
273
+ //# sourceMappingURL=index.js.map