@timbal-ai/timbal-react 1.5.0 → 1.6.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/CHANGELOG.md +17 -1
- package/README.md +25 -0
- package/dist/app.cjs +855 -640
- package/dist/app.d.cts +4 -4
- package/dist/app.d.ts +4 -4
- package/dist/app.esm.js +6 -6
- package/dist/{chart-artifact-2OTDTRwM.d.ts → chart-artifact-C2pZQsaP.d.ts} +81 -29
- package/dist/{chart-artifact-CS3qyGIY.d.cts → chart-artifact-VAqgH-My.d.cts} +81 -29
- package/dist/{chat-ClmzWzCX.d.cts → chat-DDsp-Vzz.d.cts} +1 -1
- package/dist/{chat-ClmzWzCX.d.ts → chat-DDsp-Vzz.d.ts} +1 -1
- package/dist/chat.cjs +26 -26
- package/dist/chat.d.cts +3 -3
- package/dist/chat.d.ts +3 -3
- package/dist/chat.esm.js +3 -3
- package/dist/{chunk-TZI3ID3C.esm.js → chunk-24B4I4XC.esm.js} +3 -3
- package/dist/{chunk-SZDYIRMB.esm.js → chunk-6SQMTBPL.esm.js} +618 -530
- package/dist/{chunk-QIABF4KB.esm.js → chunk-ELEY66OH.esm.js} +2 -2
- package/dist/{chunk-WMKPT5BV.esm.js → chunk-HSL36SJ4.esm.js} +6 -6
- package/dist/chunk-JJOO4PR5.esm.js +391 -0
- package/dist/{chunk-AZL2WANO.esm.js → chunk-MBS7XHV2.esm.js} +28 -28
- package/dist/{chunk-5ECRZ5O7.esm.js → chunk-NO5AWNWT.esm.js} +224 -57
- package/dist/{chunk-ZNYAETFD.esm.js → chunk-R4RQT2XQ.esm.js} +2 -2
- package/dist/{chunk-JYDJRGDE.esm.js → chunk-TMP7RIA7.esm.js} +2 -2
- package/dist/{chunk-IGHBLJV3.esm.js → chunk-WQIQW7EM.esm.js} +3 -2
- package/dist/{chunk-B4XAC4G7.esm.js → chunk-YYEI6XME.esm.js} +361 -527
- package/dist/{circular-progress-CDsJwIPF.d.cts → circular-progress-B9nnwzCu.d.cts} +1 -1
- package/dist/{circular-progress-CDsJwIPF.d.ts → circular-progress-B9nnwzCu.d.ts} +1 -1
- package/dist/index.cjs +1327 -852
- package/dist/index.d.cts +9 -8
- package/dist/index.d.ts +9 -8
- package/dist/index.esm.js +40 -20
- package/dist/{kanban-U5xNe9py.d.cts → kanban-FFBeaZPS.d.cts} +4 -4
- package/dist/{kanban-U5xNe9py.d.ts → kanban-FFBeaZPS.d.ts} +4 -4
- package/dist/{layout-B8r6Jbat.d.ts → layout-CuKeSY74.d.ts} +1 -1
- package/dist/{layout-Cu7Ijn04.d.cts → layout-PzVwkJyL.d.cts} +1 -1
- package/dist/site.cjs +71 -0
- package/dist/site.d.cts +15 -1
- package/dist/site.d.ts +15 -1
- package/dist/site.esm.js +12 -311
- package/dist/studio.cjs +31 -31
- package/dist/studio.d.cts +2 -2
- package/dist/studio.d.ts +2 -2
- package/dist/studio.esm.js +7 -7
- package/dist/{timbal-v2-button-B7vPs7gg.d.ts → timbal-v2-button-DCAZNyUx.d.cts} +1 -1
- package/dist/{timbal-v2-button-B7vPs7gg.d.cts → timbal-v2-button-DCAZNyUx.d.ts} +1 -1
- package/dist/ui.cjs +77 -77
- package/dist/ui.d.cts +3 -3
- package/dist/ui.d.ts +3 -3
- package/dist/ui.esm.js +15 -15
- package/dist/{welcome-NXZlcihe.d.cts → welcome-B00oH5Io.d.cts} +1 -1
- package/dist/{welcome-DduQAC4K.d.ts → welcome-DU-4NTjZ.d.ts} +1 -1
- package/package.json +1 -1
|
@@ -5,8 +5,8 @@ var SIDEBAR_MOBILE_PX = 272;
|
|
|
5
5
|
var SIDEBAR_GAP_PX = 12;
|
|
6
6
|
var SIDEBAR_CONTENT_GAP_PX = 8;
|
|
7
7
|
var TOPBAR_GAP_PX = 8;
|
|
8
|
-
var TOPBAR_HEIGHT_PX =
|
|
9
|
-
var PILL_HEIGHT_PX =
|
|
8
|
+
var TOPBAR_HEIGHT_PX = 44;
|
|
9
|
+
var PILL_HEIGHT_PX = 36;
|
|
10
10
|
var SIDEBAR_INSET_PX_EXPANDED = SIDEBAR_GAP_PX + SIDEBAR_WIDTH_PX + SIDEBAR_CONTENT_GAP_PX;
|
|
11
11
|
var SIDEBAR_INSET_PX_COLLAPSED = SIDEBAR_GAP_PX + SIDEBAR_WIDTH_COLLAPSED_PX + SIDEBAR_CONTENT_GAP_PX;
|
|
12
12
|
var px = (n) => `${n / 16}rem`;
|
|
@@ -17,10 +17,10 @@ import {
|
|
|
17
17
|
studioSidebarEntryItemVariants,
|
|
18
18
|
studioSidebarWidthTransition,
|
|
19
19
|
useShellInsetReporter
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-ELEY66OH.esm.js";
|
|
21
21
|
import {
|
|
22
22
|
WorkforceSelector
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-TMP7RIA7.esm.js";
|
|
24
24
|
import {
|
|
25
25
|
Composer,
|
|
26
26
|
TimbalChat,
|
|
@@ -43,7 +43,7 @@ import {
|
|
|
43
43
|
studioTopbarIconPillClass,
|
|
44
44
|
studioTopbarPillHeightClass,
|
|
45
45
|
useTimbalRuntime
|
|
46
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-WQIQW7EM.esm.js";
|
|
47
47
|
import {
|
|
48
48
|
DropdownMenu,
|
|
49
49
|
DropdownMenuContent,
|
|
@@ -51,10 +51,10 @@ import {
|
|
|
51
51
|
DropdownMenuLabel,
|
|
52
52
|
DropdownMenuSeparator,
|
|
53
53
|
DropdownMenuTrigger
|
|
54
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-24B4I4XC.esm.js";
|
|
55
55
|
import {
|
|
56
56
|
PillSegmentedTabs
|
|
57
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-R4RQT2XQ.esm.js";
|
|
58
58
|
import {
|
|
59
59
|
Avatar,
|
|
60
60
|
AvatarFallback,
|
|
@@ -63,7 +63,7 @@ import {
|
|
|
63
63
|
Tooltip,
|
|
64
64
|
TooltipContent,
|
|
65
65
|
TooltipTrigger
|
|
66
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-MBS7XHV2.esm.js";
|
|
67
67
|
import {
|
|
68
68
|
cn
|
|
69
69
|
} from "./chunk-EDEKQYSU.esm.js";
|
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cn
|
|
3
|
+
} from "./chunk-EDEKQYSU.esm.js";
|
|
4
|
+
|
|
5
|
+
// src/site/easing.ts
|
|
6
|
+
var EASE = {
|
|
7
|
+
/** Strong slow-out — the workhorse for entrances and reveals. */
|
|
8
|
+
out: [0.16, 1, 0.3, 1],
|
|
9
|
+
/** Symmetric in-out for loops and continuous motion. */
|
|
10
|
+
inOut: [0.65, 0, 0.35, 1],
|
|
11
|
+
/** Gentle in-out, good for parallax / large translations. */
|
|
12
|
+
soft: [0.4, 0, 0.2, 1]
|
|
13
|
+
};
|
|
14
|
+
var DURATION = {
|
|
15
|
+
fast: 0.4,
|
|
16
|
+
base: 0.7,
|
|
17
|
+
slow: 1.1
|
|
18
|
+
};
|
|
19
|
+
var SPRING = {
|
|
20
|
+
/** Tight, responsive follow. */
|
|
21
|
+
snappy: { stiffness: 350, damping: 30, mass: 0.4 },
|
|
22
|
+
/** Looser, more elastic follow. */
|
|
23
|
+
smooth: { stiffness: 150, damping: 20, mass: 0.6 }
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// src/site/Reveal.tsx
|
|
27
|
+
import * as React from "react";
|
|
28
|
+
import { motion, useReducedMotion } from "motion/react";
|
|
29
|
+
import { jsx } from "react/jsx-runtime";
|
|
30
|
+
function hidden(variant, distance) {
|
|
31
|
+
switch (variant) {
|
|
32
|
+
case "fade":
|
|
33
|
+
return { opacity: 0 };
|
|
34
|
+
case "fade-up":
|
|
35
|
+
return { opacity: 0, y: distance };
|
|
36
|
+
case "fade-down":
|
|
37
|
+
return { opacity: 0, y: -distance };
|
|
38
|
+
case "fade-left":
|
|
39
|
+
return { opacity: 0, x: distance };
|
|
40
|
+
case "fade-right":
|
|
41
|
+
return { opacity: 0, x: -distance };
|
|
42
|
+
case "blur":
|
|
43
|
+
return { opacity: 0, filter: "blur(12px)" };
|
|
44
|
+
case "scale":
|
|
45
|
+
return { opacity: 0, scale: 0.94 };
|
|
46
|
+
case "mask-up":
|
|
47
|
+
return { y: "110%" };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function shown(variant) {
|
|
51
|
+
if (variant === "mask-up") return { y: "0%" };
|
|
52
|
+
if (variant === "blur") return { opacity: 1, filter: "blur(0px)" };
|
|
53
|
+
if (variant === "scale") return { opacity: 1, scale: 1 };
|
|
54
|
+
return { opacity: 1, x: 0, y: 0 };
|
|
55
|
+
}
|
|
56
|
+
var Reveal = React.forwardRef(function Reveal2({
|
|
57
|
+
variant = "fade-up",
|
|
58
|
+
delay = 0,
|
|
59
|
+
duration = DURATION.base,
|
|
60
|
+
distance = 28,
|
|
61
|
+
amount = 0.3,
|
|
62
|
+
repeat = false,
|
|
63
|
+
as = "div",
|
|
64
|
+
className,
|
|
65
|
+
children,
|
|
66
|
+
...rest
|
|
67
|
+
}, ref) {
|
|
68
|
+
const reduce = useReducedMotion();
|
|
69
|
+
const isMask = variant === "mask-up";
|
|
70
|
+
if (reduce) {
|
|
71
|
+
const Tag = as;
|
|
72
|
+
return /* @__PURE__ */ jsx(Tag, { ref, className: cn(isMask && "overflow-hidden", className), ...rest, children });
|
|
73
|
+
}
|
|
74
|
+
const variants = {
|
|
75
|
+
hidden: hidden(variant, distance),
|
|
76
|
+
shown: shown(variant)
|
|
77
|
+
};
|
|
78
|
+
const MotionTag = motion[as] ?? motion.div;
|
|
79
|
+
const inner = /* @__PURE__ */ jsx(
|
|
80
|
+
MotionTag,
|
|
81
|
+
{
|
|
82
|
+
ref,
|
|
83
|
+
className,
|
|
84
|
+
variants,
|
|
85
|
+
initial: "hidden",
|
|
86
|
+
whileInView: "shown",
|
|
87
|
+
viewport: { once: !repeat, amount },
|
|
88
|
+
transition: { duration, delay, ease: EASE.out },
|
|
89
|
+
...rest,
|
|
90
|
+
children
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
if (isMask) {
|
|
94
|
+
return /* @__PURE__ */ jsx("span", { className: "block overflow-hidden", children: inner });
|
|
95
|
+
}
|
|
96
|
+
return inner;
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// src/site/TextReveal.tsx
|
|
100
|
+
import * as React2 from "react";
|
|
101
|
+
import { motion as motion2, useReducedMotion as useReducedMotion2 } from "motion/react";
|
|
102
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
103
|
+
var tokenVariants = {
|
|
104
|
+
hidden: { y: "115%" },
|
|
105
|
+
shown: { y: "0%" }
|
|
106
|
+
};
|
|
107
|
+
function TextReveal({
|
|
108
|
+
children,
|
|
109
|
+
splitBy = "words",
|
|
110
|
+
stagger = 0.06,
|
|
111
|
+
delay = 0,
|
|
112
|
+
duration = DURATION.base,
|
|
113
|
+
repeat = false,
|
|
114
|
+
amount = 0.4,
|
|
115
|
+
as = "span",
|
|
116
|
+
className,
|
|
117
|
+
...rest
|
|
118
|
+
}) {
|
|
119
|
+
const reduce = useReducedMotion2();
|
|
120
|
+
const Tag = as;
|
|
121
|
+
const tokens = React2.useMemo(() => {
|
|
122
|
+
if (splitBy === "lines") return children.split("\n");
|
|
123
|
+
return children.split(/(\s+)/).filter((t) => t.length > 0);
|
|
124
|
+
}, [children, splitBy]);
|
|
125
|
+
if (reduce) {
|
|
126
|
+
return /* @__PURE__ */ jsx2(Tag, { className, ...rest, children });
|
|
127
|
+
}
|
|
128
|
+
const containerVariants = {
|
|
129
|
+
hidden: {},
|
|
130
|
+
shown: { transition: { staggerChildren: stagger, delayChildren: delay } }
|
|
131
|
+
};
|
|
132
|
+
return /* @__PURE__ */ jsx2(
|
|
133
|
+
motion2.span,
|
|
134
|
+
{
|
|
135
|
+
variants: containerVariants,
|
|
136
|
+
initial: "hidden",
|
|
137
|
+
whileInView: "shown",
|
|
138
|
+
viewport: { once: !repeat, amount },
|
|
139
|
+
className: cn(as === "span" ? "inline" : "block", className),
|
|
140
|
+
...rest,
|
|
141
|
+
children: /* @__PURE__ */ jsx2(Tag, { className: as === "span" ? "inline" : "block", children: tokens.map(
|
|
142
|
+
(token, i) => /^\s+$/.test(token) && splitBy === "words" ? /* @__PURE__ */ jsx2("span", { children: " " }, i) : /* @__PURE__ */ jsx2(
|
|
143
|
+
"span",
|
|
144
|
+
{
|
|
145
|
+
className: cn(
|
|
146
|
+
"overflow-hidden",
|
|
147
|
+
splitBy === "lines" ? "block" : "inline-block align-bottom"
|
|
148
|
+
),
|
|
149
|
+
children: /* @__PURE__ */ jsx2(
|
|
150
|
+
motion2.span,
|
|
151
|
+
{
|
|
152
|
+
className: "inline-block",
|
|
153
|
+
variants: tokenVariants,
|
|
154
|
+
transition: { duration, ease: EASE.out },
|
|
155
|
+
children: token
|
|
156
|
+
}
|
|
157
|
+
)
|
|
158
|
+
},
|
|
159
|
+
i
|
|
160
|
+
)
|
|
161
|
+
) })
|
|
162
|
+
}
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// src/site/Parallax.tsx
|
|
167
|
+
import * as React3 from "react";
|
|
168
|
+
import {
|
|
169
|
+
motion as motion3,
|
|
170
|
+
useReducedMotion as useReducedMotion3,
|
|
171
|
+
useScroll,
|
|
172
|
+
useSpring,
|
|
173
|
+
useTransform
|
|
174
|
+
} from "motion/react";
|
|
175
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
176
|
+
var Parallax = React3.forwardRef(function Parallax2({ speed = 0.2, axis = "y", smooth = true, className, children, style, ...rest }, forwardedRef) {
|
|
177
|
+
const reduce = useReducedMotion3();
|
|
178
|
+
const innerRef = React3.useRef(null);
|
|
179
|
+
React3.useImperativeHandle(forwardedRef, () => innerRef.current);
|
|
180
|
+
const { scrollYProgress } = useScroll({
|
|
181
|
+
target: innerRef,
|
|
182
|
+
offset: ["start end", "end start"]
|
|
183
|
+
});
|
|
184
|
+
const range = 100 * speed;
|
|
185
|
+
const raw = useTransform(scrollYProgress, [0, 1], [range, -range]);
|
|
186
|
+
const smoothed = useSpring(raw, { stiffness: 120, damping: 30, mass: 0.4 });
|
|
187
|
+
const value = smooth ? smoothed : raw;
|
|
188
|
+
if (reduce) {
|
|
189
|
+
return /* @__PURE__ */ jsx3("div", { ref: innerRef, className, style, ...rest, children });
|
|
190
|
+
}
|
|
191
|
+
return /* @__PURE__ */ jsx3(
|
|
192
|
+
motion3.div,
|
|
193
|
+
{
|
|
194
|
+
ref: innerRef,
|
|
195
|
+
className: cn("will-change-transform", className),
|
|
196
|
+
style: { ...style, [axis]: value },
|
|
197
|
+
...rest,
|
|
198
|
+
children
|
|
199
|
+
}
|
|
200
|
+
);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
// src/site/Marquee.tsx
|
|
204
|
+
import * as React4 from "react";
|
|
205
|
+
import {
|
|
206
|
+
motion as motion4,
|
|
207
|
+
useAnimationFrame,
|
|
208
|
+
useMotionValue,
|
|
209
|
+
useReducedMotion as useReducedMotion4
|
|
210
|
+
} from "motion/react";
|
|
211
|
+
import { jsx as jsx4, jsxs } from "react/jsx-runtime";
|
|
212
|
+
var Marquee = React4.forwardRef(function Marquee2({ speed = 60, direction = "left", pauseOnHover = true, gap = "3rem", className, children, ...rest }, ref) {
|
|
213
|
+
const reduce = useReducedMotion4();
|
|
214
|
+
const x = useMotionValue(0);
|
|
215
|
+
const setWidthRef = React4.useRef(0);
|
|
216
|
+
const groupRef = React4.useRef(null);
|
|
217
|
+
const [paused, setPaused] = React4.useState(false);
|
|
218
|
+
React4.useEffect(() => {
|
|
219
|
+
const el = groupRef.current;
|
|
220
|
+
if (!el) return;
|
|
221
|
+
const measure = () => {
|
|
222
|
+
const gapPx = parseFloat(getComputedStyle(el.parentElement).columnGap || "0") || 0;
|
|
223
|
+
setWidthRef.current = el.offsetWidth + gapPx;
|
|
224
|
+
};
|
|
225
|
+
measure();
|
|
226
|
+
const ro = new ResizeObserver(measure);
|
|
227
|
+
ro.observe(el);
|
|
228
|
+
return () => ro.disconnect();
|
|
229
|
+
}, []);
|
|
230
|
+
useAnimationFrame((_, delta) => {
|
|
231
|
+
if (reduce || paused || setWidthRef.current === 0) return;
|
|
232
|
+
const dir = direction === "left" ? -1 : 1;
|
|
233
|
+
const moveBy = speed * delta / 1e3;
|
|
234
|
+
let next = x.get() + dir * moveBy;
|
|
235
|
+
const w = setWidthRef.current;
|
|
236
|
+
if (next <= -w) next += w;
|
|
237
|
+
else if (next >= w) next -= w;
|
|
238
|
+
x.set(next);
|
|
239
|
+
});
|
|
240
|
+
if (reduce) {
|
|
241
|
+
return /* @__PURE__ */ jsx4(
|
|
242
|
+
"div",
|
|
243
|
+
{
|
|
244
|
+
ref,
|
|
245
|
+
className: cn("flex w-full items-center overflow-x-auto", className),
|
|
246
|
+
style: { columnGap: gap },
|
|
247
|
+
...rest,
|
|
248
|
+
children
|
|
249
|
+
}
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
return /* @__PURE__ */ jsx4(
|
|
253
|
+
"div",
|
|
254
|
+
{
|
|
255
|
+
ref,
|
|
256
|
+
className: cn("w-full overflow-hidden", className),
|
|
257
|
+
onMouseEnter: pauseOnHover ? () => setPaused(true) : void 0,
|
|
258
|
+
onMouseLeave: pauseOnHover ? () => setPaused(false) : void 0,
|
|
259
|
+
...rest,
|
|
260
|
+
children: /* @__PURE__ */ jsxs(motion4.div, { className: "flex w-max flex-nowrap items-center", style: { x, columnGap: gap }, children: [
|
|
261
|
+
/* @__PURE__ */ jsx4("div", { ref: groupRef, className: "flex flex-nowrap items-center", style: { columnGap: gap }, children }),
|
|
262
|
+
/* @__PURE__ */ jsx4("div", { className: "flex flex-nowrap items-center", style: { columnGap: gap }, "aria-hidden": true, children })
|
|
263
|
+
] })
|
|
264
|
+
}
|
|
265
|
+
);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
// src/site/Magnetic.tsx
|
|
269
|
+
import * as React5 from "react";
|
|
270
|
+
import { motion as motion5, useMotionValue as useMotionValue2, useReducedMotion as useReducedMotion5, useSpring as useSpring2 } from "motion/react";
|
|
271
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
272
|
+
var Magnetic = React5.forwardRef(function Magnetic2({ strength = 0.35, max = 24, spring = "snappy", className, children, ...rest }, forwardedRef) {
|
|
273
|
+
const reduce = useReducedMotion5();
|
|
274
|
+
const innerRef = React5.useRef(null);
|
|
275
|
+
React5.useImperativeHandle(forwardedRef, () => innerRef.current);
|
|
276
|
+
const mvx = useMotionValue2(0);
|
|
277
|
+
const mvy = useMotionValue2(0);
|
|
278
|
+
const x = useSpring2(mvx, SPRING[spring]);
|
|
279
|
+
const y = useSpring2(mvy, SPRING[spring]);
|
|
280
|
+
const clamp = (v) => Math.max(-max, Math.min(max, v));
|
|
281
|
+
function handleMove(e) {
|
|
282
|
+
if (reduce) return;
|
|
283
|
+
const el = innerRef.current;
|
|
284
|
+
if (!el) return;
|
|
285
|
+
const rect = el.getBoundingClientRect();
|
|
286
|
+
const cx = rect.left + rect.width / 2;
|
|
287
|
+
const cy = rect.top + rect.height / 2;
|
|
288
|
+
mvx.set(clamp((e.clientX - cx) * strength));
|
|
289
|
+
mvy.set(clamp((e.clientY - cy) * strength));
|
|
290
|
+
}
|
|
291
|
+
function reset() {
|
|
292
|
+
mvx.set(0);
|
|
293
|
+
mvy.set(0);
|
|
294
|
+
}
|
|
295
|
+
if (reduce) {
|
|
296
|
+
return /* @__PURE__ */ jsx5("div", { ref: innerRef, className: cn("inline-block", className), ...rest, children });
|
|
297
|
+
}
|
|
298
|
+
return /* @__PURE__ */ jsx5(
|
|
299
|
+
motion5.div,
|
|
300
|
+
{
|
|
301
|
+
ref: innerRef,
|
|
302
|
+
className: cn("inline-block", className),
|
|
303
|
+
style: { x, y },
|
|
304
|
+
onMouseMove: handleMove,
|
|
305
|
+
onMouseLeave: reset,
|
|
306
|
+
...rest,
|
|
307
|
+
children
|
|
308
|
+
}
|
|
309
|
+
);
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
// src/site/agent-instructions.ts
|
|
313
|
+
var SITE_AGENT_INSTRUCTIONS = `
|
|
314
|
+
## Site kit (@timbal-ai/timbal-react/site)
|
|
315
|
+
|
|
316
|
+
Expressive **motion & interaction primitives** for marketing, brand, landing, and editorial pages \u2014 the counterpart to \`/app\` (which is for dashboards and operations UIs). Import from \`@timbal-ai/timbal-react/site\` (or the package root).
|
|
317
|
+
|
|
318
|
+
These are **mechanics, not art direction**: they animate whatever you put inside them. Compose them under a chosen aesthetic; they do not impose colors, type, or layout.
|
|
319
|
+
|
|
320
|
+
### When to use \`/site\` (and when not to)
|
|
321
|
+
|
|
322
|
+
- **Do** use \`/site\` for landing pages, hero sections, feature walkthroughs, logo walls, pricing pages, and editorial/brand storytelling.
|
|
323
|
+
- **Do not** use \`/site\` inside dashboards, settings, tables, or in-thread chat artifacts \u2014 those stay on \`/app\` and \`/artifacts\`. Animated dashboard chrome reads as slop.
|
|
324
|
+
- Every primitive is **reduced-motion-aware** (collapses to static, no-transform output under \`prefers-reduced-motion\`) and **SSR-safe** (no layout shift \u2014 elements occupy their space from first paint). You never need to guard them yourself.
|
|
325
|
+
- Built on the \`motion\` engine the package already bundles \u2014 **no extra dependencies**.
|
|
326
|
+
|
|
327
|
+
### Dosing (anti-overuse \u2014 read this)
|
|
328
|
+
|
|
329
|
+
The failure mode is animating *everything*. Restraint is the brand signal.
|
|
330
|
+
|
|
331
|
+
- Pick **one** signature motion per section (e.g. a \`TextReveal\` headline **or** a \`Parallax\` hero image, not both stacked).
|
|
332
|
+
- Stagger entrances down the page; do not fire ten reveals at once on first paint.
|
|
333
|
+
- Reserve \`Magnetic\` for **primary** CTAs / nav, not every button.
|
|
334
|
+
- Keep \`Parallax\` \`speed\` subtle (\`0.15\`\u2013\`0.35\`); large values look gimmicky.
|
|
335
|
+
- Default durations are intentionally slow and weighted (\`DURATION.base\` = 0.7s) \u2014 that confident pacing is the point. Don't speed everything up to app-kit's 150ms.
|
|
336
|
+
|
|
337
|
+
### Component menu
|
|
338
|
+
|
|
339
|
+
| Component | Use for | Key props |
|
|
340
|
+
|-----------|---------|-----------|
|
|
341
|
+
| \`Reveal\` | Fade/slide a block in as it scrolls into view (headings, cards, images, list items). | \`variant\` (\`fade\` \\| \`fade-up\` \\| \`fade-down\` \\| \`fade-left\` \\| \`fade-right\` \\| \`blur\` \\| \`scale\` \\| \`mask-up\`, default \`fade-up\`), \`delay\`, \`duration\`, \`distance\` (px, default 28), \`amount\` (visibility fraction 0\u20131 / \`"some"\` / \`"all"\`, default 0.3), \`repeat\` (replay on re-enter), \`as\` (render element, e.g. \`"section"\`/\`"li"\`). |
|
|
342
|
+
| \`TextReveal\` | Signature editorial headline entrance \u2014 text rides up token-by-token from a clip on a stagger. | \`children\` (**plain string only**), \`splitBy\` (\`words\` default \\| \`lines\`), \`stagger\` (default 0.06), \`delay\`, \`duration\`, \`amount\` (default 0.4), \`repeat\`, \`as\` (\`span\` default \\| \`h1\`\u2013\`h4\` \\| \`p\`). |
|
|
343
|
+
| \`Parallax\` | Depth \u2014 translate a layer relative to scroll (hero images, background art). | \`speed\` (-0.6\u20260.6, positive = lags behind scroll, default 0.2), \`axis\` (\`y\` default \\| \`x\`), \`smooth\` (spring-damped, default true). |
|
|
344
|
+
| \`Marquee\` | Seamless infinite scrolling row (logo walls, testimonials, ticker). Duplicates children internally \u2014 no visible seam. | \`speed\` (px/s, default 60), \`direction\` (\`left\` default \\| \`right\`), \`pauseOnHover\` (default true), \`gap\` (CSS length, default \`"3rem"\`). |
|
|
345
|
+
| \`Magnetic\` | Pointer-following "magnetic" affordance for a **single** interactive child (primary CTA, nav link). | \`strength\` (fraction of cursor offset, default 0.35), \`max\` (px clamp, default 24), \`spring\` (\`"snappy"\` default \\| \`"smooth"\`). Wrap one button/link. |
|
|
346
|
+
|
|
347
|
+
### Motion tokens
|
|
348
|
+
|
|
349
|
+
\`EASE\` (cubic-bezier tuples: \`out\` / \`inOut\` / \`soft\`), \`DURATION\` (\`fast\` 0.4s / \`base\` 0.7s / \`slow\` 1.1s), and \`SPRING\` (\`snappy\` / \`smooth\`) are exported for custom \`motion\` work that should match the kit's feel. Prefer the component defaults; reach for tokens only when hand-rolling a bespoke animation.
|
|
350
|
+
|
|
351
|
+
### Example imports
|
|
352
|
+
|
|
353
|
+
\`\`\`tsx
|
|
354
|
+
import { Reveal, TextReveal, Parallax, Marquee, Magnetic } from "@timbal-ai/timbal-react/site";
|
|
355
|
+
\`\`\`
|
|
356
|
+
|
|
357
|
+
\`\`\`tsx
|
|
358
|
+
<Reveal variant="fade-up" delay={0.1}>
|
|
359
|
+
<TextReveal as="h1" className="text-6xl font-semibold">
|
|
360
|
+
Built for the long run
|
|
361
|
+
</TextReveal>
|
|
362
|
+
</Reveal>
|
|
363
|
+
|
|
364
|
+
<Parallax speed={0.3}>
|
|
365
|
+
<img src={hero} alt="" className="h-full w-full object-cover" />
|
|
366
|
+
</Parallax>
|
|
367
|
+
|
|
368
|
+
<Magnetic strength={0.4}>
|
|
369
|
+
<Button>Get started</Button>
|
|
370
|
+
</Magnetic>
|
|
371
|
+
\`\`\`
|
|
372
|
+
|
|
373
|
+
### Rules
|
|
374
|
+
|
|
375
|
+
- \`/site\` is for the **marketing/brand surface**, not the product app shell (\`/app\`) or in-chat widgets (\`/artifacts\`).
|
|
376
|
+
- \`TextReveal\` takes a **string** child only \u2014 it splits internally; do not pass JSX.
|
|
377
|
+
- \`Magnetic\` wraps a **single** interactive child; don't wrap whole layouts.
|
|
378
|
+
- Trust the reduced-motion / SSR handling \u2014 never add your own \`prefers-reduced-motion\` guards around these.
|
|
379
|
+
`.trim();
|
|
380
|
+
|
|
381
|
+
export {
|
|
382
|
+
EASE,
|
|
383
|
+
DURATION,
|
|
384
|
+
SPRING,
|
|
385
|
+
Reveal,
|
|
386
|
+
TextReveal,
|
|
387
|
+
Parallax,
|
|
388
|
+
Marquee,
|
|
389
|
+
Magnetic,
|
|
390
|
+
SITE_AGENT_INSTRUCTIONS
|
|
391
|
+
};
|
|
@@ -88,16 +88,16 @@ var buttonVariants = cva(
|
|
|
88
88
|
)
|
|
89
89
|
},
|
|
90
90
|
size: {
|
|
91
|
-
xs: "h-
|
|
92
|
-
sm: "h-
|
|
93
|
-
md: "h-
|
|
94
|
-
lg: "h-
|
|
95
|
-
xl: "h-
|
|
96
|
-
default: "h-
|
|
97
|
-
icon: "h-
|
|
98
|
-
"icon-xs": "h-
|
|
99
|
-
"icon-sm": "h-
|
|
100
|
-
"icon-lg": "h-
|
|
91
|
+
xs: "h-7 gap-1 rounded-md px-2 text-xs",
|
|
92
|
+
sm: "h-8 gap-1 rounded-md px-2.5 text-xs",
|
|
93
|
+
md: "h-9 gap-1.5 rounded-lg px-3 text-sm",
|
|
94
|
+
lg: "h-10 gap-1.5 rounded-lg px-3.5 text-sm",
|
|
95
|
+
xl: "h-11 gap-2 rounded-lg px-4 text-base",
|
|
96
|
+
default: "h-9 gap-1.5 rounded-lg px-3 text-sm",
|
|
97
|
+
icon: "h-9 w-9 rounded-lg",
|
|
98
|
+
"icon-xs": "h-7 w-7 rounded-md",
|
|
99
|
+
"icon-sm": "h-8 w-8 rounded-md",
|
|
100
|
+
"icon-lg": "h-10 w-10 rounded-lg"
|
|
101
101
|
},
|
|
102
102
|
shape: {
|
|
103
103
|
pill: "rounded-full!",
|
|
@@ -191,22 +191,22 @@ var TIMBAL_V2_MODAL_SURFACE = cn(
|
|
|
191
191
|
);
|
|
192
192
|
var TIMBAL_V2_PRIMARY_GRADIENT = "bg-gradient-to-b from-primary-fill-from to-primary-fill-to";
|
|
193
193
|
var TIMBAL_V2_SIZE_HEIGHT = {
|
|
194
|
-
xs: "min-h-
|
|
195
|
-
sm: "min-h-
|
|
196
|
-
md: "min-h-
|
|
197
|
-
lg: "min-h-
|
|
194
|
+
xs: "min-h-7 h-7",
|
|
195
|
+
sm: "min-h-8 h-8",
|
|
196
|
+
md: "min-h-9 h-9",
|
|
197
|
+
lg: "min-h-10 h-10"
|
|
198
198
|
};
|
|
199
199
|
var TIMBAL_V2_SIZE_ICON = {
|
|
200
|
-
xs: "min-h-
|
|
200
|
+
xs: "min-h-7 min-w-7 size-7",
|
|
201
201
|
sm: "min-h-8 min-w-8 size-8",
|
|
202
|
-
md: "min-h-
|
|
203
|
-
lg: "min-h-
|
|
202
|
+
md: "min-h-9 min-w-9 size-9",
|
|
203
|
+
lg: "min-h-10 min-w-10 size-10"
|
|
204
204
|
};
|
|
205
205
|
var TIMBAL_V2_SIZE_LABEL_PX = {
|
|
206
|
-
xs: "px-
|
|
207
|
-
sm: "px-
|
|
208
|
-
md: "px-5",
|
|
209
|
-
lg: "px-
|
|
206
|
+
xs: "px-2.5",
|
|
207
|
+
sm: "px-3",
|
|
208
|
+
md: "px-3.5",
|
|
209
|
+
lg: "px-4.5"
|
|
210
210
|
};
|
|
211
211
|
var TIMBAL_V2_FILL = {
|
|
212
212
|
primary: [
|
|
@@ -323,8 +323,8 @@ var TIMBAL_V2_LOGO_TILE = cn(
|
|
|
323
323
|
|
|
324
324
|
// src/design/control-surface.ts
|
|
325
325
|
var CONTROL_SIZE = {
|
|
326
|
-
sm: "h-
|
|
327
|
-
default: "h-
|
|
326
|
+
sm: "h-8 px-2.5",
|
|
327
|
+
default: "h-9 px-3"
|
|
328
328
|
};
|
|
329
329
|
var CONTROL_SHAPE = {
|
|
330
330
|
field: "rounded-lg",
|
|
@@ -352,7 +352,7 @@ var overlayListPanelClass = cn(
|
|
|
352
352
|
overlaySurfaceClass,
|
|
353
353
|
"overflow-hidden rounded-lg p-0 outline-hidden"
|
|
354
354
|
);
|
|
355
|
-
var overlayItemClass = "relative flex cursor-default items-center gap-2 rounded-md px-2 py-1
|
|
355
|
+
var overlayItemClass = "relative flex cursor-default items-center gap-2 rounded-md px-2 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground";
|
|
356
356
|
|
|
357
357
|
// src/ui/timbal-v2-button.tsx
|
|
358
358
|
import * as React from "react";
|
|
@@ -587,7 +587,7 @@ function DialogContent({
|
|
|
587
587
|
"data-slot": "dialog-content",
|
|
588
588
|
className: cn(
|
|
589
589
|
TIMBAL_V2_MODAL_SURFACE,
|
|
590
|
-
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-[70] grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-xl p-
|
|
590
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-[70] grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-xl p-5 duration-200 outline-none sm:max-w-lg",
|
|
591
591
|
className
|
|
592
592
|
),
|
|
593
593
|
...props,
|
|
@@ -684,9 +684,9 @@ function avatarChartVariantClass(_seed) {
|
|
|
684
684
|
return AVATAR_PRIMARY_FALLBACK_CLASS;
|
|
685
685
|
}
|
|
686
686
|
var AVATAR_SIZE_CLASS = {
|
|
687
|
-
default: "size-
|
|
688
|
-
sm: "size-
|
|
689
|
-
lg: "size-
|
|
687
|
+
default: "size-7",
|
|
688
|
+
sm: "size-5",
|
|
689
|
+
lg: "size-9"
|
|
690
690
|
};
|
|
691
691
|
function Avatar({
|
|
692
692
|
className,
|