@fanvue/ui 2.12.1 → 2.14.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/ChatInput/ChatInput.cjs +75 -27
- package/dist/cjs/components/ChatInput/ChatInput.cjs.map +1 -1
- package/dist/cjs/components/CreatorCard/CreatorCard.cjs +81 -0
- package/dist/cjs/components/CreatorCard/CreatorCard.cjs.map +1 -0
- package/dist/cjs/components/CreatorCover/CreatorCover.cjs +83 -0
- package/dist/cjs/components/CreatorCover/CreatorCover.cjs.map +1 -0
- package/dist/cjs/components/CreatorTile/CreatorTile.cjs +64 -0
- package/dist/cjs/components/CreatorTile/CreatorTile.cjs.map +1 -0
- package/dist/cjs/components/CyclingText/CyclingText.cjs +137 -0
- package/dist/cjs/components/CyclingText/CyclingText.cjs.map +1 -0
- package/dist/cjs/components/CyclingText/useCyclingCycle.cjs +212 -0
- package/dist/cjs/components/CyclingText/useCyclingCycle.cjs.map +1 -0
- package/dist/cjs/components/CyclingText/useCyclingTextTrackWidth.cjs +55 -0
- package/dist/cjs/components/CyclingText/useCyclingTextTrackWidth.cjs.map +1 -0
- package/dist/cjs/components/CyclingText/usePageVisibility.cjs +38 -0
- package/dist/cjs/components/CyclingText/usePageVisibility.cjs.map +1 -0
- package/dist/cjs/components/CyclingText/usePrefersReducedMotion.cjs +39 -0
- package/dist/cjs/components/CyclingText/usePrefersReducedMotion.cjs.map +1 -0
- package/dist/cjs/components/EmptyState/EmptyState.cjs +19 -3
- package/dist/cjs/components/EmptyState/EmptyState.cjs.map +1 -1
- package/dist/cjs/index.cjs +8 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/components/ChatInput/ChatInput.mjs +75 -27
- package/dist/components/ChatInput/ChatInput.mjs.map +1 -1
- package/dist/components/CreatorCard/CreatorCard.mjs +64 -0
- package/dist/components/CreatorCard/CreatorCard.mjs.map +1 -0
- package/dist/components/CreatorCover/CreatorCover.mjs +66 -0
- package/dist/components/CreatorCover/CreatorCover.mjs.map +1 -0
- package/dist/components/CreatorTile/CreatorTile.mjs +47 -0
- package/dist/components/CreatorTile/CreatorTile.mjs.map +1 -0
- package/dist/components/CyclingText/CyclingText.mjs +120 -0
- package/dist/components/CyclingText/CyclingText.mjs.map +1 -0
- package/dist/components/CyclingText/useCyclingCycle.mjs +195 -0
- package/dist/components/CyclingText/useCyclingCycle.mjs.map +1 -0
- package/dist/components/CyclingText/useCyclingTextTrackWidth.mjs +38 -0
- package/dist/components/CyclingText/useCyclingTextTrackWidth.mjs.map +1 -0
- package/dist/components/CyclingText/usePageVisibility.mjs +21 -0
- package/dist/components/CyclingText/usePageVisibility.mjs.map +1 -0
- package/dist/components/CyclingText/usePrefersReducedMotion.mjs +22 -0
- package/dist/components/CyclingText/usePrefersReducedMotion.mjs.map +1 -0
- package/dist/components/EmptyState/EmptyState.mjs +19 -3
- package/dist/components/EmptyState/EmptyState.mjs.map +1 -1
- package/dist/index.d.ts +237 -0
- package/dist/index.mjs +8 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,137 @@
|
|
|
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
|
+
const useCyclingCycle = require("./useCyclingCycle.cjs");
|
|
8
|
+
const useCyclingTextTrackWidth = require("./useCyclingTextTrackWidth.cjs");
|
|
9
|
+
const usePageVisibility = require("./usePageVisibility.cjs");
|
|
10
|
+
const usePrefersReducedMotion = require("./usePrefersReducedMotion.cjs");
|
|
11
|
+
function _interopNamespaceDefault(e) {
|
|
12
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
13
|
+
if (e) {
|
|
14
|
+
for (const k in e) {
|
|
15
|
+
if (k !== "default") {
|
|
16
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
17
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
get: () => e[k]
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
n.default = e;
|
|
25
|
+
return Object.freeze(n);
|
|
26
|
+
}
|
|
27
|
+
const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
|
|
28
|
+
const DEFAULT_INTERVAL_MS = 2100;
|
|
29
|
+
const DEFAULT_TRANSITION_MS = 200;
|
|
30
|
+
const SLIDE_OFFSET_PX = 18;
|
|
31
|
+
const CyclingText = React__namespace.forwardRef(
|
|
32
|
+
({
|
|
33
|
+
items,
|
|
34
|
+
intervalMs = DEFAULT_INTERVAL_MS,
|
|
35
|
+
transitionMs = DEFAULT_TRANSITION_MS,
|
|
36
|
+
direction = "up",
|
|
37
|
+
paused = false,
|
|
38
|
+
sizing = "longest",
|
|
39
|
+
className,
|
|
40
|
+
labelClassName,
|
|
41
|
+
announceChanges = false,
|
|
42
|
+
...rest
|
|
43
|
+
}, ref) => {
|
|
44
|
+
const docVisible = usePageVisibility.usePageVisibility();
|
|
45
|
+
const reducedMotion = usePrefersReducedMotion.usePrefersReducedMotion();
|
|
46
|
+
const { sizingLabelRef, trackWidth } = useCyclingTextTrackWidth.useCyclingTextTrackWidth();
|
|
47
|
+
const { cycle, currentLabel, incomingLabel, sizingLabel, onOutgoingTransitionEnd } = useCyclingCycle.useCyclingCycle(items, sizing, intervalMs, paused, docVisible, transitionMs);
|
|
48
|
+
const itemCount = items.length;
|
|
49
|
+
const outgoingMotionStyle = React__namespace.useMemo(() => {
|
|
50
|
+
const durMs = reducedMotion ? 0 : transitionMs;
|
|
51
|
+
const exiting = cycle.transitioning;
|
|
52
|
+
const yExit = direction === "up" ? -SLIDE_OFFSET_PX : SLIDE_OFFSET_PX;
|
|
53
|
+
return {
|
|
54
|
+
opacity: exiting ? 0 : 1,
|
|
55
|
+
transform: exiting ? `translate3d(0, ${yExit}px, 0)` : "translate3d(0, 0, 0)",
|
|
56
|
+
transition: exiting && durMs > 0 ? `opacity ${durMs}ms cubic-bezier(0.4, 0, 0.2, 1), transform ${durMs}ms cubic-bezier(0.4, 0, 0.2, 1)` : "none"
|
|
57
|
+
};
|
|
58
|
+
}, [cycle.transitioning, direction, transitionMs, reducedMotion]);
|
|
59
|
+
const incomingMotionStyle = React__namespace.useMemo(() => {
|
|
60
|
+
const durMs = reducedMotion ? 0 : transitionMs;
|
|
61
|
+
const entered = cycle.incomingEntered;
|
|
62
|
+
const yEnter = direction === "up" ? SLIDE_OFFSET_PX : -SLIDE_OFFSET_PX;
|
|
63
|
+
return {
|
|
64
|
+
opacity: entered ? 1 : 0,
|
|
65
|
+
transform: entered ? "translate3d(0, 0, 0)" : `translate3d(0, ${yEnter}px, 0)`,
|
|
66
|
+
transition: durMs > 0 ? `opacity ${durMs}ms cubic-bezier(0.4, 0, 0.2, 1), transform ${durMs}ms cubic-bezier(0.4, 0, 0.2, 1)` : "none"
|
|
67
|
+
};
|
|
68
|
+
}, [cycle.incomingEntered, direction, transitionMs, reducedMotion]);
|
|
69
|
+
if (itemCount === 0) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
const wrapperStyle = {
|
|
73
|
+
...trackWidth !== null ? { width: `${trackWidth}px` } : {}
|
|
74
|
+
// paddingTop: SLIDE_OFFSET_PX,
|
|
75
|
+
};
|
|
76
|
+
const showIncoming = incomingLabel !== null && cycle.transitioning;
|
|
77
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
78
|
+
"span",
|
|
79
|
+
{
|
|
80
|
+
ref,
|
|
81
|
+
"data-testid": "cycling-text",
|
|
82
|
+
"data-paused": paused ? "true" : void 0,
|
|
83
|
+
className: cn.cn(
|
|
84
|
+
"relative inline-flex items-center overflow-hidden align-middle leading-[inherit]",
|
|
85
|
+
"motion-safe:transition-[width] motion-safe:duration-300 motion-safe:ease-out",
|
|
86
|
+
className
|
|
87
|
+
),
|
|
88
|
+
style: wrapperStyle,
|
|
89
|
+
...rest,
|
|
90
|
+
children: [
|
|
91
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
92
|
+
"span",
|
|
93
|
+
{
|
|
94
|
+
ref: sizingLabelRef,
|
|
95
|
+
"aria-hidden": "true",
|
|
96
|
+
className: "pointer-events-none invisible inline-block select-none whitespace-nowrap leading-[inherit]",
|
|
97
|
+
children: sizingLabel
|
|
98
|
+
}
|
|
99
|
+
),
|
|
100
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
101
|
+
"span",
|
|
102
|
+
{
|
|
103
|
+
"data-layer": "current",
|
|
104
|
+
"aria-live": announceChanges ? "polite" : void 0,
|
|
105
|
+
"aria-atomic": announceChanges ? true : void 0,
|
|
106
|
+
"data-state": cycle.transitioning ? "exit" : "idle",
|
|
107
|
+
onTransitionEnd: onOutgoingTransitionEnd,
|
|
108
|
+
className: cn.cn(
|
|
109
|
+
"absolute inset-0 flex items-center whitespace-nowrap leading-[inherit]",
|
|
110
|
+
labelClassName
|
|
111
|
+
),
|
|
112
|
+
style: outgoingMotionStyle,
|
|
113
|
+
children: currentLabel
|
|
114
|
+
}
|
|
115
|
+
),
|
|
116
|
+
showIncoming ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
117
|
+
"span",
|
|
118
|
+
{
|
|
119
|
+
"aria-hidden": "true",
|
|
120
|
+
"data-layer": "incoming",
|
|
121
|
+
"data-state": cycle.incomingEntered ? "idle" : "enter",
|
|
122
|
+
className: cn.cn(
|
|
123
|
+
"absolute inset-0 flex items-center whitespace-nowrap leading-[inherit]",
|
|
124
|
+
labelClassName
|
|
125
|
+
),
|
|
126
|
+
style: incomingMotionStyle,
|
|
127
|
+
children: incomingLabel
|
|
128
|
+
}
|
|
129
|
+
) : null
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
CyclingText.displayName = "CyclingText";
|
|
136
|
+
exports.CyclingText = CyclingText;
|
|
137
|
+
//# sourceMappingURL=CyclingText.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CyclingText.cjs","sources":["../../../../src/components/CyclingText/CyclingText.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { useCyclingCycle } from \"./useCyclingCycle\";\nimport { useCyclingTextTrackWidth } from \"./useCyclingTextTrackWidth\";\nimport { usePageVisibility } from \"./usePageVisibility\";\nimport { usePrefersReducedMotion } from \"./usePrefersReducedMotion\";\n\nconst DEFAULT_INTERVAL_MS = 2100;\nconst DEFAULT_TRANSITION_MS = 200;\n\nconst SLIDE_OFFSET_PX = 18;\n\n/** How the wrapper should be sized to accommodate variable-length items. */\nexport type CyclingTextSizing = \"longest\" | \"current\";\n\nexport interface CyclingTextProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, \"children\"> {\n /** Strings to cycle through, in order. Cycles back to the first after the last. */\n items: readonly string[];\n /**\n * Milliseconds to wait after the previous transition finishes before starting the next one.\n * @default 2100\n */\n intervalMs?: number;\n /** Slide and cross-fade duration in milliseconds. @default 200 */\n transitionMs?: number;\n /** Direction the outgoing item slides. @default \"up\" */\n direction?: \"up\" | \"down\";\n /** When true, freezes on the current item — no further cycling until cleared. @default false */\n paused?: boolean;\n /**\n * How the wrapper sizes itself horizontally.\n * - `longest` reserves space for the longest item — no width jitter as items cycle.\n * - `current` shrinks/grows with each item, animating width between cycles.\n * @default \"longest\"\n */\n sizing?: CyclingTextSizing;\n /**\n * When `true`, updates are exposed to assistive technologies via `aria-live=\"polite\"`.\n * Leave `false` for decorative or frequently changing copy so screen readers are not interrupted on every cycle.\n * @default false\n */\n announceChanges?: boolean;\n /**\n * Class applied to each visible label span (current + incoming). Use this for\n * effects that have to sit on the text element itself, e.g. `background-clip: text`.\n */\n labelClassName?: string;\n}\n\n/**\n * Cycles through a list of strings with a slide-in/slide-out animation. Lives\n * inline so it can sit inside divs, spans, buttons, or as a fake placeholder\n * overlay.\n *\n * @example\n * ```tsx\n * <CyclingText items={[\"Thinking\", \"Reading messages\", \"Drafting reply\"]} />\n * ```\n */\nexport const CyclingText = React.forwardRef<HTMLSpanElement, CyclingTextProps>(\n (\n {\n items,\n intervalMs = DEFAULT_INTERVAL_MS,\n transitionMs = DEFAULT_TRANSITION_MS,\n direction = \"up\",\n paused = false,\n sizing = \"longest\",\n className,\n labelClassName,\n announceChanges = false,\n ...rest\n },\n ref,\n ) => {\n const docVisible = usePageVisibility();\n const reducedMotion = usePrefersReducedMotion();\n const { sizingLabelRef, trackWidth } = useCyclingTextTrackWidth();\n const { cycle, currentLabel, incomingLabel, sizingLabel, onOutgoingTransitionEnd } =\n useCyclingCycle(items, sizing, intervalMs, paused, docVisible, transitionMs);\n\n const itemCount = items.length;\n\n const outgoingMotionStyle = React.useMemo((): React.CSSProperties => {\n const durMs = reducedMotion ? 0 : transitionMs;\n const exiting = cycle.transitioning;\n const yExit = direction === \"up\" ? -SLIDE_OFFSET_PX : SLIDE_OFFSET_PX;\n return {\n opacity: exiting ? 0 : 1,\n transform: exiting ? `translate3d(0, ${yExit}px, 0)` : \"translate3d(0, 0, 0)\",\n transition:\n exiting && durMs > 0\n ? `opacity ${durMs}ms cubic-bezier(0.4, 0, 0.2, 1), transform ${durMs}ms cubic-bezier(0.4, 0, 0.2, 1)`\n : \"none\",\n };\n }, [cycle.transitioning, direction, transitionMs, reducedMotion]);\n\n const incomingMotionStyle = React.useMemo((): React.CSSProperties => {\n const durMs = reducedMotion ? 0 : transitionMs;\n const entered = cycle.incomingEntered;\n const yEnter = direction === \"up\" ? SLIDE_OFFSET_PX : -SLIDE_OFFSET_PX;\n return {\n opacity: entered ? 1 : 0,\n transform: entered ? \"translate3d(0, 0, 0)\" : `translate3d(0, ${yEnter}px, 0)`,\n transition:\n durMs > 0\n ? `opacity ${durMs}ms cubic-bezier(0.4, 0, 0.2, 1), transform ${durMs}ms cubic-bezier(0.4, 0, 0.2, 1)`\n : \"none\",\n };\n }, [cycle.incomingEntered, direction, transitionMs, reducedMotion]);\n\n if (itemCount === 0) {\n return null;\n }\n\n const wrapperStyle = {\n ...(trackWidth !== null ? { width: `${trackWidth}px` } : {}),\n // paddingTop: SLIDE_OFFSET_PX,\n } as React.CSSProperties;\n\n const showIncoming = incomingLabel !== null && cycle.transitioning;\n\n return (\n <span\n ref={ref}\n data-testid=\"cycling-text\"\n data-paused={paused ? \"true\" : undefined}\n className={cn(\n \"relative inline-flex items-center overflow-hidden align-middle leading-[inherit]\",\n \"motion-safe:transition-[width] motion-safe:duration-300 motion-safe:ease-out\",\n className,\n )}\n style={wrapperStyle}\n {...rest}\n >\n <span\n ref={sizingLabelRef}\n aria-hidden=\"true\"\n className=\"pointer-events-none invisible inline-block select-none whitespace-nowrap leading-[inherit]\"\n >\n {sizingLabel}\n </span>\n\n <span\n data-layer=\"current\"\n aria-live={announceChanges ? \"polite\" : undefined}\n aria-atomic={announceChanges ? true : undefined}\n data-state={cycle.transitioning ? \"exit\" : \"idle\"}\n onTransitionEnd={onOutgoingTransitionEnd}\n className={cn(\n \"absolute inset-0 flex items-center whitespace-nowrap leading-[inherit]\",\n labelClassName,\n )}\n style={outgoingMotionStyle}\n >\n {currentLabel}\n </span>\n\n {showIncoming ? (\n <span\n aria-hidden=\"true\"\n data-layer=\"incoming\"\n data-state={cycle.incomingEntered ? \"idle\" : \"enter\"}\n className={cn(\n \"absolute inset-0 flex items-center whitespace-nowrap leading-[inherit]\",\n labelClassName,\n )}\n style={incomingMotionStyle}\n >\n {incomingLabel}\n </span>\n ) : null}\n </span>\n );\n },\n);\n\nCyclingText.displayName = \"CyclingText\";\n"],"names":["React","usePageVisibility","usePrefersReducedMotion","useCyclingTextTrackWidth","useCyclingCycle","jsxs","cn","jsx"],"mappings":"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"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
|
+
const React = require("react");
|
|
5
|
+
function _interopNamespaceDefault(e) {
|
|
6
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
7
|
+
if (e) {
|
|
8
|
+
for (const k in e) {
|
|
9
|
+
if (k !== "default") {
|
|
10
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
11
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
get: () => e[k]
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
n.default = e;
|
|
19
|
+
return Object.freeze(n);
|
|
20
|
+
}
|
|
21
|
+
const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
|
|
22
|
+
const initialCycleState = {
|
|
23
|
+
currentIndex: 0,
|
|
24
|
+
incomingIndex: null,
|
|
25
|
+
incomingEntered: false,
|
|
26
|
+
transitioning: false
|
|
27
|
+
};
|
|
28
|
+
function cycleReducer(state, action) {
|
|
29
|
+
switch (action.type) {
|
|
30
|
+
case "tick": {
|
|
31
|
+
if (action.itemCount <= 1) return state;
|
|
32
|
+
const next = (state.currentIndex + 1) % action.itemCount;
|
|
33
|
+
return {
|
|
34
|
+
...state,
|
|
35
|
+
incomingIndex: next,
|
|
36
|
+
incomingEntered: false,
|
|
37
|
+
transitioning: true
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
case "incoming_entered":
|
|
41
|
+
return { ...state, incomingEntered: true };
|
|
42
|
+
case "transition_complete": {
|
|
43
|
+
if (!state.transitioning || state.incomingIndex === null) return state;
|
|
44
|
+
return {
|
|
45
|
+
currentIndex: state.incomingIndex,
|
|
46
|
+
incomingIndex: null,
|
|
47
|
+
incomingEntered: false,
|
|
48
|
+
transitioning: false
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
case "pause_clear":
|
|
52
|
+
return {
|
|
53
|
+
...state,
|
|
54
|
+
incomingIndex: null,
|
|
55
|
+
incomingEntered: false,
|
|
56
|
+
transitioning: false
|
|
57
|
+
};
|
|
58
|
+
case "clamp_after_items_change": {
|
|
59
|
+
if (action.itemCount === 0) return state;
|
|
60
|
+
const idx = state.currentIndex >= action.itemCount ? 0 : state.currentIndex;
|
|
61
|
+
return {
|
|
62
|
+
currentIndex: idx,
|
|
63
|
+
incomingIndex: null,
|
|
64
|
+
incomingEntered: false,
|
|
65
|
+
transitioning: false
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
default:
|
|
69
|
+
return state;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function useCyclingCycle(items, sizing, intervalMs, paused, docVisible, transitionMs) {
|
|
73
|
+
const [cycle, dispatch] = React__namespace.useReducer(cycleReducer, initialCycleState);
|
|
74
|
+
const enterOuterFrameRef = React__namespace.useRef(null);
|
|
75
|
+
const enterInnerFrameRef = React__namespace.useRef(null);
|
|
76
|
+
const fallbackTimerRef = React__namespace.useRef(null);
|
|
77
|
+
const cycleTimeoutRef = React__namespace.useRef(null);
|
|
78
|
+
const clearCycleTimeout = React__namespace.useCallback(() => {
|
|
79
|
+
if (cycleTimeoutRef.current !== null) {
|
|
80
|
+
clearTimeout(cycleTimeoutRef.current);
|
|
81
|
+
cycleTimeoutRef.current = null;
|
|
82
|
+
}
|
|
83
|
+
}, []);
|
|
84
|
+
const clearAnimationArtifacts = React__namespace.useCallback(() => {
|
|
85
|
+
if (enterOuterFrameRef.current !== null) {
|
|
86
|
+
cancelAnimationFrame(enterOuterFrameRef.current);
|
|
87
|
+
enterOuterFrameRef.current = null;
|
|
88
|
+
}
|
|
89
|
+
if (enterInnerFrameRef.current !== null) {
|
|
90
|
+
cancelAnimationFrame(enterInnerFrameRef.current);
|
|
91
|
+
enterInnerFrameRef.current = null;
|
|
92
|
+
}
|
|
93
|
+
if (fallbackTimerRef.current !== null) {
|
|
94
|
+
clearTimeout(fallbackTimerRef.current);
|
|
95
|
+
fallbackTimerRef.current = null;
|
|
96
|
+
}
|
|
97
|
+
clearCycleTimeout();
|
|
98
|
+
}, [clearCycleTimeout]);
|
|
99
|
+
const itemCount = items.length;
|
|
100
|
+
React__namespace.useEffect(() => {
|
|
101
|
+
if (itemCount === 0) return;
|
|
102
|
+
dispatch({ type: "clamp_after_items_change", itemCount });
|
|
103
|
+
}, [itemCount]);
|
|
104
|
+
const safeCurrentIndex = itemCount === 0 ? 0 : cycle.currentIndex % itemCount;
|
|
105
|
+
const safeIncomingIndex = cycle.incomingIndex === null || itemCount === 0 ? null : cycle.incomingIndex % itemCount;
|
|
106
|
+
const currentLabel = itemCount === 0 ? "" : items[safeCurrentIndex] ?? "";
|
|
107
|
+
const incomingLabel = safeIncomingIndex === null ? null : items[safeIncomingIndex] ?? "";
|
|
108
|
+
const longestItem = React__namespace.useMemo(() => {
|
|
109
|
+
if (itemCount === 0) return "";
|
|
110
|
+
let longest = items[0] ?? "";
|
|
111
|
+
for (const item of items) {
|
|
112
|
+
if (item.length > longest.length) longest = item;
|
|
113
|
+
}
|
|
114
|
+
return longest;
|
|
115
|
+
}, [items, itemCount]);
|
|
116
|
+
const sizingLabel = sizing === "longest" ? longestItem : incomingLabel && incomingLabel.length > currentLabel.length ? incomingLabel : currentLabel;
|
|
117
|
+
const shouldCycle = !paused && docVisible && itemCount > 1;
|
|
118
|
+
React__namespace.useEffect(() => {
|
|
119
|
+
if (!shouldCycle || itemCount <= 1) {
|
|
120
|
+
clearCycleTimeout();
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (cycle.transitioning) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
cycleTimeoutRef.current = setTimeout(() => {
|
|
127
|
+
cycleTimeoutRef.current = null;
|
|
128
|
+
dispatch({ type: "tick", itemCount });
|
|
129
|
+
}, intervalMs);
|
|
130
|
+
return () => {
|
|
131
|
+
clearCycleTimeout();
|
|
132
|
+
};
|
|
133
|
+
}, [shouldCycle, itemCount, intervalMs, cycle.transitioning, clearCycleTimeout]);
|
|
134
|
+
React__namespace.useEffect(() => {
|
|
135
|
+
if (paused) {
|
|
136
|
+
clearAnimationArtifacts();
|
|
137
|
+
dispatch({ type: "pause_clear" });
|
|
138
|
+
}
|
|
139
|
+
}, [paused, clearAnimationArtifacts]);
|
|
140
|
+
React__namespace.useEffect(() => {
|
|
141
|
+
return () => {
|
|
142
|
+
clearAnimationArtifacts();
|
|
143
|
+
};
|
|
144
|
+
}, [clearAnimationArtifacts]);
|
|
145
|
+
React__namespace.useEffect(() => {
|
|
146
|
+
if (!cycle.transitioning || cycle.incomingIndex === null || cycle.incomingEntered) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (enterOuterFrameRef.current !== null) {
|
|
150
|
+
cancelAnimationFrame(enterOuterFrameRef.current);
|
|
151
|
+
}
|
|
152
|
+
if (enterInnerFrameRef.current !== null) {
|
|
153
|
+
cancelAnimationFrame(enterInnerFrameRef.current);
|
|
154
|
+
}
|
|
155
|
+
enterOuterFrameRef.current = requestAnimationFrame(() => {
|
|
156
|
+
enterOuterFrameRef.current = null;
|
|
157
|
+
enterInnerFrameRef.current = requestAnimationFrame(() => {
|
|
158
|
+
enterInnerFrameRef.current = null;
|
|
159
|
+
dispatch({ type: "incoming_entered" });
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
return () => {
|
|
163
|
+
if (enterOuterFrameRef.current !== null) {
|
|
164
|
+
cancelAnimationFrame(enterOuterFrameRef.current);
|
|
165
|
+
enterOuterFrameRef.current = null;
|
|
166
|
+
}
|
|
167
|
+
if (enterInnerFrameRef.current !== null) {
|
|
168
|
+
cancelAnimationFrame(enterInnerFrameRef.current);
|
|
169
|
+
enterInnerFrameRef.current = null;
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
}, [cycle.transitioning, cycle.incomingIndex, cycle.incomingEntered]);
|
|
173
|
+
React__namespace.useEffect(() => {
|
|
174
|
+
if (!cycle.transitioning) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (fallbackTimerRef.current !== null) {
|
|
178
|
+
clearTimeout(fallbackTimerRef.current);
|
|
179
|
+
}
|
|
180
|
+
fallbackTimerRef.current = setTimeout(() => {
|
|
181
|
+
dispatch({ type: "transition_complete" });
|
|
182
|
+
fallbackTimerRef.current = null;
|
|
183
|
+
}, transitionMs);
|
|
184
|
+
return () => {
|
|
185
|
+
if (fallbackTimerRef.current !== null) {
|
|
186
|
+
clearTimeout(fallbackTimerRef.current);
|
|
187
|
+
fallbackTimerRef.current = null;
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
}, [cycle.transitioning, transitionMs]);
|
|
191
|
+
const onOutgoingTransitionEnd = React__namespace.useCallback(
|
|
192
|
+
(event) => {
|
|
193
|
+
if (!cycle.transitioning) return;
|
|
194
|
+
if (event.propertyName !== "opacity") return;
|
|
195
|
+
if (fallbackTimerRef.current !== null) {
|
|
196
|
+
clearTimeout(fallbackTimerRef.current);
|
|
197
|
+
fallbackTimerRef.current = null;
|
|
198
|
+
}
|
|
199
|
+
dispatch({ type: "transition_complete" });
|
|
200
|
+
},
|
|
201
|
+
[cycle.transitioning]
|
|
202
|
+
);
|
|
203
|
+
return {
|
|
204
|
+
cycle,
|
|
205
|
+
currentLabel,
|
|
206
|
+
incomingLabel,
|
|
207
|
+
sizingLabel,
|
|
208
|
+
onOutgoingTransitionEnd
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
exports.useCyclingCycle = useCyclingCycle;
|
|
212
|
+
//# sourceMappingURL=useCyclingCycle.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCyclingCycle.cjs","sources":["../../../../src/components/CyclingText/useCyclingCycle.ts"],"sourcesContent":["import * as React from \"react\";\n\ntype CyclingTextSizingOption = \"longest\" | \"current\";\n\ntype CycleState = {\n currentIndex: number;\n incomingIndex: number | null;\n incomingEntered: boolean;\n transitioning: boolean;\n};\n\ntype CycleAction =\n | { type: \"tick\"; itemCount: number }\n | { type: \"incoming_entered\" }\n | { type: \"transition_complete\" }\n | { type: \"pause_clear\" }\n | { type: \"clamp_after_items_change\"; itemCount: number };\n\nconst initialCycleState: CycleState = {\n currentIndex: 0,\n incomingIndex: null,\n incomingEntered: false,\n transitioning: false,\n};\n\nfunction cycleReducer(state: CycleState, action: CycleAction): CycleState {\n switch (action.type) {\n case \"tick\": {\n if (action.itemCount <= 1) return state;\n const next = (state.currentIndex + 1) % action.itemCount;\n return {\n ...state,\n incomingIndex: next,\n incomingEntered: false,\n transitioning: true,\n };\n }\n case \"incoming_entered\":\n return { ...state, incomingEntered: true };\n case \"transition_complete\": {\n if (!state.transitioning || state.incomingIndex === null) return state;\n return {\n currentIndex: state.incomingIndex,\n incomingIndex: null,\n incomingEntered: false,\n transitioning: false,\n };\n }\n case \"pause_clear\":\n return {\n ...state,\n incomingIndex: null,\n incomingEntered: false,\n transitioning: false,\n };\n case \"clamp_after_items_change\": {\n if (action.itemCount === 0) return state;\n const idx = state.currentIndex >= action.itemCount ? 0 : state.currentIndex;\n return {\n currentIndex: idx,\n incomingIndex: null,\n incomingEntered: false,\n transitioning: false,\n };\n }\n default:\n return state;\n }\n}\n\nexport function useCyclingCycle(\n items: readonly string[],\n sizing: CyclingTextSizingOption,\n intervalMs: number,\n paused: boolean,\n docVisible: boolean,\n transitionMs: number,\n) {\n const [cycle, dispatch] = React.useReducer(cycleReducer, initialCycleState);\n\n const enterOuterFrameRef = React.useRef<ReturnType<typeof requestAnimationFrame> | null>(null);\n const enterInnerFrameRef = React.useRef<ReturnType<typeof requestAnimationFrame> | null>(null);\n const fallbackTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);\n const cycleTimeoutRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const clearCycleTimeout = React.useCallback(() => {\n if (cycleTimeoutRef.current !== null) {\n clearTimeout(cycleTimeoutRef.current);\n cycleTimeoutRef.current = null;\n }\n }, []);\n\n const clearAnimationArtifacts = React.useCallback(() => {\n if (enterOuterFrameRef.current !== null) {\n cancelAnimationFrame(enterOuterFrameRef.current);\n enterOuterFrameRef.current = null;\n }\n if (enterInnerFrameRef.current !== null) {\n cancelAnimationFrame(enterInnerFrameRef.current);\n enterInnerFrameRef.current = null;\n }\n if (fallbackTimerRef.current !== null) {\n clearTimeout(fallbackTimerRef.current);\n fallbackTimerRef.current = null;\n }\n clearCycleTimeout();\n }, [clearCycleTimeout]);\n\n const itemCount = items.length;\n\n React.useEffect(() => {\n if (itemCount === 0) return;\n dispatch({ type: \"clamp_after_items_change\", itemCount });\n }, [itemCount]);\n\n const safeCurrentIndex = itemCount === 0 ? 0 : cycle.currentIndex % itemCount;\n const safeIncomingIndex =\n cycle.incomingIndex === null || itemCount === 0 ? null : cycle.incomingIndex % itemCount;\n\n const currentLabel = itemCount === 0 ? \"\" : (items[safeCurrentIndex] ?? \"\");\n const incomingLabel = safeIncomingIndex === null ? null : (items[safeIncomingIndex] ?? \"\");\n\n const longestItem = React.useMemo(() => {\n if (itemCount === 0) return \"\";\n let longest = items[0] ?? \"\";\n for (const item of items) {\n if (item.length > longest.length) longest = item;\n }\n return longest;\n }, [items, itemCount]);\n\n const sizingLabel =\n sizing === \"longest\"\n ? longestItem\n : incomingLabel && incomingLabel.length > currentLabel.length\n ? incomingLabel\n : currentLabel;\n\n const shouldCycle = !paused && docVisible && itemCount > 1;\n\n React.useEffect(() => {\n if (!shouldCycle || itemCount <= 1) {\n clearCycleTimeout();\n return;\n }\n\n if (cycle.transitioning) {\n return;\n }\n\n cycleTimeoutRef.current = setTimeout(() => {\n cycleTimeoutRef.current = null;\n dispatch({ type: \"tick\", itemCount });\n }, intervalMs);\n\n return () => {\n clearCycleTimeout();\n };\n }, [shouldCycle, itemCount, intervalMs, cycle.transitioning, clearCycleTimeout]);\n\n React.useEffect(() => {\n if (paused) {\n clearAnimationArtifacts();\n dispatch({ type: \"pause_clear\" });\n }\n }, [paused, clearAnimationArtifacts]);\n\n React.useEffect(() => {\n return () => {\n clearAnimationArtifacts();\n };\n }, [clearAnimationArtifacts]);\n\n React.useEffect(() => {\n if (!cycle.transitioning || cycle.incomingIndex === null || cycle.incomingEntered) {\n return;\n }\n\n if (enterOuterFrameRef.current !== null) {\n cancelAnimationFrame(enterOuterFrameRef.current);\n }\n if (enterInnerFrameRef.current !== null) {\n cancelAnimationFrame(enterInnerFrameRef.current);\n }\n\n enterOuterFrameRef.current = requestAnimationFrame(() => {\n enterOuterFrameRef.current = null;\n enterInnerFrameRef.current = requestAnimationFrame(() => {\n enterInnerFrameRef.current = null;\n dispatch({ type: \"incoming_entered\" });\n });\n });\n\n return () => {\n if (enterOuterFrameRef.current !== null) {\n cancelAnimationFrame(enterOuterFrameRef.current);\n enterOuterFrameRef.current = null;\n }\n if (enterInnerFrameRef.current !== null) {\n cancelAnimationFrame(enterInnerFrameRef.current);\n enterInnerFrameRef.current = null;\n }\n };\n }, [cycle.transitioning, cycle.incomingIndex, cycle.incomingEntered]);\n\n React.useEffect(() => {\n if (!cycle.transitioning) {\n return;\n }\n if (fallbackTimerRef.current !== null) {\n clearTimeout(fallbackTimerRef.current);\n }\n fallbackTimerRef.current = setTimeout(() => {\n dispatch({ type: \"transition_complete\" });\n fallbackTimerRef.current = null;\n }, transitionMs);\n\n return () => {\n if (fallbackTimerRef.current !== null) {\n clearTimeout(fallbackTimerRef.current);\n fallbackTimerRef.current = null;\n }\n };\n }, [cycle.transitioning, transitionMs]);\n\n const onOutgoingTransitionEnd = React.useCallback(\n (event: React.TransitionEvent<HTMLSpanElement>) => {\n if (!cycle.transitioning) return;\n if (event.propertyName !== \"opacity\") return;\n if (fallbackTimerRef.current !== null) {\n clearTimeout(fallbackTimerRef.current);\n fallbackTimerRef.current = null;\n }\n dispatch({ type: \"transition_complete\" });\n },\n [cycle.transitioning],\n );\n\n return {\n cycle,\n currentLabel,\n incomingLabel,\n sizingLabel,\n onOutgoingTransitionEnd,\n };\n}\n"],"names":["React"],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
|
+
const React = require("react");
|
|
5
|
+
function _interopNamespaceDefault(e) {
|
|
6
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
7
|
+
if (e) {
|
|
8
|
+
for (const k in e) {
|
|
9
|
+
if (k !== "default") {
|
|
10
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
11
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
get: () => e[k]
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
n.default = e;
|
|
19
|
+
return Object.freeze(n);
|
|
20
|
+
}
|
|
21
|
+
const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
|
|
22
|
+
function useCyclingTextTrackWidth() {
|
|
23
|
+
const sizingLabelRef = React__namespace.useRef(null);
|
|
24
|
+
const [trackWidth, setTrackWidth] = React__namespace.useState(null);
|
|
25
|
+
const widthFrameRef = React__namespace.useRef(null);
|
|
26
|
+
React__namespace.useEffect(() => {
|
|
27
|
+
const node = sizingLabelRef.current;
|
|
28
|
+
if (!node) return;
|
|
29
|
+
const measure = () => {
|
|
30
|
+
const next = Math.ceil(node.getBoundingClientRect().width);
|
|
31
|
+
if (!next) return;
|
|
32
|
+
if (widthFrameRef.current !== null) {
|
|
33
|
+
cancelAnimationFrame(widthFrameRef.current);
|
|
34
|
+
}
|
|
35
|
+
widthFrameRef.current = requestAnimationFrame(() => {
|
|
36
|
+
setTrackWidth(next);
|
|
37
|
+
widthFrameRef.current = null;
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
measure();
|
|
41
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
42
|
+
const observer = new ResizeObserver(measure);
|
|
43
|
+
observer.observe(node);
|
|
44
|
+
return () => {
|
|
45
|
+
observer.disconnect();
|
|
46
|
+
if (widthFrameRef.current !== null) {
|
|
47
|
+
cancelAnimationFrame(widthFrameRef.current);
|
|
48
|
+
widthFrameRef.current = null;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}, []);
|
|
52
|
+
return { sizingLabelRef, trackWidth };
|
|
53
|
+
}
|
|
54
|
+
exports.useCyclingTextTrackWidth = useCyclingTextTrackWidth;
|
|
55
|
+
//# sourceMappingURL=useCyclingTextTrackWidth.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCyclingTextTrackWidth.cjs","sources":["../../../../src/components/CyclingText/useCyclingTextTrackWidth.ts"],"sourcesContent":["import * as React from \"react\";\n\n/**\n * Observes the measured label node and stores its width so the wrapper can animate width\n * without layout thrash when fonts load or the parent resizes.\n */\nexport function useCyclingTextTrackWidth() {\n const sizingLabelRef = React.useRef<HTMLSpanElement | null>(null);\n const [trackWidth, setTrackWidth] = React.useState<number | null>(null);\n const widthFrameRef = React.useRef<ReturnType<typeof requestAnimationFrame> | null>(null);\n\n React.useEffect(() => {\n const node = sizingLabelRef.current;\n if (!node) return;\n\n const measure = () => {\n const next = Math.ceil(node.getBoundingClientRect().width);\n if (!next) return;\n if (widthFrameRef.current !== null) {\n cancelAnimationFrame(widthFrameRef.current);\n }\n widthFrameRef.current = requestAnimationFrame(() => {\n setTrackWidth(next);\n widthFrameRef.current = null;\n });\n };\n\n measure();\n\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(measure);\n observer.observe(node);\n\n return () => {\n observer.disconnect();\n if (widthFrameRef.current !== null) {\n cancelAnimationFrame(widthFrameRef.current);\n widthFrameRef.current = null;\n }\n };\n }, []);\n\n return { sizingLabelRef, trackWidth };\n}\n"],"names":["React"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAMO,SAAS,2BAA2B;AACzC,QAAM,iBAAiBA,iBAAM,OAA+B,IAAI;AAChE,QAAM,CAAC,YAAY,aAAa,IAAIA,iBAAM,SAAwB,IAAI;AACtE,QAAM,gBAAgBA,iBAAM,OAAwD,IAAI;AAExFA,mBAAM,UAAU,MAAM;AACpB,UAAM,OAAO,eAAe;AAC5B,QAAI,CAAC,KAAM;AAEX,UAAM,UAAU,MAAM;AACpB,YAAM,OAAO,KAAK,KAAK,KAAK,sBAAA,EAAwB,KAAK;AACzD,UAAI,CAAC,KAAM;AACX,UAAI,cAAc,YAAY,MAAM;AAClC,6BAAqB,cAAc,OAAO;AAAA,MAC5C;AACA,oBAAc,UAAU,sBAAsB,MAAM;AAClD,sBAAc,IAAI;AAClB,sBAAc,UAAU;AAAA,MAC1B,CAAC;AAAA,IACH;AAEA,YAAA;AAEA,QAAI,OAAO,mBAAmB,YAAa;AAC3C,UAAM,WAAW,IAAI,eAAe,OAAO;AAC3C,aAAS,QAAQ,IAAI;AAErB,WAAO,MAAM;AACX,eAAS,WAAA;AACT,UAAI,cAAc,YAAY,MAAM;AAClC,6BAAqB,cAAc,OAAO;AAC1C,sBAAc,UAAU;AAAA,MAC1B;AAAA,IACF;AAAA,EACF,GAAG,CAAA,CAAE;AAEL,SAAO,EAAE,gBAAgB,WAAA;AAC3B;;"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
|
+
const React = require("react");
|
|
5
|
+
function _interopNamespaceDefault(e) {
|
|
6
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
7
|
+
if (e) {
|
|
8
|
+
for (const k in e) {
|
|
9
|
+
if (k !== "default") {
|
|
10
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
11
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
get: () => e[k]
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
n.default = e;
|
|
19
|
+
return Object.freeze(n);
|
|
20
|
+
}
|
|
21
|
+
const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
|
|
22
|
+
function usePageVisibility() {
|
|
23
|
+
const [visible, setVisible] = React__namespace.useState(true);
|
|
24
|
+
React__namespace.useEffect(() => {
|
|
25
|
+
if (typeof document === "undefined") {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const update = () => {
|
|
29
|
+
setVisible(document.visibilityState === "visible");
|
|
30
|
+
};
|
|
31
|
+
update();
|
|
32
|
+
document.addEventListener("visibilitychange", update);
|
|
33
|
+
return () => document.removeEventListener("visibilitychange", update);
|
|
34
|
+
}, []);
|
|
35
|
+
return visible;
|
|
36
|
+
}
|
|
37
|
+
exports.usePageVisibility = usePageVisibility;
|
|
38
|
+
//# sourceMappingURL=usePageVisibility.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePageVisibility.cjs","sources":["../../../../src/components/CyclingText/usePageVisibility.ts"],"sourcesContent":["import * as React from \"react\";\n\n/**\n * Tracks whether the browser tab is visible (`document.visibilityState === \"visible\"`).\n * Cycling animations use this to pause while the document is hidden so timers do not queue\n * many swaps while the user is away.\n */\nexport function usePageVisibility(): boolean {\n const [visible, setVisible] = React.useState(true);\n\n React.useEffect(() => {\n if (typeof document === \"undefined\") {\n return;\n }\n const update = () => {\n setVisible(document.visibilityState === \"visible\");\n };\n update();\n document.addEventListener(\"visibilitychange\", update);\n return () => document.removeEventListener(\"visibilitychange\", update);\n }, []);\n\n return visible;\n}\n"],"names":["React"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAOO,SAAS,oBAA6B;AAC3C,QAAM,CAAC,SAAS,UAAU,IAAIA,iBAAM,SAAS,IAAI;AAEjDA,mBAAM,UAAU,MAAM;AACpB,QAAI,OAAO,aAAa,aAAa;AACnC;AAAA,IACF;AACA,UAAM,SAAS,MAAM;AACnB,iBAAW,SAAS,oBAAoB,SAAS;AAAA,IACnD;AACA,WAAA;AACA,aAAS,iBAAiB,oBAAoB,MAAM;AACpD,WAAO,MAAM,SAAS,oBAAoB,oBAAoB,MAAM;AAAA,EACtE,GAAG,CAAA,CAAE;AAEL,SAAO;AACT;;"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
|
+
const React = require("react");
|
|
5
|
+
function _interopNamespaceDefault(e) {
|
|
6
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
7
|
+
if (e) {
|
|
8
|
+
for (const k in e) {
|
|
9
|
+
if (k !== "default") {
|
|
10
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
11
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
get: () => e[k]
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
n.default = e;
|
|
19
|
+
return Object.freeze(n);
|
|
20
|
+
}
|
|
21
|
+
const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
|
|
22
|
+
function usePrefersReducedMotion() {
|
|
23
|
+
const [reduced, setReduced] = React__namespace.useState(false);
|
|
24
|
+
React__namespace.useEffect(() => {
|
|
25
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
29
|
+
const sync = () => {
|
|
30
|
+
setReduced(mq.matches);
|
|
31
|
+
};
|
|
32
|
+
sync();
|
|
33
|
+
mq.addEventListener("change", sync);
|
|
34
|
+
return () => mq.removeEventListener("change", sync);
|
|
35
|
+
}, []);
|
|
36
|
+
return reduced;
|
|
37
|
+
}
|
|
38
|
+
exports.usePrefersReducedMotion = usePrefersReducedMotion;
|
|
39
|
+
//# sourceMappingURL=usePrefersReducedMotion.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePrefersReducedMotion.cjs","sources":["../../../../src/components/CyclingText/usePrefersReducedMotion.ts"],"sourcesContent":["import * as React from \"react\";\n\nexport function usePrefersReducedMotion(): boolean {\n const [reduced, setReduced] = React.useState(false);\n\n React.useEffect(() => {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") {\n return;\n }\n const mq = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n const sync = () => {\n setReduced(mq.matches);\n };\n sync();\n mq.addEventListener(\"change\", sync);\n return () => mq.removeEventListener(\"change\", sync);\n }, []);\n\n return reduced;\n}\n"],"names":["React"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAEO,SAAS,0BAAmC;AACjD,QAAM,CAAC,SAAS,UAAU,IAAIA,iBAAM,SAAS,KAAK;AAElDA,mBAAM,UAAU,MAAM;AACpB,QAAI,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,YAAY;AAC5E;AAAA,IACF;AACA,UAAM,KAAK,OAAO,WAAW,kCAAkC;AAC/D,UAAM,OAAO,MAAM;AACjB,iBAAW,GAAG,OAAO;AAAA,IACvB;AACA,SAAA;AACA,OAAG,iBAAiB,UAAU,IAAI;AAClC,WAAO,MAAM,GAAG,oBAAoB,UAAU,IAAI;AAAA,EACpD,GAAG,CAAA,CAAE;AAEL,SAAO;AACT;;"}
|
|
@@ -22,6 +22,20 @@ function _interopNamespaceDefault(e) {
|
|
|
22
22
|
return Object.freeze(n);
|
|
23
23
|
}
|
|
24
24
|
const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
|
|
25
|
+
const titleSizeClass = {
|
|
26
|
+
xs: "typography-bold-heading-xs",
|
|
27
|
+
sm: "typography-bold-heading-sm",
|
|
28
|
+
md: "typography-bold-heading-md",
|
|
29
|
+
lg: "typography-bold-heading-lg",
|
|
30
|
+
xl: "typography-bold-heading-xl"
|
|
31
|
+
};
|
|
32
|
+
const mediaSizeClass = {
|
|
33
|
+
xs: "h-[80px]",
|
|
34
|
+
sm: "h-[160px]",
|
|
35
|
+
md: "h-[200px]",
|
|
36
|
+
lg: "h-[280px]",
|
|
37
|
+
xl: "h-[360px]"
|
|
38
|
+
};
|
|
25
39
|
function isNonEmptyString(value) {
|
|
26
40
|
return typeof value === "string" && value.length > 0;
|
|
27
41
|
}
|
|
@@ -39,8 +53,10 @@ const EmptyState = React__namespace.forwardRef(
|
|
|
39
53
|
className,
|
|
40
54
|
variant = "default",
|
|
41
55
|
title,
|
|
56
|
+
titleSize = "lg",
|
|
42
57
|
description,
|
|
43
58
|
media,
|
|
59
|
+
mediaSize = "lg",
|
|
44
60
|
primaryAction,
|
|
45
61
|
secondaryAction,
|
|
46
62
|
...props
|
|
@@ -50,11 +66,11 @@ const EmptyState = React__namespace.forwardRef(
|
|
|
50
66
|
const regionLabelledBy = hasSlotContent(title) ? titleId : void 0;
|
|
51
67
|
const renderedPrimary = primaryAction === void 0 || primaryAction === null || primaryAction === false || primaryAction === "" ? null : isNonEmptyString(primaryAction) ? /* @__PURE__ */ jsxRuntime.jsx(Button.Button, { variant: "brand", fullWidth: true, children: primaryAction }) : primaryAction;
|
|
52
68
|
const renderedSecondary = secondaryAction === void 0 || secondaryAction === null || secondaryAction === false || secondaryAction === "" ? null : isNonEmptyString(secondaryAction) ? /* @__PURE__ */ jsxRuntime.jsx(Button.Button, { variant: "secondary", fullWidth: true, children: secondaryAction }) : secondaryAction;
|
|
53
|
-
const renderedTitle = title === void 0 || title === null || title === false || title === "" ? null : isNonEmptyString(title) ? /* @__PURE__ */ jsxRuntime.jsx("h2", { id: titleId, className: "m-0
|
|
69
|
+
const renderedTitle = title === void 0 || title === null || title === false || title === "" ? null : isNonEmptyString(title) ? /* @__PURE__ */ jsxRuntime.jsx("h2", { id: titleId, className: cn.cn("m-0 text-content-primary", titleSizeClass[titleSize]), children: title }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
54
70
|
"div",
|
|
55
71
|
{
|
|
56
72
|
id: titleId,
|
|
57
|
-
className: "
|
|
73
|
+
className: cn.cn("text-content-primary min-w-0 w-full", titleSizeClass[titleSize]),
|
|
58
74
|
children: title
|
|
59
75
|
}
|
|
60
76
|
);
|
|
@@ -83,7 +99,7 @@ const EmptyState = React__namespace.forwardRef(
|
|
|
83
99
|
),
|
|
84
100
|
...props,
|
|
85
101
|
children: [
|
|
86
|
-
showMedia && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
102
|
+
showMedia && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn.cn("w-full overflow-hidden rounded-md", mediaSizeClass[mediaSize]), children: renderedMedia }),
|
|
87
103
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
88
104
|
"div",
|
|
89
105
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmptyState.cjs","sources":["../../../../src/components/EmptyState/EmptyState.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../Button/Button\";\n\nexport type EmptyStateVariant = \"default\" | \"centered\";\n\n/** Slot that can be plain copy (styled by `EmptyState`) or custom markup. */\nexport type EmptyStateSlot = string | React.ReactNode;\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === \"string\" && value.length > 0;\n}\n\nfunction hasSlotContent(value: EmptyStateSlot | undefined): boolean {\n if (value === undefined || value === null || value === false) {\n return false;\n }\n if (typeof value === \"string\") {\n return value.length > 0;\n }\n return true;\n}\n\nexport interface EmptyStateProps extends Omit<React.HTMLAttributes<HTMLElement>, \"title\"> {\n /**\n * Matches Figma property `Property 1` (`Default` / `centered`).\n * @default \"default\"\n */\n variant?: EmptyStateVariant;\n /** Main heading. Strings use library heading styles; pass a node for full control. */\n title?: EmptyStateSlot;\n /** Supporting body copy. Strings use library body styles; pass a node for rich text. */\n description?: EmptyStateSlot;\n /**\n * Top visual / illustration slot.\n * A string is treated as an image URL (`<img src={…}>`); pass a node for custom layout.\n */\n media?: EmptyStateSlot;\n /**\n * Primary call to action.\n * A string renders a brand `Button` with that label; pass a node for links, loading, etc.\n */\n primaryAction?: EmptyStateSlot;\n /**\n * Secondary action below the primary.\n * A string renders a secondary `Button` with that label; pass a node when you need more control.\n */\n secondaryAction?: EmptyStateSlot;\n}\n\nexport const EmptyState = React.forwardRef<HTMLElement, EmptyStateProps>(\n (\n {\n className,\n variant = \"default\",\n title,\n description,\n media,\n primaryAction,\n secondaryAction,\n ...props\n },\n ref,\n ) => {\n const isCentered = variant === \"centered\";\n const titleId = React.useId();\n const regionLabelledBy = hasSlotContent(title) ? titleId : undefined;\n\n const renderedPrimary =\n primaryAction === undefined ||\n primaryAction === null ||\n primaryAction === false ||\n primaryAction === \"\" ? null : isNonEmptyString(primaryAction) ? (\n <Button variant=\"brand\" fullWidth>\n {primaryAction}\n </Button>\n ) : (\n primaryAction\n );\n\n const renderedSecondary =\n secondaryAction === undefined ||\n secondaryAction === null ||\n secondaryAction === false ||\n secondaryAction === \"\" ? null : isNonEmptyString(secondaryAction) ? (\n <Button variant=\"secondary\" fullWidth>\n {secondaryAction}\n </Button>\n ) : (\n secondaryAction\n );\n\n const renderedTitle =\n title === undefined ||\n title === null ||\n title === false ||\n title === \"\" ? null : isNonEmptyString(title) ? (\n <h2 id={titleId} className
|
|
1
|
+
{"version":3,"file":"EmptyState.cjs","sources":["../../../../src/components/EmptyState/EmptyState.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../Button/Button\";\n\nexport type EmptyStateVariant = \"default\" | \"centered\";\n\nexport type EmptyStateTitleSize = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n\nconst titleSizeClass: Record<EmptyStateTitleSize, string> = {\n xs: \"typography-bold-heading-xs\",\n sm: \"typography-bold-heading-sm\",\n md: \"typography-bold-heading-md\",\n lg: \"typography-bold-heading-lg\",\n xl: \"typography-bold-heading-xl\",\n};\n\nexport type EmptyStateMediaSize = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n\nconst mediaSizeClass: Record<EmptyStateMediaSize, string> = {\n xs: \"h-[80px]\",\n sm: \"h-[160px]\",\n md: \"h-[200px]\",\n lg: \"h-[280px]\",\n xl: \"h-[360px]\",\n};\n\n/** Slot that can be plain copy (styled by `EmptyState`) or custom markup. */\nexport type EmptyStateSlot = string | React.ReactNode;\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === \"string\" && value.length > 0;\n}\n\nfunction hasSlotContent(value: EmptyStateSlot | undefined): boolean {\n if (value === undefined || value === null || value === false) {\n return false;\n }\n if (typeof value === \"string\") {\n return value.length > 0;\n }\n return true;\n}\n\nexport interface EmptyStateProps extends Omit<React.HTMLAttributes<HTMLElement>, \"title\"> {\n /**\n * Matches Figma property `Property 1` (`Default` / `centered`).\n * @default \"default\"\n */\n variant?: EmptyStateVariant;\n /** Main heading. Strings use library heading styles; pass a node for full control. */\n title?: EmptyStateSlot;\n /**\n * Size of the title heading — mapped internally to bold heading typography tokens.\n * @default \"lg\"\n */\n titleSize?: EmptyStateTitleSize;\n /** Supporting body copy. Strings use library body styles; pass a node for rich text. */\n description?: EmptyStateSlot;\n /**\n * Top visual / illustration slot.\n * A string is treated as an image URL (`<img src={…}>`); pass a node for custom layout.\n */\n media?: EmptyStateSlot;\n /**\n * Height of the media container.\n * @default \"lg\"\n */\n mediaSize?: EmptyStateMediaSize;\n /**\n * Primary call to action.\n * A string renders a brand `Button` with that label; pass a node for links, loading, etc.\n */\n primaryAction?: EmptyStateSlot;\n /**\n * Secondary action below the primary.\n * A string renders a secondary `Button` with that label; pass a node when you need more control.\n */\n secondaryAction?: EmptyStateSlot;\n}\n\nexport const EmptyState = React.forwardRef<HTMLElement, EmptyStateProps>(\n (\n {\n className,\n variant = \"default\",\n title,\n titleSize = \"lg\",\n description,\n media,\n mediaSize = \"lg\",\n primaryAction,\n secondaryAction,\n ...props\n },\n ref,\n ) => {\n const isCentered = variant === \"centered\";\n const titleId = React.useId();\n const regionLabelledBy = hasSlotContent(title) ? titleId : undefined;\n\n const renderedPrimary =\n primaryAction === undefined ||\n primaryAction === null ||\n primaryAction === false ||\n primaryAction === \"\" ? null : isNonEmptyString(primaryAction) ? (\n <Button variant=\"brand\" fullWidth>\n {primaryAction}\n </Button>\n ) : (\n primaryAction\n );\n\n const renderedSecondary =\n secondaryAction === undefined ||\n secondaryAction === null ||\n secondaryAction === false ||\n secondaryAction === \"\" ? null : isNonEmptyString(secondaryAction) ? (\n <Button variant=\"secondary\" fullWidth>\n {secondaryAction}\n </Button>\n ) : (\n secondaryAction\n );\n\n const renderedTitle =\n title === undefined ||\n title === null ||\n title === false ||\n title === \"\" ? null : isNonEmptyString(title) ? (\n <h2 id={titleId} className={cn(\"m-0 text-content-primary\", titleSizeClass[titleSize])}>\n {title}\n </h2>\n ) : (\n <div\n id={titleId}\n className={cn(\"text-content-primary min-w-0 w-full\", titleSizeClass[titleSize])}\n >\n {title}\n </div>\n );\n\n const renderedDescription =\n description === undefined ||\n description === null ||\n description === false ||\n description === \"\" ? null : isNonEmptyString(description) ? (\n <p className=\"m-0 typography-regular-body-lg text-content-secondary\">{description}</p>\n ) : (\n <div className=\"typography-regular-body-lg text-content-secondary min-w-0 w-full\">\n {description}\n </div>\n );\n\n const renderedMedia =\n media === undefined ||\n media === null ||\n media === false ||\n media === \"\" ? null : isNonEmptyString(media) ? (\n <img\n src={media}\n alt=\"\"\n decoding=\"async\"\n className=\"block h-full w-full object-contain object-center\"\n />\n ) : (\n media\n );\n\n const showMedia = renderedMedia !== null;\n const showActions = renderedPrimary !== null || renderedSecondary !== null;\n\n return (\n <section\n ref={ref}\n aria-labelledby={regionLabelledBy}\n data-testid=\"empty-state\"\n className={cn(\n \"flex w-full max-w-[375px] flex-col gap-6\",\n isCentered ? \"items-center text-center\" : \"items-start text-left\",\n className,\n )}\n {...props}\n >\n {showMedia && (\n <div className={cn(\"w-full overflow-hidden rounded-md\", mediaSizeClass[mediaSize])}>\n {renderedMedia}\n </div>\n )}\n\n <div\n className={cn(\"flex w-full flex-col gap-6\", isCentered ? \"items-center\" : \"items-start\")}\n >\n <div\n className={cn(\n \"flex w-full flex-col gap-4\",\n isCentered ? \"items-center\" : \"items-start\",\n )}\n >\n {renderedTitle}\n {renderedDescription}\n </div>\n\n {showActions ? (\n <div className={cn(\"flex flex-col gap-4\", isCentered ? \"items-center\" : \"items-start\")}>\n {renderedPrimary}\n {renderedSecondary}\n </div>\n ) : null}\n </div>\n </section>\n );\n },\n);\n\nEmptyState.displayName = \"EmptyState\";\n"],"names":["React","Button","jsx","cn","jsxs"],"mappings":"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"}
|