@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.
@@ -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;;"}
@@ -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;
@@ -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,
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fanvue/ui",
3
- "version": "1.14.1",
3
+ "version": "1.15.0",
4
4
  "description": "React component library built with Tailwind CSS for Fanvue ecosystem",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org",