@tailwind-styled/animate 2.0.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.cjs +277 -0
- package/dist/index.d.cts +117 -0
- package/dist/index.d.ts +117 -0
- package/dist/index.js +247 -0
- package/package.json +27 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
animate: () => animate,
|
|
24
|
+
animations: () => animations,
|
|
25
|
+
compileAnimation: () => compileAnimation,
|
|
26
|
+
extractAnimationCss: () => extractAnimationCss,
|
|
27
|
+
getAnimationRegistry: () => getAnimationRegistry,
|
|
28
|
+
keyframes: () => keyframes
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(index_exports);
|
|
31
|
+
var TW_TO_CSS = {
|
|
32
|
+
// Opacity
|
|
33
|
+
"opacity-0": "opacity: 0",
|
|
34
|
+
"opacity-5": "opacity: 0.05",
|
|
35
|
+
"opacity-10": "opacity: 0.1",
|
|
36
|
+
"opacity-20": "opacity: 0.2",
|
|
37
|
+
"opacity-25": "opacity: 0.25",
|
|
38
|
+
"opacity-30": "opacity: 0.3",
|
|
39
|
+
"opacity-40": "opacity: 0.4",
|
|
40
|
+
"opacity-50": "opacity: 0.5",
|
|
41
|
+
"opacity-60": "opacity: 0.6",
|
|
42
|
+
"opacity-70": "opacity: 0.7",
|
|
43
|
+
"opacity-75": "opacity: 0.75",
|
|
44
|
+
"opacity-80": "opacity: 0.8",
|
|
45
|
+
"opacity-90": "opacity: 0.9",
|
|
46
|
+
"opacity-95": "opacity: 0.95",
|
|
47
|
+
"opacity-100": "opacity: 1",
|
|
48
|
+
// Translate Y
|
|
49
|
+
"translate-y-0": "transform: translateY(0px)",
|
|
50
|
+
"translate-y-0.5": "transform: translateY(0.125rem)",
|
|
51
|
+
"translate-y-1": "transform: translateY(0.25rem)",
|
|
52
|
+
"translate-y-2": "transform: translateY(0.5rem)",
|
|
53
|
+
"translate-y-3": "transform: translateY(0.75rem)",
|
|
54
|
+
"translate-y-4": "transform: translateY(1rem)",
|
|
55
|
+
"translate-y-6": "transform: translateY(1.5rem)",
|
|
56
|
+
"translate-y-8": "transform: translateY(2rem)",
|
|
57
|
+
"-translate-y-1": "transform: translateY(-0.25rem)",
|
|
58
|
+
"-translate-y-2": "transform: translateY(-0.5rem)",
|
|
59
|
+
"-translate-y-4": "transform: translateY(-1rem)",
|
|
60
|
+
"-translate-y-8": "transform: translateY(-2rem)",
|
|
61
|
+
// Translate X
|
|
62
|
+
"translate-x-0": "transform: translateX(0px)",
|
|
63
|
+
"translate-x-1": "transform: translateX(0.25rem)",
|
|
64
|
+
"translate-x-2": "transform: translateX(0.5rem)",
|
|
65
|
+
"translate-x-4": "transform: translateX(1rem)",
|
|
66
|
+
"-translate-x-1": "transform: translateX(-0.25rem)",
|
|
67
|
+
"-translate-x-2": "transform: translateX(-0.5rem)",
|
|
68
|
+
"-translate-x-4": "transform: translateX(-1rem)",
|
|
69
|
+
// Scale
|
|
70
|
+
"scale-0": "transform: scale(0)",
|
|
71
|
+
"scale-50": "transform: scale(0.5)",
|
|
72
|
+
"scale-75": "transform: scale(0.75)",
|
|
73
|
+
"scale-90": "transform: scale(0.9)",
|
|
74
|
+
"scale-95": "transform: scale(0.95)",
|
|
75
|
+
"scale-100": "transform: scale(1)",
|
|
76
|
+
"scale-105": "transform: scale(1.05)",
|
|
77
|
+
"scale-110": "transform: scale(1.1)",
|
|
78
|
+
"scale-125": "transform: scale(1.25)",
|
|
79
|
+
"scale-150": "transform: scale(1.5)",
|
|
80
|
+
// Rotate
|
|
81
|
+
"rotate-0": "transform: rotate(0deg)",
|
|
82
|
+
"rotate-1": "transform: rotate(1deg)",
|
|
83
|
+
"rotate-2": "transform: rotate(2deg)",
|
|
84
|
+
"rotate-3": "transform: rotate(3deg)",
|
|
85
|
+
"rotate-6": "transform: rotate(6deg)",
|
|
86
|
+
"rotate-12": "transform: rotate(12deg)",
|
|
87
|
+
"rotate-45": "transform: rotate(45deg)",
|
|
88
|
+
"rotate-90": "transform: rotate(90deg)",
|
|
89
|
+
"rotate-180": "transform: rotate(180deg)",
|
|
90
|
+
"-rotate-1": "transform: rotate(-1deg)",
|
|
91
|
+
"-rotate-2": "transform: rotate(-2deg)",
|
|
92
|
+
"-rotate-6": "transform: rotate(-6deg)",
|
|
93
|
+
"-rotate-12": "transform: rotate(-12deg)",
|
|
94
|
+
"-rotate-45": "transform: rotate(-45deg)",
|
|
95
|
+
"-rotate-90": "transform: rotate(-90deg)",
|
|
96
|
+
// Blur
|
|
97
|
+
"blur-none": "filter: blur(0)",
|
|
98
|
+
"blur-sm": "filter: blur(4px)",
|
|
99
|
+
blur: "filter: blur(8px)",
|
|
100
|
+
"blur-md": "filter: blur(12px)",
|
|
101
|
+
"blur-lg": "filter: blur(16px)",
|
|
102
|
+
"blur-xl": "filter: blur(24px)",
|
|
103
|
+
"blur-2xl": "filter: blur(40px)",
|
|
104
|
+
"blur-3xl": "filter: blur(64px)"
|
|
105
|
+
};
|
|
106
|
+
function classesToCss(classes) {
|
|
107
|
+
const parts = classes.split(/\s+/).filter(Boolean);
|
|
108
|
+
const transforms = [];
|
|
109
|
+
const others = [];
|
|
110
|
+
for (const cls of parts) {
|
|
111
|
+
const css = TW_TO_CSS[cls];
|
|
112
|
+
if (!css) continue;
|
|
113
|
+
if (css.startsWith("transform:")) {
|
|
114
|
+
transforms.push(css.replace("transform: ", ""));
|
|
115
|
+
} else {
|
|
116
|
+
others.push(css);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const result = [...others];
|
|
120
|
+
if (transforms.length > 0) {
|
|
121
|
+
result.push(`transform: ${transforms.join(" ")}`);
|
|
122
|
+
}
|
|
123
|
+
return result.join("; ");
|
|
124
|
+
}
|
|
125
|
+
var _animCounter = 0;
|
|
126
|
+
function genAnimId(name) {
|
|
127
|
+
if (name) return `tw-${name.replace(/[^a-zA-Z0-9]/g, "-")}`;
|
|
128
|
+
return `tw-anim-${++_animCounter}`;
|
|
129
|
+
}
|
|
130
|
+
var _animRegistry = /* @__PURE__ */ new Map();
|
|
131
|
+
function getAnimationRegistry() {
|
|
132
|
+
return _animRegistry;
|
|
133
|
+
}
|
|
134
|
+
function compileAnimation(opts) {
|
|
135
|
+
const {
|
|
136
|
+
from,
|
|
137
|
+
to,
|
|
138
|
+
duration = 300,
|
|
139
|
+
easing = "ease-out",
|
|
140
|
+
delay = 0,
|
|
141
|
+
fill = "both",
|
|
142
|
+
iterations = 1,
|
|
143
|
+
direction = "normal",
|
|
144
|
+
name
|
|
145
|
+
} = opts;
|
|
146
|
+
const animId = genAnimId(
|
|
147
|
+
name != null ? name : `${from.replace(/\s+/g, "-")}-${to.replace(/\s+/g, "-")}`.slice(0, 30)
|
|
148
|
+
);
|
|
149
|
+
if (_animRegistry.has(animId)) {
|
|
150
|
+
return _animRegistry.get(animId);
|
|
151
|
+
}
|
|
152
|
+
const fromCss = classesToCss(from);
|
|
153
|
+
const toCss = classesToCss(to);
|
|
154
|
+
const keyframesCss = [
|
|
155
|
+
`@keyframes ${animId} {`,
|
|
156
|
+
fromCss ? ` from { ${fromCss} }` : ` from {}`,
|
|
157
|
+
toCss ? ` to { ${toCss} }` : ` to {}`,
|
|
158
|
+
`}`
|
|
159
|
+
].join("\n");
|
|
160
|
+
const iterStr = iterations === "infinite" ? "infinite" : String(iterations);
|
|
161
|
+
const animationCss = [
|
|
162
|
+
`animation-name: ${animId}`,
|
|
163
|
+
`animation-duration: ${duration}ms`,
|
|
164
|
+
`animation-timing-function: ${easing}`,
|
|
165
|
+
`animation-delay: ${delay}ms`,
|
|
166
|
+
`animation-fill-mode: ${fill}`,
|
|
167
|
+
`animation-iteration-count: ${iterStr}`,
|
|
168
|
+
`animation-direction: ${direction}`
|
|
169
|
+
].join("; ");
|
|
170
|
+
const className = animId;
|
|
171
|
+
const compiled = { className, keyframesCss, animationCss };
|
|
172
|
+
_animRegistry.set(animId, compiled);
|
|
173
|
+
return compiled;
|
|
174
|
+
}
|
|
175
|
+
function animate(opts) {
|
|
176
|
+
const compiled = compileAnimation(opts);
|
|
177
|
+
if (typeof document !== "undefined") {
|
|
178
|
+
const styleId = `__tw_anim_${compiled.className}`;
|
|
179
|
+
if (!document.getElementById(styleId)) {
|
|
180
|
+
const style = document.createElement("style");
|
|
181
|
+
style.id = styleId;
|
|
182
|
+
style.textContent = `${compiled.keyframesCss}
|
|
183
|
+
.${compiled.className}{${compiled.animationCss}}`;
|
|
184
|
+
document.head.appendChild(style);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return compiled.className;
|
|
188
|
+
}
|
|
189
|
+
function keyframes(name, stops) {
|
|
190
|
+
const animId = genAnimId(name);
|
|
191
|
+
if (_animRegistry.has(animId)) {
|
|
192
|
+
return animId;
|
|
193
|
+
}
|
|
194
|
+
const stopLines = Object.entries(stops).map(([stop, classes]) => {
|
|
195
|
+
const css = classesToCss(classes);
|
|
196
|
+
return ` ${stop} { ${css} }`;
|
|
197
|
+
}).join("\n");
|
|
198
|
+
const keyframesCss = `@keyframes ${animId} {
|
|
199
|
+
${stopLines}
|
|
200
|
+
}`;
|
|
201
|
+
if (typeof document !== "undefined") {
|
|
202
|
+
const styleId = `__tw_kf_${animId}`;
|
|
203
|
+
if (!document.getElementById(styleId)) {
|
|
204
|
+
const style = document.createElement("style");
|
|
205
|
+
style.id = styleId;
|
|
206
|
+
style.textContent = keyframesCss;
|
|
207
|
+
document.head.appendChild(style);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
_animRegistry.set(animId, {
|
|
211
|
+
className: animId,
|
|
212
|
+
keyframesCss,
|
|
213
|
+
animationCss: `animation-name: ${animId}`
|
|
214
|
+
});
|
|
215
|
+
return animId;
|
|
216
|
+
}
|
|
217
|
+
var animations = {
|
|
218
|
+
fadeIn: animate({ from: "opacity-0", to: "opacity-100", duration: 200 }),
|
|
219
|
+
fadeOut: animate({ from: "opacity-100", to: "opacity-0", duration: 200 }),
|
|
220
|
+
slideUp: animate({
|
|
221
|
+
from: "opacity-0 translate-y-4",
|
|
222
|
+
to: "opacity-100 translate-y-0",
|
|
223
|
+
duration: 300
|
|
224
|
+
}),
|
|
225
|
+
slideDown: animate({
|
|
226
|
+
from: "opacity-0 -translate-y-4",
|
|
227
|
+
to: "opacity-100 translate-y-0",
|
|
228
|
+
duration: 300
|
|
229
|
+
}),
|
|
230
|
+
slideLeft: animate({
|
|
231
|
+
from: "opacity-0 translate-x-4",
|
|
232
|
+
to: "opacity-100 translate-x-0",
|
|
233
|
+
duration: 300
|
|
234
|
+
}),
|
|
235
|
+
slideRight: animate({
|
|
236
|
+
from: "opacity-0 -translate-x-4",
|
|
237
|
+
to: "opacity-100 translate-x-0",
|
|
238
|
+
duration: 300
|
|
239
|
+
}),
|
|
240
|
+
scaleIn: animate({
|
|
241
|
+
from: "opacity-0 scale-95",
|
|
242
|
+
to: "opacity-100 scale-100",
|
|
243
|
+
duration: 200,
|
|
244
|
+
easing: "cubic-bezier(0.16,1,0.3,1)"
|
|
245
|
+
}),
|
|
246
|
+
scaleOut: animate({ from: "opacity-100 scale-100", to: "opacity-0 scale-95", duration: 150 }),
|
|
247
|
+
blurIn: animate({ from: "opacity-0 blur-sm", to: "opacity-100 blur-none", duration: 300 }),
|
|
248
|
+
bounceIn: animate({
|
|
249
|
+
from: "opacity-0 scale-50",
|
|
250
|
+
to: "opacity-100 scale-100",
|
|
251
|
+
duration: 400,
|
|
252
|
+
easing: "cubic-bezier(0.34,1.56,0.64,1)"
|
|
253
|
+
}),
|
|
254
|
+
spinIn: animate({
|
|
255
|
+
from: "opacity-0 rotate-180 scale-50",
|
|
256
|
+
to: "opacity-100 rotate-0 scale-100",
|
|
257
|
+
duration: 400,
|
|
258
|
+
easing: "cubic-bezier(0.16,1,0.3,1)"
|
|
259
|
+
})
|
|
260
|
+
};
|
|
261
|
+
function extractAnimationCss() {
|
|
262
|
+
const lines = [];
|
|
263
|
+
for (const [, compiled] of _animRegistry) {
|
|
264
|
+
lines.push(compiled.keyframesCss);
|
|
265
|
+
lines.push(`.${compiled.className} { ${compiled.animationCss} }`);
|
|
266
|
+
}
|
|
267
|
+
return lines.join("\n\n");
|
|
268
|
+
}
|
|
269
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
270
|
+
0 && (module.exports = {
|
|
271
|
+
animate,
|
|
272
|
+
animations,
|
|
273
|
+
compileAnimation,
|
|
274
|
+
extractAnimationCss,
|
|
275
|
+
getAnimationRegistry,
|
|
276
|
+
keyframes
|
|
277
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tailwind-styled-v4 — Animation DSL
|
|
3
|
+
*
|
|
4
|
+
* Compile-time animation system. Define animations dengan Tailwind class,
|
|
5
|
+
* compiler generate @keyframes — nol runtime, nol JS overhead.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
*
|
|
9
|
+
* // Cara 1: .animate() chaining pada tw component
|
|
10
|
+
* const FadeIn = tw.div.animate({
|
|
11
|
+
* from: "opacity-0 translate-y-2",
|
|
12
|
+
* to: "opacity-100 translate-y-0",
|
|
13
|
+
* duration: 300,
|
|
14
|
+
* easing: "ease-out"
|
|
15
|
+
* })
|
|
16
|
+
*
|
|
17
|
+
* // Cara 2: standalone animate() utility
|
|
18
|
+
* const fadeIn = animate({
|
|
19
|
+
* from: "opacity-0 scale-95",
|
|
20
|
+
* to: "opacity-100 scale-100",
|
|
21
|
+
* duration: 200,
|
|
22
|
+
* })
|
|
23
|
+
* const Box = tw.div`${fadeIn}`
|
|
24
|
+
*
|
|
25
|
+
* // Cara 3: preset animations
|
|
26
|
+
* const Card = tw.div`${animations.fadeIn} ${animations.slideUp}`
|
|
27
|
+
*
|
|
28
|
+
* // Cara 4: tw.keyframes() custom
|
|
29
|
+
* const spin = tw.keyframes("spin", {
|
|
30
|
+
* "0%": "rotate-0",
|
|
31
|
+
* "100%": "rotate-180",
|
|
32
|
+
* })
|
|
33
|
+
*/
|
|
34
|
+
interface AnimateOptions {
|
|
35
|
+
/** Tailwind classes for animation start state */
|
|
36
|
+
from: string;
|
|
37
|
+
/** Tailwind classes for animation end state */
|
|
38
|
+
to: string;
|
|
39
|
+
/** Duration in ms. Default: 300 */
|
|
40
|
+
duration?: number;
|
|
41
|
+
/** CSS easing. Default: "ease-out" */
|
|
42
|
+
easing?: string;
|
|
43
|
+
/** Delay in ms. Default: 0 */
|
|
44
|
+
delay?: number;
|
|
45
|
+
/** Fill mode. Default: "both" */
|
|
46
|
+
fill?: "none" | "forwards" | "backwards" | "both";
|
|
47
|
+
/** Iteration count. Default: 1 */
|
|
48
|
+
iterations?: number | "infinite";
|
|
49
|
+
/** Direction. Default: "normal" */
|
|
50
|
+
direction?: "normal" | "reverse" | "alternate" | "alternate-reverse";
|
|
51
|
+
/** Animation name override (auto-generated from from+to if not set) */
|
|
52
|
+
name?: string;
|
|
53
|
+
}
|
|
54
|
+
interface KeyframesDefinition {
|
|
55
|
+
[stop: string]: string;
|
|
56
|
+
}
|
|
57
|
+
interface CompiledAnimation {
|
|
58
|
+
/** CSS animation class name to apply */
|
|
59
|
+
className: string;
|
|
60
|
+
/** @keyframes CSS to inject */
|
|
61
|
+
keyframesCss: string;
|
|
62
|
+
/** animation CSS shorthand */
|
|
63
|
+
animationCss: string;
|
|
64
|
+
}
|
|
65
|
+
declare function getAnimationRegistry(): Map<string, CompiledAnimation>;
|
|
66
|
+
/**
|
|
67
|
+
* Compile AnimateOptions into CSS animation + @keyframes.
|
|
68
|
+
*
|
|
69
|
+
* Called at build time by the compiler, or at runtime in dev mode.
|
|
70
|
+
*/
|
|
71
|
+
declare function compileAnimation(opts: AnimateOptions): CompiledAnimation;
|
|
72
|
+
/**
|
|
73
|
+
* Generate an animation class string to use in tw template literals.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* const fadeIn = animate({ from: "opacity-0", to: "opacity-100", duration: 200 })
|
|
77
|
+
* const Box = tw.div`${fadeIn} p-4 bg-white`
|
|
78
|
+
*/
|
|
79
|
+
declare function animate(opts: AnimateOptions): string;
|
|
80
|
+
/**
|
|
81
|
+
* Define a custom keyframe animation with multiple stops.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* const pulse = tw.keyframes("pulse", {
|
|
85
|
+
* "0%, 100%": "opacity-100 scale-100",
|
|
86
|
+
* "50%": "opacity-50 scale-95",
|
|
87
|
+
* })
|
|
88
|
+
* const Dot = tw.div`${pulse} w-4 h-4 rounded-full bg-blue-500`
|
|
89
|
+
*/
|
|
90
|
+
declare function keyframes(name: string, stops: KeyframesDefinition): string;
|
|
91
|
+
/**
|
|
92
|
+
* Collection of ready-to-use animation class strings.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* const Card = tw.div`${animations.fadeIn} p-4 bg-white`
|
|
96
|
+
* const Modal = tw.div`${animations.scaleIn} fixed inset-0`
|
|
97
|
+
*/
|
|
98
|
+
declare const animations: {
|
|
99
|
+
readonly fadeIn: string;
|
|
100
|
+
readonly fadeOut: string;
|
|
101
|
+
readonly slideUp: string;
|
|
102
|
+
readonly slideDown: string;
|
|
103
|
+
readonly slideLeft: string;
|
|
104
|
+
readonly slideRight: string;
|
|
105
|
+
readonly scaleIn: string;
|
|
106
|
+
readonly scaleOut: string;
|
|
107
|
+
readonly blurIn: string;
|
|
108
|
+
readonly bounceIn: string;
|
|
109
|
+
readonly spinIn: string;
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Get all compiled animation CSS to inject into a stylesheet.
|
|
113
|
+
* Called by the CSS extraction engine at build time.
|
|
114
|
+
*/
|
|
115
|
+
declare function extractAnimationCss(): string;
|
|
116
|
+
|
|
117
|
+
export { type AnimateOptions, type CompiledAnimation, type KeyframesDefinition, animate, animations, compileAnimation, extractAnimationCss, getAnimationRegistry, keyframes };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tailwind-styled-v4 — Animation DSL
|
|
3
|
+
*
|
|
4
|
+
* Compile-time animation system. Define animations dengan Tailwind class,
|
|
5
|
+
* compiler generate @keyframes — nol runtime, nol JS overhead.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
*
|
|
9
|
+
* // Cara 1: .animate() chaining pada tw component
|
|
10
|
+
* const FadeIn = tw.div.animate({
|
|
11
|
+
* from: "opacity-0 translate-y-2",
|
|
12
|
+
* to: "opacity-100 translate-y-0",
|
|
13
|
+
* duration: 300,
|
|
14
|
+
* easing: "ease-out"
|
|
15
|
+
* })
|
|
16
|
+
*
|
|
17
|
+
* // Cara 2: standalone animate() utility
|
|
18
|
+
* const fadeIn = animate({
|
|
19
|
+
* from: "opacity-0 scale-95",
|
|
20
|
+
* to: "opacity-100 scale-100",
|
|
21
|
+
* duration: 200,
|
|
22
|
+
* })
|
|
23
|
+
* const Box = tw.div`${fadeIn}`
|
|
24
|
+
*
|
|
25
|
+
* // Cara 3: preset animations
|
|
26
|
+
* const Card = tw.div`${animations.fadeIn} ${animations.slideUp}`
|
|
27
|
+
*
|
|
28
|
+
* // Cara 4: tw.keyframes() custom
|
|
29
|
+
* const spin = tw.keyframes("spin", {
|
|
30
|
+
* "0%": "rotate-0",
|
|
31
|
+
* "100%": "rotate-180",
|
|
32
|
+
* })
|
|
33
|
+
*/
|
|
34
|
+
interface AnimateOptions {
|
|
35
|
+
/** Tailwind classes for animation start state */
|
|
36
|
+
from: string;
|
|
37
|
+
/** Tailwind classes for animation end state */
|
|
38
|
+
to: string;
|
|
39
|
+
/** Duration in ms. Default: 300 */
|
|
40
|
+
duration?: number;
|
|
41
|
+
/** CSS easing. Default: "ease-out" */
|
|
42
|
+
easing?: string;
|
|
43
|
+
/** Delay in ms. Default: 0 */
|
|
44
|
+
delay?: number;
|
|
45
|
+
/** Fill mode. Default: "both" */
|
|
46
|
+
fill?: "none" | "forwards" | "backwards" | "both";
|
|
47
|
+
/** Iteration count. Default: 1 */
|
|
48
|
+
iterations?: number | "infinite";
|
|
49
|
+
/** Direction. Default: "normal" */
|
|
50
|
+
direction?: "normal" | "reverse" | "alternate" | "alternate-reverse";
|
|
51
|
+
/** Animation name override (auto-generated from from+to if not set) */
|
|
52
|
+
name?: string;
|
|
53
|
+
}
|
|
54
|
+
interface KeyframesDefinition {
|
|
55
|
+
[stop: string]: string;
|
|
56
|
+
}
|
|
57
|
+
interface CompiledAnimation {
|
|
58
|
+
/** CSS animation class name to apply */
|
|
59
|
+
className: string;
|
|
60
|
+
/** @keyframes CSS to inject */
|
|
61
|
+
keyframesCss: string;
|
|
62
|
+
/** animation CSS shorthand */
|
|
63
|
+
animationCss: string;
|
|
64
|
+
}
|
|
65
|
+
declare function getAnimationRegistry(): Map<string, CompiledAnimation>;
|
|
66
|
+
/**
|
|
67
|
+
* Compile AnimateOptions into CSS animation + @keyframes.
|
|
68
|
+
*
|
|
69
|
+
* Called at build time by the compiler, or at runtime in dev mode.
|
|
70
|
+
*/
|
|
71
|
+
declare function compileAnimation(opts: AnimateOptions): CompiledAnimation;
|
|
72
|
+
/**
|
|
73
|
+
* Generate an animation class string to use in tw template literals.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* const fadeIn = animate({ from: "opacity-0", to: "opacity-100", duration: 200 })
|
|
77
|
+
* const Box = tw.div`${fadeIn} p-4 bg-white`
|
|
78
|
+
*/
|
|
79
|
+
declare function animate(opts: AnimateOptions): string;
|
|
80
|
+
/**
|
|
81
|
+
* Define a custom keyframe animation with multiple stops.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* const pulse = tw.keyframes("pulse", {
|
|
85
|
+
* "0%, 100%": "opacity-100 scale-100",
|
|
86
|
+
* "50%": "opacity-50 scale-95",
|
|
87
|
+
* })
|
|
88
|
+
* const Dot = tw.div`${pulse} w-4 h-4 rounded-full bg-blue-500`
|
|
89
|
+
*/
|
|
90
|
+
declare function keyframes(name: string, stops: KeyframesDefinition): string;
|
|
91
|
+
/**
|
|
92
|
+
* Collection of ready-to-use animation class strings.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* const Card = tw.div`${animations.fadeIn} p-4 bg-white`
|
|
96
|
+
* const Modal = tw.div`${animations.scaleIn} fixed inset-0`
|
|
97
|
+
*/
|
|
98
|
+
declare const animations: {
|
|
99
|
+
readonly fadeIn: string;
|
|
100
|
+
readonly fadeOut: string;
|
|
101
|
+
readonly slideUp: string;
|
|
102
|
+
readonly slideDown: string;
|
|
103
|
+
readonly slideLeft: string;
|
|
104
|
+
readonly slideRight: string;
|
|
105
|
+
readonly scaleIn: string;
|
|
106
|
+
readonly scaleOut: string;
|
|
107
|
+
readonly blurIn: string;
|
|
108
|
+
readonly bounceIn: string;
|
|
109
|
+
readonly spinIn: string;
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Get all compiled animation CSS to inject into a stylesheet.
|
|
113
|
+
* Called by the CSS extraction engine at build time.
|
|
114
|
+
*/
|
|
115
|
+
declare function extractAnimationCss(): string;
|
|
116
|
+
|
|
117
|
+
export { type AnimateOptions, type CompiledAnimation, type KeyframesDefinition, animate, animations, compileAnimation, extractAnimationCss, getAnimationRegistry, keyframes };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
var TW_TO_CSS = {
|
|
3
|
+
// Opacity
|
|
4
|
+
"opacity-0": "opacity: 0",
|
|
5
|
+
"opacity-5": "opacity: 0.05",
|
|
6
|
+
"opacity-10": "opacity: 0.1",
|
|
7
|
+
"opacity-20": "opacity: 0.2",
|
|
8
|
+
"opacity-25": "opacity: 0.25",
|
|
9
|
+
"opacity-30": "opacity: 0.3",
|
|
10
|
+
"opacity-40": "opacity: 0.4",
|
|
11
|
+
"opacity-50": "opacity: 0.5",
|
|
12
|
+
"opacity-60": "opacity: 0.6",
|
|
13
|
+
"opacity-70": "opacity: 0.7",
|
|
14
|
+
"opacity-75": "opacity: 0.75",
|
|
15
|
+
"opacity-80": "opacity: 0.8",
|
|
16
|
+
"opacity-90": "opacity: 0.9",
|
|
17
|
+
"opacity-95": "opacity: 0.95",
|
|
18
|
+
"opacity-100": "opacity: 1",
|
|
19
|
+
// Translate Y
|
|
20
|
+
"translate-y-0": "transform: translateY(0px)",
|
|
21
|
+
"translate-y-0.5": "transform: translateY(0.125rem)",
|
|
22
|
+
"translate-y-1": "transform: translateY(0.25rem)",
|
|
23
|
+
"translate-y-2": "transform: translateY(0.5rem)",
|
|
24
|
+
"translate-y-3": "transform: translateY(0.75rem)",
|
|
25
|
+
"translate-y-4": "transform: translateY(1rem)",
|
|
26
|
+
"translate-y-6": "transform: translateY(1.5rem)",
|
|
27
|
+
"translate-y-8": "transform: translateY(2rem)",
|
|
28
|
+
"-translate-y-1": "transform: translateY(-0.25rem)",
|
|
29
|
+
"-translate-y-2": "transform: translateY(-0.5rem)",
|
|
30
|
+
"-translate-y-4": "transform: translateY(-1rem)",
|
|
31
|
+
"-translate-y-8": "transform: translateY(-2rem)",
|
|
32
|
+
// Translate X
|
|
33
|
+
"translate-x-0": "transform: translateX(0px)",
|
|
34
|
+
"translate-x-1": "transform: translateX(0.25rem)",
|
|
35
|
+
"translate-x-2": "transform: translateX(0.5rem)",
|
|
36
|
+
"translate-x-4": "transform: translateX(1rem)",
|
|
37
|
+
"-translate-x-1": "transform: translateX(-0.25rem)",
|
|
38
|
+
"-translate-x-2": "transform: translateX(-0.5rem)",
|
|
39
|
+
"-translate-x-4": "transform: translateX(-1rem)",
|
|
40
|
+
// Scale
|
|
41
|
+
"scale-0": "transform: scale(0)",
|
|
42
|
+
"scale-50": "transform: scale(0.5)",
|
|
43
|
+
"scale-75": "transform: scale(0.75)",
|
|
44
|
+
"scale-90": "transform: scale(0.9)",
|
|
45
|
+
"scale-95": "transform: scale(0.95)",
|
|
46
|
+
"scale-100": "transform: scale(1)",
|
|
47
|
+
"scale-105": "transform: scale(1.05)",
|
|
48
|
+
"scale-110": "transform: scale(1.1)",
|
|
49
|
+
"scale-125": "transform: scale(1.25)",
|
|
50
|
+
"scale-150": "transform: scale(1.5)",
|
|
51
|
+
// Rotate
|
|
52
|
+
"rotate-0": "transform: rotate(0deg)",
|
|
53
|
+
"rotate-1": "transform: rotate(1deg)",
|
|
54
|
+
"rotate-2": "transform: rotate(2deg)",
|
|
55
|
+
"rotate-3": "transform: rotate(3deg)",
|
|
56
|
+
"rotate-6": "transform: rotate(6deg)",
|
|
57
|
+
"rotate-12": "transform: rotate(12deg)",
|
|
58
|
+
"rotate-45": "transform: rotate(45deg)",
|
|
59
|
+
"rotate-90": "transform: rotate(90deg)",
|
|
60
|
+
"rotate-180": "transform: rotate(180deg)",
|
|
61
|
+
"-rotate-1": "transform: rotate(-1deg)",
|
|
62
|
+
"-rotate-2": "transform: rotate(-2deg)",
|
|
63
|
+
"-rotate-6": "transform: rotate(-6deg)",
|
|
64
|
+
"-rotate-12": "transform: rotate(-12deg)",
|
|
65
|
+
"-rotate-45": "transform: rotate(-45deg)",
|
|
66
|
+
"-rotate-90": "transform: rotate(-90deg)",
|
|
67
|
+
// Blur
|
|
68
|
+
"blur-none": "filter: blur(0)",
|
|
69
|
+
"blur-sm": "filter: blur(4px)",
|
|
70
|
+
blur: "filter: blur(8px)",
|
|
71
|
+
"blur-md": "filter: blur(12px)",
|
|
72
|
+
"blur-lg": "filter: blur(16px)",
|
|
73
|
+
"blur-xl": "filter: blur(24px)",
|
|
74
|
+
"blur-2xl": "filter: blur(40px)",
|
|
75
|
+
"blur-3xl": "filter: blur(64px)"
|
|
76
|
+
};
|
|
77
|
+
function classesToCss(classes) {
|
|
78
|
+
const parts = classes.split(/\s+/).filter(Boolean);
|
|
79
|
+
const transforms = [];
|
|
80
|
+
const others = [];
|
|
81
|
+
for (const cls of parts) {
|
|
82
|
+
const css = TW_TO_CSS[cls];
|
|
83
|
+
if (!css) continue;
|
|
84
|
+
if (css.startsWith("transform:")) {
|
|
85
|
+
transforms.push(css.replace("transform: ", ""));
|
|
86
|
+
} else {
|
|
87
|
+
others.push(css);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const result = [...others];
|
|
91
|
+
if (transforms.length > 0) {
|
|
92
|
+
result.push(`transform: ${transforms.join(" ")}`);
|
|
93
|
+
}
|
|
94
|
+
return result.join("; ");
|
|
95
|
+
}
|
|
96
|
+
var _animCounter = 0;
|
|
97
|
+
function genAnimId(name) {
|
|
98
|
+
if (name) return `tw-${name.replace(/[^a-zA-Z0-9]/g, "-")}`;
|
|
99
|
+
return `tw-anim-${++_animCounter}`;
|
|
100
|
+
}
|
|
101
|
+
var _animRegistry = /* @__PURE__ */ new Map();
|
|
102
|
+
function getAnimationRegistry() {
|
|
103
|
+
return _animRegistry;
|
|
104
|
+
}
|
|
105
|
+
function compileAnimation(opts) {
|
|
106
|
+
const {
|
|
107
|
+
from,
|
|
108
|
+
to,
|
|
109
|
+
duration = 300,
|
|
110
|
+
easing = "ease-out",
|
|
111
|
+
delay = 0,
|
|
112
|
+
fill = "both",
|
|
113
|
+
iterations = 1,
|
|
114
|
+
direction = "normal",
|
|
115
|
+
name
|
|
116
|
+
} = opts;
|
|
117
|
+
const animId = genAnimId(
|
|
118
|
+
name != null ? name : `${from.replace(/\s+/g, "-")}-${to.replace(/\s+/g, "-")}`.slice(0, 30)
|
|
119
|
+
);
|
|
120
|
+
if (_animRegistry.has(animId)) {
|
|
121
|
+
return _animRegistry.get(animId);
|
|
122
|
+
}
|
|
123
|
+
const fromCss = classesToCss(from);
|
|
124
|
+
const toCss = classesToCss(to);
|
|
125
|
+
const keyframesCss = [
|
|
126
|
+
`@keyframes ${animId} {`,
|
|
127
|
+
fromCss ? ` from { ${fromCss} }` : ` from {}`,
|
|
128
|
+
toCss ? ` to { ${toCss} }` : ` to {}`,
|
|
129
|
+
`}`
|
|
130
|
+
].join("\n");
|
|
131
|
+
const iterStr = iterations === "infinite" ? "infinite" : String(iterations);
|
|
132
|
+
const animationCss = [
|
|
133
|
+
`animation-name: ${animId}`,
|
|
134
|
+
`animation-duration: ${duration}ms`,
|
|
135
|
+
`animation-timing-function: ${easing}`,
|
|
136
|
+
`animation-delay: ${delay}ms`,
|
|
137
|
+
`animation-fill-mode: ${fill}`,
|
|
138
|
+
`animation-iteration-count: ${iterStr}`,
|
|
139
|
+
`animation-direction: ${direction}`
|
|
140
|
+
].join("; ");
|
|
141
|
+
const className = animId;
|
|
142
|
+
const compiled = { className, keyframesCss, animationCss };
|
|
143
|
+
_animRegistry.set(animId, compiled);
|
|
144
|
+
return compiled;
|
|
145
|
+
}
|
|
146
|
+
function animate(opts) {
|
|
147
|
+
const compiled = compileAnimation(opts);
|
|
148
|
+
if (typeof document !== "undefined") {
|
|
149
|
+
const styleId = `__tw_anim_${compiled.className}`;
|
|
150
|
+
if (!document.getElementById(styleId)) {
|
|
151
|
+
const style = document.createElement("style");
|
|
152
|
+
style.id = styleId;
|
|
153
|
+
style.textContent = `${compiled.keyframesCss}
|
|
154
|
+
.${compiled.className}{${compiled.animationCss}}`;
|
|
155
|
+
document.head.appendChild(style);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return compiled.className;
|
|
159
|
+
}
|
|
160
|
+
function keyframes(name, stops) {
|
|
161
|
+
const animId = genAnimId(name);
|
|
162
|
+
if (_animRegistry.has(animId)) {
|
|
163
|
+
return animId;
|
|
164
|
+
}
|
|
165
|
+
const stopLines = Object.entries(stops).map(([stop, classes]) => {
|
|
166
|
+
const css = classesToCss(classes);
|
|
167
|
+
return ` ${stop} { ${css} }`;
|
|
168
|
+
}).join("\n");
|
|
169
|
+
const keyframesCss = `@keyframes ${animId} {
|
|
170
|
+
${stopLines}
|
|
171
|
+
}`;
|
|
172
|
+
if (typeof document !== "undefined") {
|
|
173
|
+
const styleId = `__tw_kf_${animId}`;
|
|
174
|
+
if (!document.getElementById(styleId)) {
|
|
175
|
+
const style = document.createElement("style");
|
|
176
|
+
style.id = styleId;
|
|
177
|
+
style.textContent = keyframesCss;
|
|
178
|
+
document.head.appendChild(style);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
_animRegistry.set(animId, {
|
|
182
|
+
className: animId,
|
|
183
|
+
keyframesCss,
|
|
184
|
+
animationCss: `animation-name: ${animId}`
|
|
185
|
+
});
|
|
186
|
+
return animId;
|
|
187
|
+
}
|
|
188
|
+
var animations = {
|
|
189
|
+
fadeIn: animate({ from: "opacity-0", to: "opacity-100", duration: 200 }),
|
|
190
|
+
fadeOut: animate({ from: "opacity-100", to: "opacity-0", duration: 200 }),
|
|
191
|
+
slideUp: animate({
|
|
192
|
+
from: "opacity-0 translate-y-4",
|
|
193
|
+
to: "opacity-100 translate-y-0",
|
|
194
|
+
duration: 300
|
|
195
|
+
}),
|
|
196
|
+
slideDown: animate({
|
|
197
|
+
from: "opacity-0 -translate-y-4",
|
|
198
|
+
to: "opacity-100 translate-y-0",
|
|
199
|
+
duration: 300
|
|
200
|
+
}),
|
|
201
|
+
slideLeft: animate({
|
|
202
|
+
from: "opacity-0 translate-x-4",
|
|
203
|
+
to: "opacity-100 translate-x-0",
|
|
204
|
+
duration: 300
|
|
205
|
+
}),
|
|
206
|
+
slideRight: animate({
|
|
207
|
+
from: "opacity-0 -translate-x-4",
|
|
208
|
+
to: "opacity-100 translate-x-0",
|
|
209
|
+
duration: 300
|
|
210
|
+
}),
|
|
211
|
+
scaleIn: animate({
|
|
212
|
+
from: "opacity-0 scale-95",
|
|
213
|
+
to: "opacity-100 scale-100",
|
|
214
|
+
duration: 200,
|
|
215
|
+
easing: "cubic-bezier(0.16,1,0.3,1)"
|
|
216
|
+
}),
|
|
217
|
+
scaleOut: animate({ from: "opacity-100 scale-100", to: "opacity-0 scale-95", duration: 150 }),
|
|
218
|
+
blurIn: animate({ from: "opacity-0 blur-sm", to: "opacity-100 blur-none", duration: 300 }),
|
|
219
|
+
bounceIn: animate({
|
|
220
|
+
from: "opacity-0 scale-50",
|
|
221
|
+
to: "opacity-100 scale-100",
|
|
222
|
+
duration: 400,
|
|
223
|
+
easing: "cubic-bezier(0.34,1.56,0.64,1)"
|
|
224
|
+
}),
|
|
225
|
+
spinIn: animate({
|
|
226
|
+
from: "opacity-0 rotate-180 scale-50",
|
|
227
|
+
to: "opacity-100 rotate-0 scale-100",
|
|
228
|
+
duration: 400,
|
|
229
|
+
easing: "cubic-bezier(0.16,1,0.3,1)"
|
|
230
|
+
})
|
|
231
|
+
};
|
|
232
|
+
function extractAnimationCss() {
|
|
233
|
+
const lines = [];
|
|
234
|
+
for (const [, compiled] of _animRegistry) {
|
|
235
|
+
lines.push(compiled.keyframesCss);
|
|
236
|
+
lines.push(`.${compiled.className} { ${compiled.animationCss} }`);
|
|
237
|
+
}
|
|
238
|
+
return lines.join("\n\n");
|
|
239
|
+
}
|
|
240
|
+
export {
|
|
241
|
+
animate,
|
|
242
|
+
animations,
|
|
243
|
+
compileAnimation,
|
|
244
|
+
extractAnimationCss,
|
|
245
|
+
getAnimationRegistry,
|
|
246
|
+
keyframes
|
|
247
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tailwind-styled/animate",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Compile-time animation DSL for tailwind-styled-v4 — zero-runtime @keyframes generation",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"require": "./dist/index.cjs"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": ["dist"],
|
|
18
|
+
"sideEffects": false,
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --out-dir dist --clean",
|
|
21
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --out-dir dist --watch"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"tsup": "^8",
|
|
25
|
+
"typescript": "^5"
|
|
26
|
+
}
|
|
27
|
+
}
|