@remotion/design 4.0.371

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/README.md ADDED
@@ -0,0 +1,18 @@
1
+ # @remotion/design
2
+
3
+ Design system
4
+
5
+ [![NPM Downloads](https://img.shields.io/npm/dm/@remotion/design.svg?style=flat&color=black&label=Downloads)](https://npmcharts.com/compare/@remotion/design?minimal=true)
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @remotion/design --save-exact
11
+ ```
12
+
13
+ When installing a Remotion package, make sure to align the version of all `remotion` and `@remotion/*` packages to the same version.
14
+ Remove the `^` character from the version number to use the exact version.
15
+
16
+ ## Usage
17
+
18
+ See the [documentation](https://www.remotion.dev/design) for more information.
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export declare const Button: React.FC<React.ButtonHTMLAttributes<HTMLButtonElement> & {
3
+ readonly depth?: number;
4
+ }>;
package/dist/Button.js ADDED
@@ -0,0 +1,48 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useCallback, useRef, useState } from 'react';
3
+ import { cn } from './helpers/cn';
4
+ import { useHoverTransforms } from './helpers/hover-transforms';
5
+ import { Outer } from './helpers/Outer';
6
+ export const Button = ({ children, className, disabled, depth, ...buttonProps }) => {
7
+ const [dimensions, setDimensions] = useState(null);
8
+ const ref = useRef(null);
9
+ const { isActive, progress } = useHoverTransforms(ref, Boolean(disabled));
10
+ const onPointerEnter = useCallback((e) => {
11
+ if (e.pointerType !== 'mouse') {
12
+ return;
13
+ }
14
+ setDimensions((prevDim) => {
15
+ if (!ref.current) {
16
+ throw new Error('Ref is not set');
17
+ }
18
+ const { childNodes } = ref.current;
19
+ if (childNodes.length === 0) {
20
+ throw new Error('No child nodes');
21
+ }
22
+ const childNode = childNodes[0];
23
+ if (!childNode) {
24
+ throw new Error('No child node');
25
+ }
26
+ const rect = childNode.getBoundingClientRect();
27
+ const { borderRadius } = getComputedStyle(childNode);
28
+ const cornerRadius = borderRadius.includes('e+0')
29
+ ? Infinity
30
+ : parseInt(borderRadius ?? '0', 10);
31
+ const newCornerRadius = Math.min(cornerRadius, rect.width / 2, rect.height / 2);
32
+ if (prevDim) {
33
+ return {
34
+ width: rect.width,
35
+ height: rect.height,
36
+ borderRadius: prevDim.borderRadius,
37
+ };
38
+ }
39
+ return {
40
+ width: rect.width,
41
+ height: rect.height,
42
+ borderRadius: newCornerRadius,
43
+ };
44
+ });
45
+ }, []);
46
+ const content = (_jsx("button", { type: "button", disabled: disabled, className: cn('text-text', 'flex', 'justify-center', 'bg-button-bg', 'items-center', 'font-brand', 'border-solid', 'text-[1em]', 'rounded-lg', 'border-black', 'border-2', 'border-b-4', 'cursor-pointer', 'px-4', 'h-12', 'flex', 'flex-row', 'items-center', 'disabled:cursor-default', 'disabled:border-gray-500', 'disabled:text-gray-500', className), ...buttonProps, children: children }));
47
+ return (_jsx("div", { ref: ref, className: "contents", onPointerEnter: onPointerEnter, children: dimensions && (isActive || progress > 0) ? (_jsx(Outer, { parentRef: ref, width: dimensions.width, height: dimensions.height, cornerRadius: dimensions.borderRadius, hoverTransform: progress, depthFactor: depth ?? 1, children: content })) : (content) }));
48
+ };
package/dist/Card.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const Card: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
package/dist/Card.js ADDED
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ import { cn } from './helpers/cn';
4
+ export const Card = React.forwardRef(({ children, className, ...rest }, ref) => {
5
+ return (_jsx("div", { ref: ref, className: cn('rounded-lg border-2 border-black bg-card-bg text-text border-b-4', className), ...rest, children: children }));
6
+ });
7
+ Card.displayName = 'Card';
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const CheckIcon: React.FC<React.SVGProps<SVGSVGElement>>;
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ const d = 'M143.056 81.4934C147.25 77.2994 147.25 70.4506 143.056 66.2566C138.862 62.0627 132.013 62.0627 127.819 66.2566L86.1875 107.888L69.1809 90.8816C64.9869 86.6877 58.1381 86.6877 53.9441 90.8816C49.7502 95.0756 49.7502 101.924 53.9441 106.118L78.5691 130.743C82.7631 134.937 89.6119 134.937 93.8059 130.743L143.056 81.4934Z';
3
+ export const CheckIcon = (props) => {
4
+ return (_jsx("svg", { ...props, viewBox: '50.79867500000001 63.11117499999997 95.40282500000015 70.77732499999999', fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: d, fill: "currentcolor" }) }));
5
+ };
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ interface CounterProps {
3
+ readonly count: number;
4
+ readonly setCount: (count: number) => void;
5
+ readonly minCount?: number;
6
+ readonly step?: number;
7
+ }
8
+ export declare const Counter: React.FC<CounterProps>;
9
+ export {};
@@ -0,0 +1,52 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Card } from './Card';
3
+ import { cn } from './helpers/cn';
4
+ const Triangle = ({ rotated }) => (_jsx("svg", { width: "12px", height: "7px", viewBox: "0 0 12 7", fill: "none", style: {
5
+ transform: rotated ? 'rotate(180deg)' : 'rotate(0deg)',
6
+ }, children: _jsx("path", { className: "fill-text", d: "M7.17096 0.475588C6.73198 0.0764969 6.01906 0.0764969 5.58007 0.475588L1.08483 4.56228C0.761737 4.85601 0.666915 5.29341 0.84251 5.67654C1.01811 6.05966 1.42549 6.3087 1.88203 6.3087H10.8725C11.3255 6.3087 11.7364 6.05966 11.912 5.67654C12.0876 5.29341 11.9893 4.85601 11.6697 4.56228L7.17448 0.475588H7.17096Z" }) }));
7
+ const container = {
8
+ display: 'flex',
9
+ flexDirection: 'row',
10
+ justifyContent: 'flex-end',
11
+ alignItems: 'center',
12
+ height: 42,
13
+ flexShrink: 0,
14
+ };
15
+ const buttonContainer = {
16
+ display: 'flex',
17
+ width: 30,
18
+ height: 20,
19
+ justifyContent: 'center',
20
+ alignItems: 'center',
21
+ cursor: 'pointer',
22
+ };
23
+ export const Counter = ({ count, setCount, minCount = 0, step = 1, }) => {
24
+ const decrement = () => {
25
+ if (count > minCount) {
26
+ setCount(Math.max(minCount, count - step));
27
+ }
28
+ };
29
+ const increment = () => {
30
+ setCount(count + step);
31
+ };
32
+ return (_jsxs(Card, { style: container, className: cn('w-[140px] flex flex-row overflow-hidden'), children: [_jsx("input", { className: 'fontbrand text-2xl font-medium min-w-[80px] border-0 text-end outline-0 text-text overflow-hidden flex-1 px-0 py-0 pr-2 w-full h-full tabular-nums', type: "number", onClick: (e) => e.currentTarget.select(), value: count, onChange: (e) => {
33
+ if (e.target.value.trim() === '') {
34
+ setCount(step === 1 ? 1 : minCount);
35
+ return;
36
+ }
37
+ const inputValue = parseInt(e.target.value, 10);
38
+ const validValue = Math.max(inputValue, minCount);
39
+ // For steps > 1, round to the nearest valid step
40
+ if (step > 1) {
41
+ const roundedValue = Math.round(validValue / step) * step;
42
+ setCount(Math.max(roundedValue, minCount));
43
+ }
44
+ else {
45
+ setCount(validValue);
46
+ }
47
+ } }), _jsxs("div", { className: "flex flex-col h-full", children: [_jsx("button", { type: "button", className: "border-0 flex-1 p-0 pt-[5px] bg-transparent", style: {
48
+ ...buttonContainer,
49
+ }, onClick: increment, children: _jsx(Triangle, { rotated: false }) }), _jsx("button", { type: "button", className: "border-0 flex-1 p-0 bg-transparent pb-[5px] pl-[1px]", style: {
50
+ ...buttonContainer,
51
+ }, onClick: decrement, children: _jsx(Triangle, { rotated: true }) })] })] }));
52
+ };
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const PlanePaperIcon: React.FC<React.SVGProps<SVGSVGElement>>;
@@ -0,0 +1,4 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ export const PlanePaperIcon = (props) => {
3
+ return (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", ...props, viewBox: "0 0 576 512", children: _jsx("path", { fill: "currentcolor", d: "M169.9 280L94.9 448.6 461.2 280 169.9 280zm291.3-48L94.9 63.4 169.9 232 461.2 232zM34.8 465.6L128 256 34.8 46.4C33 42.2 32 37.6 32 33 32 14.8 46.7 0 64.8 0 69.5 0 74.2 1 78.5 3L554.2 222c13.3 6.1 21.8 19.4 21.8 34s-8.5 27.9-21.8 34L78.5 509c-4.3 2-9 3-13.7 3-18.1 0-32.8-14.8-32.8-33 0-4.6 1-9.2 2.8-13.4z" }) }));
4
+ };
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ export declare const Switch: React.FC<{
3
+ readonly active: boolean;
4
+ readonly onToggle: () => void;
5
+ }>;
package/dist/Switch.js ADDED
@@ -0,0 +1,4 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ export const Switch = ({ active, onToggle }) => {
3
+ return (_jsx("div", { "data-active": active, className: "h-8 transition-all rounded-full w-14 border-2 border-b-4 bg-gray-200 p-[2px] cursor-pointer data-[active=true]:bg-brand border-black relative", onClick: onToggle, children: _jsx("div", { "data-active": active, className: "h-4 w-4 box-content left-[4px] top-[3px] transition-all rounded-full bg-white border-2 border-black absolute data-[active=true]:left-[calc(100%-24px)]" }) }));
4
+ };
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const Triangle: React.FC<React.SVGProps<SVGSVGElement>>;
@@ -0,0 +1,4 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ export const Triangle = (props) => {
3
+ return (_jsx("svg", { viewBox: "0 0 127 131", fill: "none", ...props, children: _jsx("path", { d: "M28.5644 0.011261C25.8196 0.159241 23.6077 0.591782 21.3786 1.43413C20.2669 1.84959 18.4446 2.75455 17.4418 3.38062C13.2472 5.993 10.0496 9.9201 8.38209 14.4903C8.04973 15.3953 7.15007 18.2809 6.5713 20.2672C2.71476 33.5453 0.525761 48.0643 0.0558711 63.4312C-0.0186237 65.8785 -0.0186237 71.7066 0.0558711 74.1141C0.371041 84.3018 1.35093 93.4992 3.12735 102.879C3.84937 106.675 5.00691 111.774 5.67736 114.091C7.04692 118.798 9.84334 122.805 13.8202 125.741C16.4848 127.711 19.5105 129.031 22.8627 129.68C24.4787 129.993 26.6104 130.135 28.1805 130.033C30.3523 129.89 34.6616 129.316 38.1628 128.695C53.9442 125.901 68.5223 120.898 81.7422 113.738C90.1143 109.202 97.2715 104.29 104.177 98.3312C111.059 92.4007 116.927 86.0206 122.09 78.8608C123.287 77.2045 123.889 76.237 124.491 75.019C126.038 71.8773 126.766 68.7527 126.76 65.2582C126.76 62.0027 126.141 59.1114 124.806 56.1518C124.164 54.7233 123.551 53.6988 122.176 51.7523C117.11 44.5868 111.489 38.3433 104.635 32.2762C94.011 22.8739 81.3927 15.1619 67.3017 9.45339C64.2474 8.21835 61.239 7.13128 57.6174 5.95315C49.9502 3.46598 40.4607 1.30891 32.4324 0.233231C31.1718 0.0624847 29.4584 -0.0342712 28.5644 0.011261Z", fill: "currentcolor" }) }));
4
+ };
@@ -0,0 +1,537 @@
1
+ // src/Button.tsx
2
+ import { useCallback, useRef, useState as useState2 } from "react";
3
+
4
+ // src/helpers/cn.ts
5
+ import { clsx } from "clsx";
6
+ import { twMerge } from "tailwind-merge";
7
+ function cn(...inputs) {
8
+ return twMerge(clsx(inputs));
9
+ }
10
+
11
+ // src/helpers/hover-transforms.ts
12
+ import React, { useEffect, useMemo, useState } from "react";
13
+
14
+ // src/helpers/get-child-node-from.ts
15
+ var getChildNodeFrom = (htmlElement) => {
16
+ if (!htmlElement) {
17
+ return null;
18
+ }
19
+ const { childNodes } = htmlElement;
20
+ if (childNodes.length === 0) {
21
+ return null;
22
+ }
23
+ const childNode = childNodes[0];
24
+ if (!childNode) {
25
+ return null;
26
+ }
27
+ return childNode;
28
+ };
29
+
30
+ // src/helpers/hover-transforms.ts
31
+ var useHoverTransforms = (ref, disabled) => {
32
+ const [state, setState] = React.useState({
33
+ progress: 0,
34
+ isActive: false
35
+ });
36
+ const eventTarget = useMemo(() => new EventTarget, []);
37
+ useEffect(() => {
38
+ if (disabled) {
39
+ eventTarget.dispatchEvent(new Event("disabled"));
40
+ } else {
41
+ eventTarget.dispatchEvent(new Event("enabled"));
42
+ }
43
+ }, [disabled, eventTarget]);
44
+ React.useEffect(() => {
45
+ const element = ref.current;
46
+ if (!element)
47
+ return;
48
+ let animationFrame;
49
+ let start = null;
50
+ let isHovered = false;
51
+ let internalDisabled = disabled;
52
+ const getIsActive = () => {
53
+ return isHovered && !internalDisabled;
54
+ };
55
+ const animate = (timestamp) => {
56
+ if (start === null)
57
+ start = timestamp;
58
+ const progress = Math.min((timestamp - start) / 150, 1);
59
+ setState(() => ({
60
+ isActive: getIsActive(),
61
+ progress: getIsActive() ? progress : 1 - progress
62
+ }));
63
+ if (progress < 1) {
64
+ animationFrame = requestAnimationFrame(animate);
65
+ }
66
+ };
67
+ const animateIn = () => {
68
+ start = null;
69
+ cancelAnimationFrame(animationFrame);
70
+ animationFrame = requestAnimationFrame(animate);
71
+ };
72
+ const handleMouseEnter = () => {
73
+ const prevIsActive = getIsActive();
74
+ isHovered = true;
75
+ if (prevIsActive === getIsActive()) {
76
+ return;
77
+ }
78
+ animateIn();
79
+ };
80
+ const handleMouseLeave = () => {
81
+ const prevIsActive = getIsActive();
82
+ isHovered = false;
83
+ if (prevIsActive === getIsActive()) {
84
+ return;
85
+ }
86
+ animateIn();
87
+ };
88
+ const handleDisabled = () => {
89
+ const prevIsActive = getIsActive();
90
+ internalDisabled = true;
91
+ if (prevIsActive === getIsActive()) {
92
+ return;
93
+ }
94
+ animateIn();
95
+ };
96
+ const handleEnabled = () => {
97
+ const prevIsActive = getIsActive();
98
+ internalDisabled = false;
99
+ if (prevIsActive === getIsActive()) {
100
+ return;
101
+ }
102
+ animateIn();
103
+ };
104
+ element.addEventListener("mouseenter", handleMouseEnter);
105
+ element.addEventListener("mouseleave", handleMouseLeave);
106
+ eventTarget.addEventListener("disabled", handleDisabled);
107
+ eventTarget.addEventListener("enabled", handleEnabled);
108
+ return () => {
109
+ element.removeEventListener("mouseenter", handleMouseEnter);
110
+ element.removeEventListener("mouseleave", handleMouseLeave);
111
+ eventTarget.removeEventListener("disabled", handleDisabled);
112
+ eventTarget.removeEventListener("enabled", handleEnabled);
113
+ cancelAnimationFrame(animationFrame);
114
+ };
115
+ }, [ref, eventTarget]);
116
+ return state;
117
+ };
118
+ var useClickTransforms = (ref) => {
119
+ const [hoverProgress, setHoverProgress] = React.useState(0);
120
+ React.useEffect(() => {
121
+ const element = getChildNodeFrom(ref.current);
122
+ if (!element) {
123
+ return;
124
+ }
125
+ let animationFrame;
126
+ let start = null;
127
+ let isHovered = false;
128
+ const animate = (timestamp) => {
129
+ if (start === null)
130
+ start = timestamp;
131
+ const progress = Math.min((timestamp - start) / 150, 1);
132
+ setHoverProgress(isHovered ? progress : 1 - progress);
133
+ if (progress < 1) {
134
+ animationFrame = requestAnimationFrame(animate);
135
+ }
136
+ };
137
+ const handleMouseEnter = () => {
138
+ isHovered = true;
139
+ start = null;
140
+ cancelAnimationFrame(animationFrame);
141
+ animationFrame = requestAnimationFrame(animate);
142
+ };
143
+ const handleMouseLeave = () => {
144
+ isHovered = false;
145
+ start = null;
146
+ cancelAnimationFrame(animationFrame);
147
+ animationFrame = requestAnimationFrame(animate);
148
+ };
149
+ element.addEventListener("pointerdown", handleMouseEnter);
150
+ element.addEventListener("pointerup", handleMouseLeave);
151
+ return () => {
152
+ element.removeEventListener("pointerdown", handleMouseEnter);
153
+ element.removeEventListener("pointerup", handleMouseLeave);
154
+ cancelAnimationFrame(animationFrame);
155
+ };
156
+ }, [ref]);
157
+ return hoverProgress;
158
+ };
159
+ var getAngle = (ref, coordinates) => {
160
+ const element = getChildNodeFrom(ref);
161
+ if (!element) {
162
+ return 0;
163
+ }
164
+ if (coordinates === null) {
165
+ return 0;
166
+ }
167
+ const clientRect = element.getClientRects();
168
+ if (!clientRect) {
169
+ return 0;
170
+ }
171
+ if (clientRect.length === 0) {
172
+ return 0;
173
+ }
174
+ const center = {
175
+ x: clientRect[0].x + clientRect[0].width / 2,
176
+ y: clientRect[0].y + clientRect[0].height / 2
177
+ };
178
+ const angle = Math.atan2(coordinates.y - center.y, coordinates.x - center.x);
179
+ return angle;
180
+ };
181
+ var lastCoordinates = null;
182
+ var useMousePosition = (ref) => {
183
+ const [angle, setAngle] = useState(getAngle(ref.current, lastCoordinates));
184
+ useEffect(() => {
185
+ const element = ref.current;
186
+ if (!element) {
187
+ return;
188
+ }
189
+ const onMouseMove = (e) => {
190
+ const clientRect = element.getClientRects();
191
+ if (!clientRect) {
192
+ return;
193
+ }
194
+ lastCoordinates = { y: e.clientY, x: e.clientX };
195
+ setAngle(getAngle(element, { y: e.clientY, x: e.clientX }));
196
+ };
197
+ window.addEventListener("mousemove", onMouseMove);
198
+ return () => {
199
+ window.removeEventListener("mousemove", onMouseMove);
200
+ };
201
+ }, [ref]);
202
+ return angle;
203
+ };
204
+
205
+ // src/helpers/Outer.tsx
206
+ import { parsePath, PathInternals, reduceInstructions } from "@remotion/paths";
207
+ import { makeRect } from "@remotion/shapes";
208
+ import {
209
+ extrudeAndTransformElement,
210
+ interpolateMatrix4d,
211
+ makeMatrix3dTransform,
212
+ reduceMatrices,
213
+ rotateX,
214
+ rotateY,
215
+ scaled,
216
+ translateX,
217
+ translateY,
218
+ translateZ
219
+ } from "@remotion/svg-3d-engine";
220
+ import { interpolate } from "remotion";
221
+
222
+ // src/helpers/Faces.tsx
223
+ import { threeDIntoSvgPath } from "@remotion/svg-3d-engine";
224
+ import { jsx, Fragment } from "react/jsx-runtime";
225
+ var Faces = ({ elements, ...svgProps }) => {
226
+ return /* @__PURE__ */ jsx(Fragment, {
227
+ children: elements.map(({ points, color, crispEdges }, idx) => {
228
+ return /* @__PURE__ */ jsx("path", {
229
+ d: threeDIntoSvgPath(points),
230
+ fill: color,
231
+ shapeRendering: crispEdges ? "crispEdges" : undefined,
232
+ ...svgProps
233
+ }, idx);
234
+ })
235
+ });
236
+ };
237
+
238
+ // src/helpers/Outer.tsx
239
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
240
+ var Outer = ({
241
+ children,
242
+ width,
243
+ height,
244
+ cornerRadius,
245
+ hoverTransform,
246
+ parentRef,
247
+ depthFactor
248
+ }) => {
249
+ const clickTransform = useClickTransforms(parentRef);
250
+ const angle = useMousePosition(parentRef);
251
+ const appropriateScale = Math.min(1 + 0.1 * depthFactor, (20 + width) / width);
252
+ const transformationUnhovered = reduceMatrices([
253
+ rotateX(-Math.PI / 20)
254
+ ]);
255
+ const transformationHovered = reduceMatrices([
256
+ scaled(appropriateScale),
257
+ rotateX(-Math.PI / 16),
258
+ rotateX(Math.sin(angle) / 4),
259
+ rotateY(-Math.cos(angle) / 4)
260
+ ]);
261
+ const transformation = interpolateMatrix4d(hoverTransform, transformationUnhovered, transformationHovered);
262
+ const depthFromClick = clickTransform * 15 * depthFactor;
263
+ const depthFromHover = interpolate(hoverTransform, [0, 1], [10, 20]) * depthFactor;
264
+ const depth = depthFromHover;
265
+ const frontFace = reduceMatrices([
266
+ translateZ(-depth / 2 + depthFromClick),
267
+ transformation
268
+ ]);
269
+ const centerOriented = reduceMatrices([
270
+ translateX(-width / 2),
271
+ translateY(-height / 2),
272
+ transformation,
273
+ translateX(width / 2),
274
+ translateY(height / 2)
275
+ ]);
276
+ const { path, instructions } = makeRect({ height, width, cornerRadius });
277
+ const { viewBox } = PathInternals.getBoundingBoxFromInstructions(reduceInstructions(instructions));
278
+ const inbetween = extrudeAndTransformElement({
279
+ sideColor: "black",
280
+ crispEdges: false,
281
+ depth,
282
+ pressInDepth: depthFromClick,
283
+ points: parsePath(path),
284
+ description: "rect",
285
+ transformations: centerOriented
286
+ });
287
+ return /* @__PURE__ */ jsxs("div", {
288
+ className: "relative",
289
+ style: { width, height },
290
+ children: [
291
+ /* @__PURE__ */ jsx2("svg", {
292
+ viewBox,
293
+ style: {
294
+ overflow: "visible",
295
+ height,
296
+ width,
297
+ position: "absolute",
298
+ top: 0,
299
+ left: 0
300
+ },
301
+ pointerEvents: "none",
302
+ children: /* @__PURE__ */ jsx2(Faces, {
303
+ elements: inbetween
304
+ })
305
+ }),
306
+ /* @__PURE__ */ jsx2("div", {
307
+ style: {
308
+ transform: makeMatrix3dTransform(frontFace)
309
+ },
310
+ children
311
+ })
312
+ ]
313
+ });
314
+ };
315
+
316
+ // src/Button.tsx
317
+ import { jsx as jsx3 } from "react/jsx-runtime";
318
+ var Button = ({ children, className, disabled, depth, ...buttonProps }) => {
319
+ const [dimensions, setDimensions] = useState2(null);
320
+ const ref = useRef(null);
321
+ const { isActive, progress } = useHoverTransforms(ref, Boolean(disabled));
322
+ const onPointerEnter = useCallback((e) => {
323
+ if (e.pointerType !== "mouse") {
324
+ return;
325
+ }
326
+ setDimensions((prevDim) => {
327
+ if (!ref.current) {
328
+ throw new Error("Ref is not set");
329
+ }
330
+ const { childNodes } = ref.current;
331
+ if (childNodes.length === 0) {
332
+ throw new Error("No child nodes");
333
+ }
334
+ const childNode = childNodes[0];
335
+ if (!childNode) {
336
+ throw new Error("No child node");
337
+ }
338
+ const rect = childNode.getBoundingClientRect();
339
+ const { borderRadius } = getComputedStyle(childNode);
340
+ const cornerRadius = borderRadius.includes("e+0") ? Infinity : parseInt(borderRadius ?? "0", 10);
341
+ const newCornerRadius = Math.min(cornerRadius, rect.width / 2, rect.height / 2);
342
+ if (prevDim) {
343
+ return {
344
+ width: rect.width,
345
+ height: rect.height,
346
+ borderRadius: prevDim.borderRadius
347
+ };
348
+ }
349
+ return {
350
+ width: rect.width,
351
+ height: rect.height,
352
+ borderRadius: newCornerRadius
353
+ };
354
+ });
355
+ }, []);
356
+ const content = /* @__PURE__ */ jsx3("button", {
357
+ type: "button",
358
+ disabled,
359
+ className: cn("text-text", "flex", "justify-center", "bg-button-bg", "items-center", "font-brand", "border-solid", "text-[1em]", "rounded-lg", "border-black", "border-2", "border-b-4", "cursor-pointer", "px-4", "h-12", "flex", "flex-row", "items-center", "disabled:cursor-default", "disabled:border-gray-500", "disabled:text-gray-500", className),
360
+ ...buttonProps,
361
+ children
362
+ });
363
+ return /* @__PURE__ */ jsx3("div", {
364
+ ref,
365
+ className: "contents",
366
+ onPointerEnter,
367
+ children: dimensions && (isActive || progress > 0) ? /* @__PURE__ */ jsx3(Outer, {
368
+ parentRef: ref,
369
+ width: dimensions.width,
370
+ height: dimensions.height,
371
+ cornerRadius: dimensions.borderRadius,
372
+ hoverTransform: progress,
373
+ depthFactor: depth ?? 1,
374
+ children: content
375
+ }) : content
376
+ });
377
+ };
378
+ // src/Card.tsx
379
+ import React3 from "react";
380
+ import { jsx as jsx4 } from "react/jsx-runtime";
381
+ var Card = React3.forwardRef(({ children, className, ...rest }, ref) => {
382
+ return /* @__PURE__ */ jsx4("div", {
383
+ ref,
384
+ className: cn("rounded-lg border-2 border-black bg-card-bg text-text border-b-4", className),
385
+ ...rest,
386
+ children
387
+ });
388
+ });
389
+ Card.displayName = "Card";
390
+ // src/CheckIcon.tsx
391
+ import { jsx as jsx5 } from "react/jsx-runtime";
392
+ var d = "M143.056 81.4934C147.25 77.2994 147.25 70.4506 143.056 66.2566C138.862 62.0627 132.013 62.0627 127.819 66.2566L86.1875 107.888L69.1809 90.8816C64.9869 86.6877 58.1381 86.6877 53.9441 90.8816C49.7502 95.0756 49.7502 101.924 53.9441 106.118L78.5691 130.743C82.7631 134.937 89.6119 134.937 93.8059 130.743L143.056 81.4934Z";
393
+ var CheckIcon = (props) => {
394
+ return /* @__PURE__ */ jsx5("svg", {
395
+ ...props,
396
+ viewBox: "50.79867500000001 63.11117499999997 95.40282500000015 70.77732499999999",
397
+ fill: "none",
398
+ xmlns: "http://www.w3.org/2000/svg",
399
+ children: /* @__PURE__ */ jsx5("path", {
400
+ d,
401
+ fill: "currentcolor"
402
+ })
403
+ });
404
+ };
405
+ // src/Counter.tsx
406
+ import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
407
+ var Triangle = ({ rotated }) => /* @__PURE__ */ jsx6("svg", {
408
+ width: "12px",
409
+ height: "7px",
410
+ viewBox: "0 0 12 7",
411
+ fill: "none",
412
+ style: {
413
+ transform: rotated ? "rotate(180deg)" : "rotate(0deg)"
414
+ },
415
+ children: /* @__PURE__ */ jsx6("path", {
416
+ className: "fill-text",
417
+ d: "M7.17096 0.475588C6.73198 0.0764969 6.01906 0.0764969 5.58007 0.475588L1.08483 4.56228C0.761737 4.85601 0.666915 5.29341 0.84251 5.67654C1.01811 6.05966 1.42549 6.3087 1.88203 6.3087H10.8725C11.3255 6.3087 11.7364 6.05966 11.912 5.67654C12.0876 5.29341 11.9893 4.85601 11.6697 4.56228L7.17448 0.475588H7.17096Z"
418
+ })
419
+ });
420
+ var container = {
421
+ display: "flex",
422
+ flexDirection: "row",
423
+ justifyContent: "flex-end",
424
+ alignItems: "center",
425
+ height: 42,
426
+ flexShrink: 0
427
+ };
428
+ var buttonContainer = {
429
+ display: "flex",
430
+ width: 30,
431
+ height: 20,
432
+ justifyContent: "center",
433
+ alignItems: "center",
434
+ cursor: "pointer"
435
+ };
436
+ var Counter = ({
437
+ count,
438
+ setCount,
439
+ minCount = 0,
440
+ step = 1
441
+ }) => {
442
+ const decrement = () => {
443
+ if (count > minCount) {
444
+ setCount(Math.max(minCount, count - step));
445
+ }
446
+ };
447
+ const increment = () => {
448
+ setCount(count + step);
449
+ };
450
+ return /* @__PURE__ */ jsxs2(Card, {
451
+ style: container,
452
+ className: cn("w-[140px] flex flex-row overflow-hidden"),
453
+ children: [
454
+ /* @__PURE__ */ jsx6("input", {
455
+ className: "fontbrand text-2xl font-medium min-w-[80px] border-0 text-end outline-0 text-text overflow-hidden flex-1 px-0 py-0 pr-2 w-full h-full tabular-nums",
456
+ type: "number",
457
+ onClick: (e) => e.currentTarget.select(),
458
+ value: count,
459
+ onChange: (e) => {
460
+ if (e.target.value.trim() === "") {
461
+ setCount(step === 1 ? 1 : minCount);
462
+ return;
463
+ }
464
+ const inputValue = parseInt(e.target.value, 10);
465
+ const validValue = Math.max(inputValue, minCount);
466
+ if (step > 1) {
467
+ const roundedValue = Math.round(validValue / step) * step;
468
+ setCount(Math.max(roundedValue, minCount));
469
+ } else {
470
+ setCount(validValue);
471
+ }
472
+ }
473
+ }),
474
+ /* @__PURE__ */ jsxs2("div", {
475
+ className: "flex flex-col h-full",
476
+ children: [
477
+ /* @__PURE__ */ jsx6("button", {
478
+ type: "button",
479
+ className: "border-0 flex-1 p-0 pt-[5px] bg-transparent",
480
+ style: {
481
+ ...buttonContainer
482
+ },
483
+ onClick: increment,
484
+ children: /* @__PURE__ */ jsx6(Triangle, {
485
+ rotated: false
486
+ })
487
+ }),
488
+ /* @__PURE__ */ jsx6("button", {
489
+ type: "button",
490
+ className: "border-0 flex-1 p-0 bg-transparent pb-[5px] pl-[1px]",
491
+ style: {
492
+ ...buttonContainer
493
+ },
494
+ onClick: decrement,
495
+ children: /* @__PURE__ */ jsx6(Triangle, {
496
+ rotated: true
497
+ })
498
+ })
499
+ ]
500
+ })
501
+ ]
502
+ });
503
+ };
504
+ // src/PaperPlaneIcon.tsx
505
+ import { jsx as jsx7 } from "react/jsx-runtime";
506
+ var PlanePaperIcon = (props) => {
507
+ return /* @__PURE__ */ jsx7("svg", {
508
+ xmlns: "http://www.w3.org/2000/svg",
509
+ ...props,
510
+ viewBox: "0 0 576 512",
511
+ children: /* @__PURE__ */ jsx7("path", {
512
+ fill: "currentcolor",
513
+ d: "M169.9 280L94.9 448.6 461.2 280 169.9 280zm291.3-48L94.9 63.4 169.9 232 461.2 232zM34.8 465.6L128 256 34.8 46.4C33 42.2 32 37.6 32 33 32 14.8 46.7 0 64.8 0 69.5 0 74.2 1 78.5 3L554.2 222c13.3 6.1 21.8 19.4 21.8 34s-8.5 27.9-21.8 34L78.5 509c-4.3 2-9 3-13.7 3-18.1 0-32.8-14.8-32.8-33 0-4.6 1-9.2 2.8-13.4z"
514
+ })
515
+ });
516
+ };
517
+ // src/Switch.tsx
518
+ import { jsx as jsx8 } from "react/jsx-runtime";
519
+ var Switch = ({ active, onToggle }) => {
520
+ return /* @__PURE__ */ jsx8("div", {
521
+ "data-active": active,
522
+ className: "h-8 transition-all rounded-full w-14 border-2 border-b-4 bg-gray-200 p-[2px] cursor-pointer data-[active=true]:bg-brand border-black relative",
523
+ onClick: onToggle,
524
+ children: /* @__PURE__ */ jsx8("div", {
525
+ "data-active": active,
526
+ className: "h-4 w-4 box-content left-[4px] top-[3px] transition-all rounded-full bg-white border-2 border-black absolute data-[active=true]:left-[calc(100%-24px)]"
527
+ })
528
+ });
529
+ };
530
+ export {
531
+ Switch,
532
+ PlanePaperIcon,
533
+ Counter,
534
+ CheckIcon,
535
+ Card,
536
+ Button
537
+ };
@@ -0,0 +1,5 @@
1
+ import type { FaceType } from '@remotion/svg-3d-engine';
2
+ import React from 'react';
3
+ export declare const Faces: React.FC<{
4
+ readonly elements: FaceType[];
5
+ }>;
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { threeDIntoSvgPath } from '@remotion/svg-3d-engine';
3
+ export const Faces = ({ elements, ...svgProps }) => {
4
+ return (_jsx(_Fragment, { children: elements.map(({ points, color, crispEdges }, idx) => {
5
+ return (_jsx("path", { d: threeDIntoSvgPath(points), fill: color, shapeRendering: crispEdges ? 'crispEdges' : undefined, ...svgProps }, idx));
6
+ }) }));
7
+ };
@@ -0,0 +1,9 @@
1
+ export declare const Outer: React.FC<{
2
+ children: React.ReactNode;
3
+ width: number;
4
+ height: number;
5
+ cornerRadius: number;
6
+ hoverTransform: number;
7
+ parentRef: React.RefObject<HTMLDivElement | null>;
8
+ depthFactor: number;
9
+ }>;
@@ -0,0 +1,57 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { parsePath, PathInternals, reduceInstructions } from '@remotion/paths';
3
+ import { makeRect } from '@remotion/shapes';
4
+ import { extrudeAndTransformElement, interpolateMatrix4d, makeMatrix3dTransform, reduceMatrices, rotateX, rotateY, scaled, translateX, translateY, translateZ, } from '@remotion/svg-3d-engine';
5
+ import { interpolate } from 'remotion';
6
+ import { Faces } from './Faces';
7
+ import { useClickTransforms, useMousePosition } from './hover-transforms';
8
+ export const Outer = ({ children, width, height, cornerRadius, hoverTransform, parentRef, depthFactor, }) => {
9
+ const clickTransform = useClickTransforms(parentRef);
10
+ const angle = useMousePosition(parentRef);
11
+ const appropriateScale = Math.min(1 + 0.1 * depthFactor, (20 + width) / width);
12
+ const transformationUnhovered = reduceMatrices([
13
+ rotateX(-Math.PI / 20),
14
+ ]);
15
+ const transformationHovered = reduceMatrices([
16
+ scaled(appropriateScale),
17
+ rotateX(-Math.PI / 16),
18
+ rotateX(Math.sin(angle) / 4),
19
+ rotateY(-Math.cos(angle) / 4),
20
+ ]);
21
+ const transformation = interpolateMatrix4d(hoverTransform, transformationUnhovered, transformationHovered);
22
+ const depthFromClick = clickTransform * 15 * depthFactor;
23
+ const depthFromHover = interpolate(hoverTransform, [0, 1], [10, 20]) * depthFactor;
24
+ const depth = depthFromHover;
25
+ const frontFace = reduceMatrices([
26
+ translateZ(-depth / 2 + depthFromClick),
27
+ transformation,
28
+ ]);
29
+ const centerOriented = reduceMatrices([
30
+ translateX(-width / 2),
31
+ translateY(-height / 2),
32
+ transformation,
33
+ translateX(width / 2),
34
+ translateY(height / 2),
35
+ ]);
36
+ const { path, instructions } = makeRect({ height, width, cornerRadius });
37
+ const { viewBox } = PathInternals.getBoundingBoxFromInstructions(reduceInstructions(instructions));
38
+ const inbetween = extrudeAndTransformElement({
39
+ sideColor: 'black',
40
+ crispEdges: false,
41
+ depth,
42
+ pressInDepth: depthFromClick,
43
+ points: parsePath(path),
44
+ description: 'rect',
45
+ transformations: centerOriented,
46
+ });
47
+ return (_jsxs("div", { className: "relative", style: { width, height }, children: [_jsx("svg", { viewBox: viewBox, style: {
48
+ overflow: 'visible',
49
+ height,
50
+ width,
51
+ position: 'absolute',
52
+ top: 0,
53
+ left: 0,
54
+ }, pointerEvents: "none", children: _jsx(Faces, { elements: inbetween }) }), _jsx("div", { style: {
55
+ transform: makeMatrix3dTransform(frontFace),
56
+ }, children: children })] }));
57
+ };
@@ -0,0 +1,2 @@
1
+ import { type ClassValue } from 'clsx';
2
+ export declare function cn(...inputs: ClassValue[]): string;
@@ -0,0 +1,5 @@
1
+ import { clsx } from 'clsx';
2
+ import { twMerge } from 'tailwind-merge';
3
+ export function cn(...inputs) {
4
+ return twMerge(clsx(inputs));
5
+ }
@@ -0,0 +1 @@
1
+ export declare const getChildNodeFrom: (htmlElement: HTMLDivElement | null) => HTMLElement | null;
@@ -0,0 +1,14 @@
1
+ export const getChildNodeFrom = (htmlElement) => {
2
+ if (!htmlElement) {
3
+ return null;
4
+ }
5
+ const { childNodes } = htmlElement;
6
+ if (childNodes.length === 0) {
7
+ return null;
8
+ }
9
+ const childNode = childNodes[0];
10
+ if (!childNode) {
11
+ return null;
12
+ }
13
+ return childNode;
14
+ };
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ type State = {
3
+ progress: number;
4
+ isActive: boolean;
5
+ };
6
+ export declare const useHoverTransforms: (ref: React.RefObject<HTMLDivElement | null>, disabled: boolean) => State;
7
+ export declare const useClickTransforms: (ref: React.RefObject<HTMLDivElement | null>) => number;
8
+ export declare const useMousePosition: (ref: React.RefObject<HTMLDivElement | null>) => number;
9
+ export {};
@@ -0,0 +1,177 @@
1
+ import React, { useEffect, useMemo, useState } from 'react';
2
+ import { getChildNodeFrom } from './get-child-node-from';
3
+ export const useHoverTransforms = (ref, disabled) => {
4
+ const [state, setState] = React.useState({
5
+ progress: 0,
6
+ isActive: false,
7
+ });
8
+ const eventTarget = useMemo(() => new EventTarget(), []);
9
+ useEffect(() => {
10
+ if (disabled) {
11
+ eventTarget.dispatchEvent(new Event('disabled'));
12
+ }
13
+ else {
14
+ eventTarget.dispatchEvent(new Event('enabled'));
15
+ }
16
+ }, [disabled, eventTarget]);
17
+ React.useEffect(() => {
18
+ const element = ref.current;
19
+ if (!element)
20
+ return;
21
+ let animationFrame;
22
+ let start = null;
23
+ let isHovered = false;
24
+ let internalDisabled = disabled;
25
+ const getIsActive = () => {
26
+ return isHovered && !internalDisabled;
27
+ };
28
+ const animate = (timestamp) => {
29
+ if (start === null)
30
+ start = timestamp;
31
+ const progress = Math.min((timestamp - start) / 150, 1);
32
+ setState(() => ({
33
+ isActive: getIsActive(),
34
+ progress: getIsActive() ? progress : 1 - progress,
35
+ }));
36
+ if (progress < 1) {
37
+ animationFrame = requestAnimationFrame(animate);
38
+ }
39
+ };
40
+ const animateIn = () => {
41
+ start = null;
42
+ cancelAnimationFrame(animationFrame);
43
+ animationFrame = requestAnimationFrame(animate);
44
+ };
45
+ const handleMouseEnter = () => {
46
+ const prevIsActive = getIsActive();
47
+ isHovered = true;
48
+ if (prevIsActive === getIsActive()) {
49
+ return;
50
+ }
51
+ animateIn();
52
+ };
53
+ const handleMouseLeave = () => {
54
+ const prevIsActive = getIsActive();
55
+ isHovered = false;
56
+ if (prevIsActive === getIsActive()) {
57
+ return;
58
+ }
59
+ animateIn();
60
+ };
61
+ const handleDisabled = () => {
62
+ const prevIsActive = getIsActive();
63
+ internalDisabled = true;
64
+ if (prevIsActive === getIsActive()) {
65
+ return;
66
+ }
67
+ animateIn();
68
+ };
69
+ const handleEnabled = () => {
70
+ const prevIsActive = getIsActive();
71
+ internalDisabled = false;
72
+ if (prevIsActive === getIsActive()) {
73
+ return;
74
+ }
75
+ animateIn();
76
+ };
77
+ element.addEventListener('mouseenter', handleMouseEnter);
78
+ element.addEventListener('mouseleave', handleMouseLeave);
79
+ eventTarget.addEventListener('disabled', handleDisabled);
80
+ eventTarget.addEventListener('enabled', handleEnabled);
81
+ return () => {
82
+ element.removeEventListener('mouseenter', handleMouseEnter);
83
+ element.removeEventListener('mouseleave', handleMouseLeave);
84
+ eventTarget.removeEventListener('disabled', handleDisabled);
85
+ eventTarget.removeEventListener('enabled', handleEnabled);
86
+ cancelAnimationFrame(animationFrame);
87
+ };
88
+ // eslint-disable-next-line react-hooks/exhaustive-deps
89
+ }, [ref, eventTarget]);
90
+ return state;
91
+ };
92
+ export const useClickTransforms = (ref) => {
93
+ const [hoverProgress, setHoverProgress] = React.useState(0);
94
+ React.useEffect(() => {
95
+ const element = getChildNodeFrom(ref.current);
96
+ if (!element) {
97
+ return;
98
+ }
99
+ let animationFrame;
100
+ let start = null;
101
+ let isHovered = false;
102
+ const animate = (timestamp) => {
103
+ if (start === null)
104
+ start = timestamp;
105
+ const progress = Math.min((timestamp - start) / 150, 1);
106
+ setHoverProgress(isHovered ? progress : 1 - progress);
107
+ if (progress < 1) {
108
+ animationFrame = requestAnimationFrame(animate);
109
+ }
110
+ };
111
+ const handleMouseEnter = () => {
112
+ isHovered = true;
113
+ start = null;
114
+ cancelAnimationFrame(animationFrame);
115
+ animationFrame = requestAnimationFrame(animate);
116
+ };
117
+ const handleMouseLeave = () => {
118
+ isHovered = false;
119
+ start = null;
120
+ cancelAnimationFrame(animationFrame);
121
+ animationFrame = requestAnimationFrame(animate);
122
+ };
123
+ element.addEventListener('pointerdown', handleMouseEnter);
124
+ element.addEventListener('pointerup', handleMouseLeave);
125
+ return () => {
126
+ element.removeEventListener('pointerdown', handleMouseEnter);
127
+ element.removeEventListener('pointerup', handleMouseLeave);
128
+ cancelAnimationFrame(animationFrame);
129
+ };
130
+ }, [ref]);
131
+ return hoverProgress;
132
+ };
133
+ const getAngle = (ref, coordinates) => {
134
+ const element = getChildNodeFrom(ref);
135
+ if (!element) {
136
+ return 0;
137
+ }
138
+ if (coordinates === null) {
139
+ return 0;
140
+ }
141
+ const clientRect = element.getClientRects();
142
+ if (!clientRect) {
143
+ return 0;
144
+ }
145
+ if (clientRect.length === 0) {
146
+ return 0;
147
+ }
148
+ const center = {
149
+ x: clientRect[0].x + clientRect[0].width / 2,
150
+ y: clientRect[0].y + clientRect[0].height / 2,
151
+ };
152
+ const angle = Math.atan2(coordinates.y - center.y, coordinates.x - center.x);
153
+ return angle;
154
+ };
155
+ let lastCoordinates = null;
156
+ export const useMousePosition = (ref) => {
157
+ const [angle, setAngle] = useState(getAngle(ref.current, lastCoordinates));
158
+ useEffect(() => {
159
+ const element = ref.current;
160
+ if (!element) {
161
+ return;
162
+ }
163
+ const onMouseMove = (e) => {
164
+ const clientRect = element.getClientRects();
165
+ if (!clientRect) {
166
+ return;
167
+ }
168
+ lastCoordinates = { y: e.clientY, x: e.clientX };
169
+ setAngle(getAngle(element, { y: e.clientY, x: e.clientX }));
170
+ };
171
+ window.addEventListener('mousemove', onMouseMove);
172
+ return () => {
173
+ window.removeEventListener('mousemove', onMouseMove);
174
+ };
175
+ }, [ref]);
176
+ return angle;
177
+ };
@@ -0,0 +1,6 @@
1
+ export { Button } from './Button';
2
+ export { Card } from './Card';
3
+ export { CheckIcon } from './CheckIcon';
4
+ export { Counter } from './Counter';
5
+ export { PlanePaperIcon } from './PaperPlaneIcon';
6
+ export { Switch } from './Switch';
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { Button } from './Button';
2
+ export { Card } from './Card';
3
+ export { CheckIcon } from './CheckIcon';
4
+ export { Counter } from './Counter';
5
+ export { PlanePaperIcon } from './PaperPlaneIcon';
6
+ export { Switch } from './Switch';
package/index.css ADDED
@@ -0,0 +1 @@
1
+ @source "./dist/esm/index.mjs";
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@remotion/design",
3
+ "version": "4.0.371",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "module": "dist/esm/index.mjs",
7
+ "repository": {
8
+ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/design"
9
+ },
10
+ "sideEffects": false,
11
+ "author": "Jonny Burger <jonny@remotion.dev>",
12
+ "bugs": {
13
+ "url": "https://github.com/remotion-dev/remotion/issues"
14
+ },
15
+ "scripts": {
16
+ "formatting": "prettier --experimental-cli src --check",
17
+ "lint": "eslint src",
18
+ "watch": "tsc -w",
19
+ "make": "tsc -d && bun --env-file=../.env.bundle bundle.ts"
20
+ },
21
+ "dependencies": {
22
+ "@remotion/paths": "4.0.371",
23
+ "@remotion/shapes": "4.0.371",
24
+ "@remotion/svg-3d-engine": "4.0.371",
25
+ "clsx": "^2.1.1",
26
+ "remotion": "4.0.371"
27
+ },
28
+ "peerDependencies": {
29
+ "react": ">=16.8.0",
30
+ "react-dom": ">=16.8.0"
31
+ },
32
+ "devDependencies": {
33
+ "@remotion/eslint-config-internal": "4.0.371",
34
+ "eslint": "9.19.0",
35
+ "react": "19.0.0",
36
+ "react-dom": "19.0.0",
37
+ "tailwindcss": "4.1.10",
38
+ "tailwind-merge": "^2.6.0",
39
+ "bun-plugin-tailwind": "0.1.2"
40
+ },
41
+ "keywords": [],
42
+ "publishConfig": {
43
+ "access": "public"
44
+ },
45
+ "exports": {
46
+ ".": {
47
+ "types": "./dist/index.d.ts",
48
+ "require": "./dist/index.js",
49
+ "module": "./dist/esm/index.mjs",
50
+ "import": "./dist/esm/index.mjs"
51
+ },
52
+ "./package.json": "./package.json",
53
+ "./register": "./index.css",
54
+ "./tailwind.css": "./dist/esm/index.css"
55
+ },
56
+ "description": "Design system",
57
+ "homepage": "https://www.remotion.dev/design"
58
+ }