@fanvue/ui 1.14.1 → 1.15.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/cjs/components/Skeleton/Skeleton.cjs +61 -0
- package/dist/cjs/components/Skeleton/Skeleton.cjs.map +1 -0
- package/dist/cjs/index.cjs +2 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/components/Skeleton/Skeleton.mjs +44 -0
- package/dist/components/Skeleton/Skeleton.mjs.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -1
- package/dist/styles/theme.css +27 -0
- package/package.json +1 -1
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
5
|
+
const React = require("react");
|
|
6
|
+
const cn = require("../../utils/cn.cjs");
|
|
7
|
+
function _interopNamespaceDefault(e) {
|
|
8
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
9
|
+
if (e) {
|
|
10
|
+
for (const k in e) {
|
|
11
|
+
if (k !== "default") {
|
|
12
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
13
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
get: () => e[k]
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
n.default = e;
|
|
21
|
+
return Object.freeze(n);
|
|
22
|
+
}
|
|
23
|
+
const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
|
|
24
|
+
const VARIANT_CLASSES = {
|
|
25
|
+
text: "rounded my-0.5",
|
|
26
|
+
circular: "rounded-full",
|
|
27
|
+
rectangular: "",
|
|
28
|
+
rounded: "rounded-lg"
|
|
29
|
+
};
|
|
30
|
+
const Skeleton = React__namespace.forwardRef(
|
|
31
|
+
({ className, variant = "text", animation = "pulse", width, height, style, children, ...props }, ref) => {
|
|
32
|
+
const hasChildren = React__namespace.Children.count(children) > 0;
|
|
33
|
+
const sizeStyle = {
|
|
34
|
+
...style,
|
|
35
|
+
...width !== void 0 && { width: typeof width === "number" ? `${width}px` : width },
|
|
36
|
+
...height !== void 0 && { height: typeof height === "number" ? `${height}px` : height }
|
|
37
|
+
};
|
|
38
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
39
|
+
"span",
|
|
40
|
+
{
|
|
41
|
+
ref,
|
|
42
|
+
"aria-hidden": "true",
|
|
43
|
+
className: cn.cn(
|
|
44
|
+
"block bg-neutral-200 dark:bg-neutral-200",
|
|
45
|
+
VARIANT_CLASSES[variant],
|
|
46
|
+
variant === "text" && !height && !hasChildren && "h-[1em]",
|
|
47
|
+
animation === "pulse" && "animate-pulse",
|
|
48
|
+
animation === "wave" && "fv-skeleton-wave",
|
|
49
|
+
hasChildren && "relative overflow-hidden [&>*]:invisible",
|
|
50
|
+
className
|
|
51
|
+
),
|
|
52
|
+
style: sizeStyle,
|
|
53
|
+
...props,
|
|
54
|
+
children
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
Skeleton.displayName = "Skeleton";
|
|
60
|
+
exports.Skeleton = Skeleton;
|
|
61
|
+
//# sourceMappingURL=Skeleton.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Skeleton.cjs","sources":["../../../../src/components/Skeleton/Skeleton.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Shape variant of the skeleton placeholder. */\nexport type SkeletonVariant = \"text\" | \"circular\" | \"rectangular\" | \"rounded\";\n\n/** Animation style of the skeleton. `false` disables animation. */\nexport type SkeletonAnimation = \"pulse\" | \"wave\" | false;\n\nexport interface SkeletonProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** Shape variant of the skeleton.\n *\n * - `text` – a single line of text with slight vertical margin and rounded ends\n * - `circular` – a circle (width and height should match)\n * - `rectangular` – a sharp-cornered rectangle\n * - `rounded` – a rectangle with rounded corners\n *\n * @default \"text\"\n */\n variant?: SkeletonVariant;\n /** Animation style. Set to `false` to disable animation. @default \"pulse\" */\n animation?: SkeletonAnimation;\n /** Width of the skeleton. Accepts a CSS value (number is treated as `px`). */\n width?: number | string;\n /** Height of the skeleton. Accepts a CSS value (number is treated as `px`). */\n height?: number | string;\n}\n\nconst VARIANT_CLASSES: Record<SkeletonVariant, string> = {\n text: \"rounded my-0.5\",\n circular: \"rounded-full\",\n rectangular: \"\",\n rounded: \"rounded-lg\",\n};\n\n/**\n * A placeholder preview of content before data is loaded, reducing perceived\n * load time. Mirrors common MUI Skeleton props for easy migration.\n *\n * When used as a loading state, wrap the skeleton region with `aria-busy=\"true\"`\n * and provide an accessible label so screen readers can convey the loading state.\n *\n * @example\n * ```tsx\n * <Skeleton variant=\"text\" width={200} />\n * <Skeleton variant=\"circular\" width={40} height={40} />\n * <Skeleton variant=\"rectangular\" width=\"100%\" height={120} />\n * ```\n */\nexport const Skeleton = React.forwardRef<HTMLSpanElement, SkeletonProps>(\n (\n { className, variant = \"text\", animation = \"pulse\", width, height, style, children, ...props },\n ref,\n ) => {\n const hasChildren = React.Children.count(children) > 0;\n const sizeStyle: React.CSSProperties = {\n ...style,\n ...(width !== undefined && { width: typeof width === \"number\" ? `${width}px` : width }),\n ...(height !== undefined && { height: typeof height === \"number\" ? `${height}px` : height }),\n };\n\n return (\n <span\n ref={ref}\n aria-hidden=\"true\"\n className={cn(\n \"block bg-neutral-200 dark:bg-neutral-200\",\n VARIANT_CLASSES[variant],\n variant === \"text\" && !height && !hasChildren && \"h-[1em]\",\n animation === \"pulse\" && \"animate-pulse\",\n animation === \"wave\" && \"fv-skeleton-wave\",\n hasChildren && \"relative overflow-hidden [&>*]:invisible\",\n className,\n )}\n style={sizeStyle}\n {...props}\n >\n {children}\n </span>\n );\n },\n);\n\nSkeleton.displayName = \"Skeleton\";\n"],"names":["React","jsx","cn"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA4BA,MAAM,kBAAmD;AAAA,EACvD,MAAM;AAAA,EACN,UAAU;AAAA,EACV,aAAa;AAAA,EACb,SAAS;AACX;AAgBO,MAAM,WAAWA,iBAAM;AAAA,EAC5B,CACE,EAAE,WAAW,UAAU,QAAQ,YAAY,SAAS,OAAO,QAAQ,OAAO,UAAU,GAAG,MAAA,GACvF,QACG;AACH,UAAM,cAAcA,iBAAM,SAAS,MAAM,QAAQ,IAAI;AACrD,UAAM,YAAiC;AAAA,MACrC,GAAG;AAAA,MACH,GAAI,UAAU,UAAa,EAAE,OAAO,OAAO,UAAU,WAAW,GAAG,KAAK,OAAO,MAAA;AAAA,MAC/E,GAAI,WAAW,UAAa,EAAE,QAAQ,OAAO,WAAW,WAAW,GAAG,MAAM,OAAO,OAAA;AAAA,IAAO;AAG5F,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,eAAY;AAAA,QACZ,WAAWC,GAAAA;AAAAA,UACT;AAAA,UACA,gBAAgB,OAAO;AAAA,UACvB,YAAY,UAAU,CAAC,UAAU,CAAC,eAAe;AAAA,UACjD,cAAc,WAAW;AAAA,UACzB,cAAc,UAAU;AAAA,UACxB,eAAe;AAAA,UACf;AAAA,QAAA;AAAA,QAEF,OAAO;AAAA,QACN,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AAEA,SAAS,cAAc;;"}
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -139,6 +139,7 @@ const Radio = require("./components/Radio/Radio.cjs");
|
|
|
139
139
|
const RadioGroup = require("./components/RadioGroup/RadioGroup.cjs");
|
|
140
140
|
const SearchField = require("./components/SearchField/SearchField.cjs");
|
|
141
141
|
const Select = require("./components/Select/Select.cjs");
|
|
142
|
+
const Skeleton = require("./components/Skeleton/Skeleton.cjs");
|
|
142
143
|
const Slider = require("./components/Slider/Slider.cjs");
|
|
143
144
|
const Snackbar = require("./components/Snackbar/Snackbar.cjs");
|
|
144
145
|
const Switch = require("./components/Switch/Switch.cjs");
|
|
@@ -299,6 +300,7 @@ exports.SelectGroup = Select.SelectGroup;
|
|
|
299
300
|
exports.SelectItem = Select.SelectItem;
|
|
300
301
|
exports.SelectLabel = Select.SelectLabel;
|
|
301
302
|
exports.SelectSeparator = Select.SelectSeparator;
|
|
303
|
+
exports.Skeleton = Skeleton.Skeleton;
|
|
302
304
|
exports.Slider = Slider.Slider;
|
|
303
305
|
exports.Snackbar = Snackbar.Snackbar;
|
|
304
306
|
exports.Switch = Switch.Switch;
|
package/dist/cjs/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn } from "../../utils/cn.mjs";
|
|
5
|
+
const VARIANT_CLASSES = {
|
|
6
|
+
text: "rounded my-0.5",
|
|
7
|
+
circular: "rounded-full",
|
|
8
|
+
rectangular: "",
|
|
9
|
+
rounded: "rounded-lg"
|
|
10
|
+
};
|
|
11
|
+
const Skeleton = React.forwardRef(
|
|
12
|
+
({ className, variant = "text", animation = "pulse", width, height, style, children, ...props }, ref) => {
|
|
13
|
+
const hasChildren = React.Children.count(children) > 0;
|
|
14
|
+
const sizeStyle = {
|
|
15
|
+
...style,
|
|
16
|
+
...width !== void 0 && { width: typeof width === "number" ? `${width}px` : width },
|
|
17
|
+
...height !== void 0 && { height: typeof height === "number" ? `${height}px` : height }
|
|
18
|
+
};
|
|
19
|
+
return /* @__PURE__ */ jsx(
|
|
20
|
+
"span",
|
|
21
|
+
{
|
|
22
|
+
ref,
|
|
23
|
+
"aria-hidden": "true",
|
|
24
|
+
className: cn(
|
|
25
|
+
"block bg-neutral-200 dark:bg-neutral-200",
|
|
26
|
+
VARIANT_CLASSES[variant],
|
|
27
|
+
variant === "text" && !height && !hasChildren && "h-[1em]",
|
|
28
|
+
animation === "pulse" && "animate-pulse",
|
|
29
|
+
animation === "wave" && "fv-skeleton-wave",
|
|
30
|
+
hasChildren && "relative overflow-hidden [&>*]:invisible",
|
|
31
|
+
className
|
|
32
|
+
),
|
|
33
|
+
style: sizeStyle,
|
|
34
|
+
...props,
|
|
35
|
+
children
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
Skeleton.displayName = "Skeleton";
|
|
41
|
+
export {
|
|
42
|
+
Skeleton
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=Skeleton.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Skeleton.mjs","sources":["../../../src/components/Skeleton/Skeleton.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Shape variant of the skeleton placeholder. */\nexport type SkeletonVariant = \"text\" | \"circular\" | \"rectangular\" | \"rounded\";\n\n/** Animation style of the skeleton. `false` disables animation. */\nexport type SkeletonAnimation = \"pulse\" | \"wave\" | false;\n\nexport interface SkeletonProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** Shape variant of the skeleton.\n *\n * - `text` – a single line of text with slight vertical margin and rounded ends\n * - `circular` – a circle (width and height should match)\n * - `rectangular` – a sharp-cornered rectangle\n * - `rounded` – a rectangle with rounded corners\n *\n * @default \"text\"\n */\n variant?: SkeletonVariant;\n /** Animation style. Set to `false` to disable animation. @default \"pulse\" */\n animation?: SkeletonAnimation;\n /** Width of the skeleton. Accepts a CSS value (number is treated as `px`). */\n width?: number | string;\n /** Height of the skeleton. Accepts a CSS value (number is treated as `px`). */\n height?: number | string;\n}\n\nconst VARIANT_CLASSES: Record<SkeletonVariant, string> = {\n text: \"rounded my-0.5\",\n circular: \"rounded-full\",\n rectangular: \"\",\n rounded: \"rounded-lg\",\n};\n\n/**\n * A placeholder preview of content before data is loaded, reducing perceived\n * load time. Mirrors common MUI Skeleton props for easy migration.\n *\n * When used as a loading state, wrap the skeleton region with `aria-busy=\"true\"`\n * and provide an accessible label so screen readers can convey the loading state.\n *\n * @example\n * ```tsx\n * <Skeleton variant=\"text\" width={200} />\n * <Skeleton variant=\"circular\" width={40} height={40} />\n * <Skeleton variant=\"rectangular\" width=\"100%\" height={120} />\n * ```\n */\nexport const Skeleton = React.forwardRef<HTMLSpanElement, SkeletonProps>(\n (\n { className, variant = \"text\", animation = \"pulse\", width, height, style, children, ...props },\n ref,\n ) => {\n const hasChildren = React.Children.count(children) > 0;\n const sizeStyle: React.CSSProperties = {\n ...style,\n ...(width !== undefined && { width: typeof width === \"number\" ? `${width}px` : width }),\n ...(height !== undefined && { height: typeof height === \"number\" ? `${height}px` : height }),\n };\n\n return (\n <span\n ref={ref}\n aria-hidden=\"true\"\n className={cn(\n \"block bg-neutral-200 dark:bg-neutral-200\",\n VARIANT_CLASSES[variant],\n variant === \"text\" && !height && !hasChildren && \"h-[1em]\",\n animation === \"pulse\" && \"animate-pulse\",\n animation === \"wave\" && \"fv-skeleton-wave\",\n hasChildren && \"relative overflow-hidden [&>*]:invisible\",\n className,\n )}\n style={sizeStyle}\n {...props}\n >\n {children}\n </span>\n );\n },\n);\n\nSkeleton.displayName = \"Skeleton\";\n"],"names":[],"mappings":";;;;AA4BA,MAAM,kBAAmD;AAAA,EACvD,MAAM;AAAA,EACN,UAAU;AAAA,EACV,aAAa;AAAA,EACb,SAAS;AACX;AAgBO,MAAM,WAAW,MAAM;AAAA,EAC5B,CACE,EAAE,WAAW,UAAU,QAAQ,YAAY,SAAS,OAAO,QAAQ,OAAO,UAAU,GAAG,MAAA,GACvF,QACG;AACH,UAAM,cAAc,MAAM,SAAS,MAAM,QAAQ,IAAI;AACrD,UAAM,YAAiC;AAAA,MACrC,GAAG;AAAA,MACH,GAAI,UAAU,UAAa,EAAE,OAAO,OAAO,UAAU,WAAW,GAAG,KAAK,OAAO,MAAA;AAAA,MAC/E,GAAI,WAAW,UAAa,EAAE,QAAQ,OAAO,WAAW,WAAW,GAAG,MAAM,OAAO,OAAA;AAAA,IAAO;AAG5F,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,eAAY;AAAA,QACZ,WAAW;AAAA,UACT;AAAA,UACA,gBAAgB,OAAO;AAAA,UACvB,YAAY,UAAU,CAAC,UAAU,CAAC,eAAe;AAAA,UACjD,cAAc,WAAW;AAAA,UACzB,cAAc,UAAU;AAAA,UACxB,eAAe;AAAA,UACf;AAAA,QAAA;AAAA,QAEF,OAAO;AAAA,QACN,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AAEA,SAAS,cAAc;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1104,6 +1104,47 @@ export declare const ShareIcon: React_2.ForwardRefExoticComponent<React_2.SVGAtt
|
|
|
1104
1104
|
className?: string;
|
|
1105
1105
|
} & React_2.RefAttributes<SVGSVGElement>>;
|
|
1106
1106
|
|
|
1107
|
+
/**
|
|
1108
|
+
* A placeholder preview of content before data is loaded, reducing perceived
|
|
1109
|
+
* load time. Mirrors common MUI Skeleton props for easy migration.
|
|
1110
|
+
*
|
|
1111
|
+
* When used as a loading state, wrap the skeleton region with `aria-busy="true"`
|
|
1112
|
+
* and provide an accessible label so screen readers can convey the loading state.
|
|
1113
|
+
*
|
|
1114
|
+
* @example
|
|
1115
|
+
* ```tsx
|
|
1116
|
+
* <Skeleton variant="text" width={200} />
|
|
1117
|
+
* <Skeleton variant="circular" width={40} height={40} />
|
|
1118
|
+
* <Skeleton variant="rectangular" width="100%" height={120} />
|
|
1119
|
+
* ```
|
|
1120
|
+
*/
|
|
1121
|
+
export declare const Skeleton: React_2.ForwardRefExoticComponent<SkeletonProps & React_2.RefAttributes<HTMLSpanElement>>;
|
|
1122
|
+
|
|
1123
|
+
/** Animation style of the skeleton. `false` disables animation. */
|
|
1124
|
+
export declare type SkeletonAnimation = "pulse" | "wave" | false;
|
|
1125
|
+
|
|
1126
|
+
export declare interface SkeletonProps extends React_2.HTMLAttributes<HTMLSpanElement> {
|
|
1127
|
+
/** Shape variant of the skeleton.
|
|
1128
|
+
*
|
|
1129
|
+
* - `text` – a single line of text with slight vertical margin and rounded ends
|
|
1130
|
+
* - `circular` – a circle (width and height should match)
|
|
1131
|
+
* - `rectangular` – a sharp-cornered rectangle
|
|
1132
|
+
* - `rounded` – a rectangle with rounded corners
|
|
1133
|
+
*
|
|
1134
|
+
* @default "text"
|
|
1135
|
+
*/
|
|
1136
|
+
variant?: SkeletonVariant;
|
|
1137
|
+
/** Animation style. Set to `false` to disable animation. @default "pulse" */
|
|
1138
|
+
animation?: SkeletonAnimation;
|
|
1139
|
+
/** Width of the skeleton. Accepts a CSS value (number is treated as `px`). */
|
|
1140
|
+
width?: number | string;
|
|
1141
|
+
/** Height of the skeleton. Accepts a CSS value (number is treated as `px`). */
|
|
1142
|
+
height?: number | string;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
/** Shape variant of the skeleton placeholder. */
|
|
1146
|
+
export declare type SkeletonVariant = "text" | "circular" | "rectangular" | "rounded";
|
|
1147
|
+
|
|
1107
1148
|
/**
|
|
1108
1149
|
* A range input for selecting one or more numeric values along a track.
|
|
1109
1150
|
* Supports single and multi-thumb modes, optional labels, and a value tooltip.
|
package/dist/index.mjs
CHANGED
|
@@ -137,6 +137,7 @@ import { Radio } from "./components/Radio/Radio.mjs";
|
|
|
137
137
|
import { RadioGroup } from "./components/RadioGroup/RadioGroup.mjs";
|
|
138
138
|
import { SearchField } from "./components/SearchField/SearchField.mjs";
|
|
139
139
|
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator } from "./components/Select/Select.mjs";
|
|
140
|
+
import { Skeleton } from "./components/Skeleton/Skeleton.mjs";
|
|
140
141
|
import { Slider } from "./components/Slider/Slider.mjs";
|
|
141
142
|
import { Snackbar } from "./components/Snackbar/Snackbar.mjs";
|
|
142
143
|
import { Switch } from "./components/Switch/Switch.mjs";
|
|
@@ -268,6 +269,7 @@ export {
|
|
|
268
269
|
SendIcon,
|
|
269
270
|
SettingsIcon,
|
|
270
271
|
ShareIcon,
|
|
272
|
+
Skeleton,
|
|
271
273
|
Slider,
|
|
272
274
|
Snackbar,
|
|
273
275
|
SpinnerIcon,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/styles/theme.css
CHANGED
|
@@ -477,3 +477,30 @@
|
|
|
477
477
|
letter-spacing: 0px;
|
|
478
478
|
line-height: 64px;
|
|
479
479
|
}
|
|
480
|
+
|
|
481
|
+
@utility fv-skeleton-wave {
|
|
482
|
+
position: relative;
|
|
483
|
+
overflow: hidden;
|
|
484
|
+
|
|
485
|
+
&::after {
|
|
486
|
+
position: absolute;
|
|
487
|
+
inset: 0;
|
|
488
|
+
transform: translateX(-100%);
|
|
489
|
+
will-change: transform;
|
|
490
|
+
background-image: linear-gradient(
|
|
491
|
+
90deg,
|
|
492
|
+
transparent,
|
|
493
|
+
color-mix(in srgb, var(--color-foreground-default) 8%, transparent),
|
|
494
|
+
color-mix(in srgb, var(--color-foreground-default) 16%, transparent),
|
|
495
|
+
transparent
|
|
496
|
+
);
|
|
497
|
+
animation: fv-skeleton-shimmer 1.5s ease-in-out infinite;
|
|
498
|
+
content: "";
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
@keyframes fv-skeleton-shimmer {
|
|
503
|
+
100% {
|
|
504
|
+
transform: translateX(100%);
|
|
505
|
+
}
|
|
506
|
+
}
|