@dreamtree-org/twreact-ui 2.1.2 → 2.2.1
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 +47 -4
- package/ai-skills/dreamtree-ui.md +20 -3
- package/dist/_shared/{cn-DPPQUJu1.js → cn-TMJ-_w1a.js} +14 -1
- package/dist/_shared/useLatestRef-CdtlnPUz.js +21 -0
- package/dist/_shared/useReducedMotion-B_PMM5ER.js +77 -0
- package/dist/ai-schema.json +513 -0
- package/dist/charts/index.js +6 -76
- package/dist/components/motion/BentoExpandGrid.d.ts +10 -0
- package/dist/components/motion/BentoExpandGrid.d.ts.map +1 -0
- package/dist/components/motion/CountUp.d.ts +9 -0
- package/dist/components/motion/CountUp.d.ts.map +1 -0
- package/dist/components/motion/DeviceFrame.d.ts +8 -0
- package/dist/components/motion/DeviceFrame.d.ts.map +1 -0
- package/dist/components/motion/DeviceMorphHero.d.ts +11 -0
- package/dist/components/motion/DeviceMorphHero.d.ts.map +1 -0
- package/dist/components/motion/LogoMarquee.d.ts +9 -0
- package/dist/components/motion/LogoMarquee.d.ts.map +1 -0
- package/dist/components/motion/PhotoCollage.d.ts +9 -0
- package/dist/components/motion/PhotoCollage.d.ts.map +1 -0
- package/dist/components/motion/Reveal.d.ts +9 -0
- package/dist/components/motion/Reveal.d.ts.map +1 -0
- package/dist/components/motion/RevealGroup.d.ts +5 -0
- package/dist/components/motion/RevealGroup.d.ts.map +1 -0
- package/dist/components/motion/RotatingBadge.d.ts +9 -0
- package/dist/components/motion/RotatingBadge.d.ts.map +1 -0
- package/dist/components/motion/ScrollStage.d.ts +11 -0
- package/dist/components/motion/ScrollStage.d.ts.map +1 -0
- package/dist/components/motion/SmoothScrollProvider.d.ts +18 -0
- package/dist/components/motion/SmoothScrollProvider.d.ts.map +1 -0
- package/dist/components/motion/StackedCards.d.ts +10 -0
- package/dist/components/motion/StackedCards.d.ts.map +1 -0
- package/dist/components/motion/StatStrip.d.ts +8 -0
- package/dist/components/motion/StatStrip.d.ts.map +1 -0
- package/dist/components/motion/TestimonialSpotlight.d.ts +10 -0
- package/dist/components/motion/TestimonialSpotlight.d.ts.map +1 -0
- package/dist/components/motion/storyData.d.ts +52 -0
- package/dist/components/motion/storyData.d.ts.map +1 -0
- package/dist/esm/components/motion/BentoExpandGrid.js +144 -0
- package/dist/esm/components/motion/CountUp.js +97 -0
- package/dist/esm/components/motion/DeviceFrame.js +102 -0
- package/dist/esm/components/motion/DeviceMorphHero.js +228 -0
- package/dist/esm/components/motion/LogoMarquee.js +144 -0
- package/dist/esm/components/motion/PhotoCollage.js +92 -0
- package/dist/esm/components/motion/Reveal.js +115 -0
- package/dist/esm/components/motion/RevealGroup.js +43 -0
- package/dist/esm/components/motion/RotatingBadge.js +66 -0
- package/dist/esm/components/motion/ScrollStage.js +62 -0
- package/dist/esm/components/motion/SmoothScrollProvider.js +63 -0
- package/dist/esm/components/motion/StackedCards.js +166 -0
- package/dist/esm/components/motion/StatStrip.js +58 -0
- package/dist/esm/components/motion/TestimonialSpotlight.js +209 -0
- package/dist/esm/hooks/useScrollProgress.js +107 -0
- package/dist/esm/hooks/useSmoothScroll.js +33 -0
- package/dist/esm/motion/engine/inView.js +54 -0
- package/dist/esm/motion/engine/progress.js +45 -0
- package/dist/esm/motion/engine/scheduler.js +67 -0
- package/dist/esm/motion/engine/useHydrated.js +17 -0
- package/dist/esm/motion/engine/useIsomorphicLayoutEffect.js +7 -0
- package/dist/esm/motion/engine/useMergedRef.js +12 -0
- package/dist/esm/motion/index.js +16 -0
- package/dist/esm/motion/tokens.js +10 -0
- package/dist/hooks/useScrollProgress.d.ts +17 -0
- package/dist/hooks/useScrollProgress.d.ts.map +1 -0
- package/dist/hooks/useSmoothScroll.d.ts +11 -0
- package/dist/hooks/useSmoothScroll.d.ts.map +1 -0
- package/dist/index.css +1 -1
- package/dist/index.esm.css +1 -1
- package/dist/motion/engine/inView.d.ts +5 -0
- package/dist/motion/engine/inView.d.ts.map +1 -0
- package/dist/motion/engine/progress.d.ts +18 -0
- package/dist/motion/engine/progress.d.ts.map +1 -0
- package/dist/motion/engine/scheduler.d.ts +10 -0
- package/dist/motion/engine/scheduler.d.ts.map +1 -0
- package/dist/motion/engine/useHydrated.d.ts +3 -0
- package/dist/motion/engine/useHydrated.d.ts.map +1 -0
- package/dist/motion/engine/useIsomorphicLayoutEffect.d.ts +4 -0
- package/dist/motion/engine/useIsomorphicLayoutEffect.d.ts.map +1 -0
- package/dist/motion/engine/useMergedRef.d.ts +3 -0
- package/dist/motion/engine/useMergedRef.d.ts.map +1 -0
- package/dist/motion/index.d.ts +20 -0
- package/dist/motion/index.d.ts.map +1 -0
- package/dist/motion/index.js +1813 -0
- package/dist/motion/tokens.d.ts +6 -0
- package/dist/motion/tokens.d.ts.map +1 -0
- package/dist/rich-text/index.js +3 -18
- package/dist/tokens/tokens.json +21 -0
- package/dist/types/motion.d.ts +290 -0
- package/dist/types/motion.d.ts.map +1 -0
- package/doc/README.md +17 -1
- package/mcp/catalog.snapshot.json +952 -5
- package/motion/package.json +5 -0
- package/package.json +14 -3
- package/tokens/tokens.json +6 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export default BentoExpandGrid;
|
|
2
|
+
/**
|
|
3
|
+
* A photo grid whose active tile grows (its row and column tracks widen) while the
|
|
4
|
+
* neighbours shrink. Hover, keyboard focus and — with `trigger="click"` — tap expand a
|
|
5
|
+
* tile, and arrow keys move between tiles, so it never depends on a mouse. Below `md` it
|
|
6
|
+
* becomes a horizontal snap scroller. Under reduced motion the resize is instant.
|
|
7
|
+
*/
|
|
8
|
+
declare const BentoExpandGrid: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
|
|
9
|
+
import React from "react";
|
|
10
|
+
//# sourceMappingURL=BentoExpandGrid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BentoExpandGrid.d.ts","sourceRoot":"","sources":["../../../src/components/motion/BentoExpandGrid.jsx"],"names":[],"mappings":";AASA;;;;;GAKG;AACH,yFA+FE;kBA9GsC,OAAO"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export default CountUp;
|
|
2
|
+
/**
|
|
3
|
+
* A number that counts up when it scrolls into view. The server (and reduced motion)
|
|
4
|
+
* renders the real final value, so crawlers and no-JS readers never see "0". Screen readers
|
|
5
|
+
* read the final value once from a visually hidden copy; the animating digits are hidden.
|
|
6
|
+
*/
|
|
7
|
+
declare const CountUp: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
|
|
8
|
+
import React from "react";
|
|
9
|
+
//# sourceMappingURL=CountUp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CountUp.d.ts","sourceRoot":"","sources":["../../../src/components/motion/CountUp.jsx"],"names":[],"mappings":";AAaA;;;;GAIG;AACH,iFA8DE;kBAhFgD,OAAO"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export default DeviceFrame;
|
|
2
|
+
/**
|
|
3
|
+
* A CSS-only device mock-up (phone, tablet, laptop or browser window) around any
|
|
4
|
+
* screen content. Purely presentational: no motion, works anywhere.
|
|
5
|
+
*/
|
|
6
|
+
declare const DeviceFrame: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
|
|
7
|
+
import React from "react";
|
|
8
|
+
//# sourceMappingURL=DeviceFrame.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeviceFrame.d.ts","sourceRoot":"","sources":["../../../src/components/motion/DeviceFrame.jsx"],"names":[],"mappings":";AA+CA;;;GAGG;AACH,qFAuBE;kBA1EgB,OAAO"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export default DeviceMorphHero;
|
|
2
|
+
/**
|
|
3
|
+
* The signature scroll hero: full-bleed media shrinks into a device frame, the bezel fades
|
|
4
|
+
* in, then the device slides aside while the copy (`content`) fades in beside it. The
|
|
5
|
+
* timeline maps the scene's scroll progress: 0–45 % morph, 40–60 % bezel, 60–90 % slide.
|
|
6
|
+
* The server, no-JS readers and reduced-motion users get the final layout (copy beside the
|
|
7
|
+
* device) with no pinning. Below `md` the device rises and shrinks and the copy appears under it.
|
|
8
|
+
*/
|
|
9
|
+
declare const DeviceMorphHero: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
|
|
10
|
+
import React from "react";
|
|
11
|
+
//# sourceMappingURL=DeviceMorphHero.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeviceMorphHero.d.ts","sourceRoot":"","sources":["../../../src/components/motion/DeviceMorphHero.jsx"],"names":[],"mappings":";AAuCA;;;;;;GAMG;AACH,yFAmLE;kBAjOoD,OAAO"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export default LogoMarquee;
|
|
2
|
+
/**
|
|
3
|
+
* An endless strip of logos or names. The second copy of the list (needed for a seamless
|
|
4
|
+
* loop) is `aria-hidden`, so screen readers read each item once. Pauses on hover, while
|
|
5
|
+
* focus is inside and while off screen; under reduced motion it is a static, wrapped row.
|
|
6
|
+
*/
|
|
7
|
+
declare const LogoMarquee: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
|
|
8
|
+
import React from "react";
|
|
9
|
+
//# sourceMappingURL=LogoMarquee.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LogoMarquee.d.ts","sourceRoot":"","sources":["../../../src/components/motion/LogoMarquee.jsx"],"names":[],"mappings":";AA6CA;;;;GAIG;AACH,qFA2EE;kBA7HiD,OAAO"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export default PhotoCollage;
|
|
2
|
+
/**
|
|
3
|
+
* Overlapping, offset photos with floating stat chips and an optional badge. On scroll the
|
|
4
|
+
* photos drift at different depths (parallax), driven by a CSS variable — no re-renders.
|
|
5
|
+
* Under reduced motion (or `parallax={0}`) they stay put.
|
|
6
|
+
*/
|
|
7
|
+
declare const PhotoCollage: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
|
|
8
|
+
import React from "react";
|
|
9
|
+
//# sourceMappingURL=PhotoCollage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PhotoCollage.d.ts","sourceRoot":"","sources":["../../../src/components/motion/PhotoCollage.jsx"],"names":[],"mappings":";AAmBA;;;;GAIG;AACH,sFA2CE;kBAnE4B,OAAO"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export default Reveal;
|
|
2
|
+
/**
|
|
3
|
+
* Plays an entrance when the element scrolls into view. The server, no-JS readers and
|
|
4
|
+
* reduced-motion users get the content as-is; elements already on screen at load are not
|
|
5
|
+
* hidden (no flash, no LCP delay). Only content below the fold animates.
|
|
6
|
+
*/
|
|
7
|
+
declare const Reveal: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
|
|
8
|
+
import React from "react";
|
|
9
|
+
//# sourceMappingURL=Reveal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Reveal.d.ts","sourceRoot":"","sources":["../../../src/components/motion/Reveal.jsx"],"names":[],"mappings":";AAoBA;;;;GAIG;AACH,gFAyEE;kBAlGsC,OAAO"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RevealGroup.d.ts","sourceRoot":"","sources":["../../../src/components/motion/RevealGroup.jsx"],"names":[],"mappings":";AAGA,4EAA4E;AAC5E,qFAoBE;kBAxBgB,OAAO"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export default RotatingBadge;
|
|
2
|
+
/**
|
|
3
|
+
* A circular badge with text set around its edge, slowly turning (SVG `textPath`). The
|
|
4
|
+
* text is spread to fill the circle exactly. Exposed as one image named by `text`
|
|
5
|
+
* (override with `aria-label`); it stops turning under reduced motion.
|
|
6
|
+
*/
|
|
7
|
+
declare const RotatingBadge: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
|
|
8
|
+
import React from "react";
|
|
9
|
+
//# sourceMappingURL=RotatingBadge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RotatingBadge.d.ts","sourceRoot":"","sources":["../../../src/components/motion/RotatingBadge.jsx"],"names":[],"mappings":";AAMA;;;;GAIG;AACH,uFAiCG;kBA5C0B,OAAO"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export default ScrollStage;
|
|
2
|
+
/**
|
|
3
|
+
* A pinned scroll scene: a tall section whose content sticks to the viewport while the
|
|
4
|
+
* user scrolls through `length` vh. Progress (0–1) is written to `--dt-p` on the root, so
|
|
5
|
+
* children animate with CSS (`opacity: var(--dt-p, 1)`), and passed to `children(progress)`
|
|
6
|
+
* and `onProgress`. Under reduced motion, or with `pin={false}`, it renders in normal flow
|
|
7
|
+
* at its final state.
|
|
8
|
+
*/
|
|
9
|
+
declare const ScrollStage: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
|
|
10
|
+
import React from "react";
|
|
11
|
+
//# sourceMappingURL=ScrollStage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ScrollStage.d.ts","sourceRoot":"","sources":["../../../src/components/motion/ScrollStage.jsx"],"names":[],"mappings":";AAQA;;;;;;GAMG;AACH,qFAsCE;kBArD4B,OAAO"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export default SmoothScrollProvider;
|
|
2
|
+
/**
|
|
3
|
+
* Opt-in smooth (inertial) scrolling with Lenis. Lenis is an optional peer dependency
|
|
4
|
+
* and is never imported by this package: install it and pass the class —
|
|
5
|
+
* `<SmoothScrollProvider lenis={Lenis}>`. Without `lenis`, with `enabled={false}` or when
|
|
6
|
+
* the user prefers reduced motion, the page keeps native scrolling. Lenis runs on the same
|
|
7
|
+
* frame loop as the other motion components.
|
|
8
|
+
*/
|
|
9
|
+
declare function SmoothScrollProvider({ lenis: LenisClass, options, enabled, children }: {
|
|
10
|
+
lenis: any;
|
|
11
|
+
options: any;
|
|
12
|
+
enabled?: boolean | undefined;
|
|
13
|
+
children: any;
|
|
14
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
declare namespace SmoothScrollProvider {
|
|
16
|
+
let displayName: string;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=SmoothScrollProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SmoothScrollProvider.d.ts","sourceRoot":"","sources":["../../../src/components/motion/SmoothScrollProvider.jsx"],"names":[],"mappings":";AAKA;;;;;;GAMG;AACH;;;;;4CA2BC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export default StackedCards;
|
|
2
|
+
/**
|
|
3
|
+
* Cards that stick one over another as the page scrolls (sticky stacking). Cards
|
|
4
|
+
* underneath shrink and dim as the next one covers them, and each has a slight
|
|
5
|
+
* alternating tilt so the stack looks hand-placed. Tilt is off below `md` and under
|
|
6
|
+
* reduced motion; the scale/dim effect is off under reduced motion.
|
|
7
|
+
*/
|
|
8
|
+
declare const StackedCards: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
|
|
9
|
+
import React from "react";
|
|
10
|
+
//# sourceMappingURL=StackedCards.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StackedCards.d.ts","sourceRoot":"","sources":["../../../src/components/motion/StackedCards.jsx"],"names":[],"mappings":";AAqDA;;;;;GAKG;AACH,sFA6EE;kBAxIuC,OAAO"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export default StatStrip;
|
|
2
|
+
/**
|
|
3
|
+
* A row of headline numbers that count up on view — as bordered cards or one band with
|
|
4
|
+
* dividers. A description list: each label is a `<dt>`, each number its `<dd>`.
|
|
5
|
+
*/
|
|
6
|
+
declare const StatStrip: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
|
|
7
|
+
import React from "react";
|
|
8
|
+
//# sourceMappingURL=StatStrip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatStrip.d.ts","sourceRoot":"","sources":["../../../src/components/motion/StatStrip.jsx"],"names":[],"mappings":";AAMA;;;GAGG;AACH,mFAsCG;kBAhDe,OAAO"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export default TestimonialSpotlight;
|
|
2
|
+
/**
|
|
3
|
+
* Client quotes with a 3×3 tile grid of logos: the active client's logo sits in the centre
|
|
4
|
+
* tile and the quote beside it. Dots are a tab list (arrow keys, Home/End). Autoplay pauses
|
|
5
|
+
* on hover, while focus is inside, while off screen and under reduced motion, and has a
|
|
6
|
+
* visible pause button (WCAG 2.2.2).
|
|
7
|
+
*/
|
|
8
|
+
declare const TestimonialSpotlight: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
|
|
9
|
+
import React from "react";
|
|
10
|
+
//# sourceMappingURL=TestimonialSpotlight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TestimonialSpotlight.d.ts","sourceRoot":"","sources":["../../../src/components/motion/TestimonialSpotlight.jsx"],"names":[],"mappings":";AAgBA;;;;;GAKG;AACH,8FAgIE;kBAtJwD,OAAO"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** A token-coloured placeholder screen for device mock-ups. */
|
|
2
|
+
export function Screen({ label }: {
|
|
3
|
+
label?: string | undefined;
|
|
4
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
export function photo(seed: any, w?: number, h?: number): string;
|
|
6
|
+
export const clients: string[];
|
|
7
|
+
export const stats: ({
|
|
8
|
+
value: number;
|
|
9
|
+
suffix: string;
|
|
10
|
+
label: string;
|
|
11
|
+
prefix?: undefined;
|
|
12
|
+
} | {
|
|
13
|
+
value: number;
|
|
14
|
+
label: string;
|
|
15
|
+
suffix?: undefined;
|
|
16
|
+
prefix?: undefined;
|
|
17
|
+
} | {
|
|
18
|
+
value: number;
|
|
19
|
+
prefix: string;
|
|
20
|
+
label: string;
|
|
21
|
+
suffix?: undefined;
|
|
22
|
+
})[];
|
|
23
|
+
export const pillars: {
|
|
24
|
+
kicker: string;
|
|
25
|
+
title: string;
|
|
26
|
+
body: string;
|
|
27
|
+
bullets: string[];
|
|
28
|
+
metric: {
|
|
29
|
+
value: string;
|
|
30
|
+
label: string;
|
|
31
|
+
};
|
|
32
|
+
media: {
|
|
33
|
+
src: string;
|
|
34
|
+
alt: string;
|
|
35
|
+
};
|
|
36
|
+
}[];
|
|
37
|
+
export const projects: {
|
|
38
|
+
title: string;
|
|
39
|
+
tag: string;
|
|
40
|
+
client: string;
|
|
41
|
+
media: {
|
|
42
|
+
src: string;
|
|
43
|
+
alt: string;
|
|
44
|
+
};
|
|
45
|
+
}[];
|
|
46
|
+
export const testimonials: {
|
|
47
|
+
quote: string;
|
|
48
|
+
name: string;
|
|
49
|
+
role: string;
|
|
50
|
+
logo: string;
|
|
51
|
+
}[];
|
|
52
|
+
//# sourceMappingURL=storyData.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storyData.d.ts","sourceRoot":"","sources":["../../../src/components/motion/storyData.js"],"names":[],"mappings":"AA8DA,+DAA+D;AAC/D;;4CAQC;AAtEM,iEAAwF;AAE/F,+BAAoH;AAEpH;;;;;;;;;;;;;;;KAKE;AAEF;;;;;;;;;;;;;IAiCE;AAEF;;;;;;;;IAOE;AAEF;;;;;IAIE"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { objectWithoutProperties as _objectWithoutProperties, slicedToArray as _slicedToArray, objectSpread2 as _objectSpread2, typeof as _typeof } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
3
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
+
import React, { useRef, useState } from 'react';
|
|
5
|
+
import { cn } from '../../utils/cn.js';
|
|
6
|
+
import { useMergedRef } from '../../motion/engine/useMergedRef.js';
|
|
7
|
+
|
|
8
|
+
var _excluded = ["items", "cols", "expand", "trigger", "label", "className", "style", "onMouseLeave"];
|
|
9
|
+
var isImage = function isImage(media) {
|
|
10
|
+
return media && _typeof(media) === "object" && ! /*#__PURE__*/React.isValidElement(media) && "src" in media;
|
|
11
|
+
};
|
|
12
|
+
var tracks = function tracks(count, active, expand) {
|
|
13
|
+
return Array.from({
|
|
14
|
+
length: count
|
|
15
|
+
}, function (_, i) {
|
|
16
|
+
return i === active ? "".concat(expand, "fr") : "1fr";
|
|
17
|
+
}).join(" ");
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* A photo grid whose active tile grows (its row and column tracks widen) while the
|
|
21
|
+
* neighbours shrink. Hover, keyboard focus and — with `trigger="click"` — tap expand a
|
|
22
|
+
* tile, and arrow keys move between tiles, so it never depends on a mouse. Below `md` it
|
|
23
|
+
* becomes a horizontal snap scroller. Under reduced motion the resize is instant.
|
|
24
|
+
*/
|
|
25
|
+
var BentoExpandGrid = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
26
|
+
var _ref$items = _ref.items,
|
|
27
|
+
items = _ref$items === void 0 ? [] : _ref$items,
|
|
28
|
+
_ref$cols = _ref.cols,
|
|
29
|
+
cols = _ref$cols === void 0 ? 3 : _ref$cols,
|
|
30
|
+
_ref$expand = _ref.expand,
|
|
31
|
+
expand = _ref$expand === void 0 ? 2 : _ref$expand,
|
|
32
|
+
_ref$trigger = _ref.trigger,
|
|
33
|
+
trigger = _ref$trigger === void 0 ? "hover" : _ref$trigger,
|
|
34
|
+
label = _ref.label,
|
|
35
|
+
className = _ref.className,
|
|
36
|
+
style = _ref.style,
|
|
37
|
+
_onMouseLeave = _ref.onMouseLeave,
|
|
38
|
+
rest = _objectWithoutProperties(_ref, _excluded);
|
|
39
|
+
var local = useRef(null);
|
|
40
|
+
var setRef = useMergedRef(ref, local);
|
|
41
|
+
var _useState = useState(null),
|
|
42
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
43
|
+
active = _useState2[0],
|
|
44
|
+
setActive = _useState2[1];
|
|
45
|
+
var rows = Math.max(1, Math.ceil(items.length / cols));
|
|
46
|
+
var activeCol = active == null ? -1 : active % cols;
|
|
47
|
+
var activeRow = active == null ? -1 : Math.floor(active / cols);
|
|
48
|
+
var focusTile = function focusTile(index) {
|
|
49
|
+
var tiles = local.current ? local.current.querySelectorAll("[data-bento-tile]") : [];
|
|
50
|
+
if (tiles[index]) tiles[index].focus();
|
|
51
|
+
};
|
|
52
|
+
var _onKeyDown = function onKeyDown(event, index) {
|
|
53
|
+
var step = {
|
|
54
|
+
ArrowRight: 1,
|
|
55
|
+
ArrowLeft: -1,
|
|
56
|
+
ArrowDown: cols,
|
|
57
|
+
ArrowUp: -cols
|
|
58
|
+
}[event.key];
|
|
59
|
+
if (step === undefined) {
|
|
60
|
+
if (event.key === "Home") focusTile(0);else if (event.key === "End") focusTile(items.length - 1);else return;
|
|
61
|
+
event.preventDefault();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
var next = index + step;
|
|
65
|
+
if (next >= 0 && next < items.length) {
|
|
66
|
+
event.preventDefault();
|
|
67
|
+
focusTile(next);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
return jsx("ul", _objectSpread2(_objectSpread2({
|
|
71
|
+
ref: setRef,
|
|
72
|
+
"aria-label": label,
|
|
73
|
+
className: cn("flex snap-x snap-mandatory gap-4 overflow-x-auto pb-2", "md:grid md:h-[min(80vh,720px)] md:snap-none md:overflow-visible md:pb-0", "md:transition-[grid-template-columns,grid-template-rows] md:duration-500 md:ease-emphasized motion-reduce:transition-none", className),
|
|
74
|
+
style: _objectSpread2({
|
|
75
|
+
gridTemplateColumns: tracks(cols, activeCol, expand),
|
|
76
|
+
gridTemplateRows: tracks(rows, activeRow, expand)
|
|
77
|
+
}, style),
|
|
78
|
+
onMouseLeave: function onMouseLeave(e) {
|
|
79
|
+
if (trigger === "hover") setActive(null);
|
|
80
|
+
if (_onMouseLeave) _onMouseLeave(e);
|
|
81
|
+
}
|
|
82
|
+
}, rest), {}, {
|
|
83
|
+
children: items.map(function (item, i) {
|
|
84
|
+
var _item$id;
|
|
85
|
+
var Tag = item.href ? "a" : trigger === "click" ? "button" : "div";
|
|
86
|
+
var expanded = active === i;
|
|
87
|
+
var interactive = {
|
|
88
|
+
"data-bento-tile": "",
|
|
89
|
+
onKeyDown: function onKeyDown(e) {
|
|
90
|
+
return _onKeyDown(e, i);
|
|
91
|
+
},
|
|
92
|
+
onFocus: trigger !== "click" ? function () {
|
|
93
|
+
return setActive(i);
|
|
94
|
+
} : undefined,
|
|
95
|
+
onMouseEnter: trigger === "hover" ? function () {
|
|
96
|
+
return setActive(i);
|
|
97
|
+
} : undefined,
|
|
98
|
+
onClick: trigger === "click" ? function () {
|
|
99
|
+
return setActive(expanded ? null : i);
|
|
100
|
+
} : undefined
|
|
101
|
+
};
|
|
102
|
+
if (Tag === "a") interactive.href = item.href;
|
|
103
|
+
if (Tag === "button") {
|
|
104
|
+
interactive.type = "button";
|
|
105
|
+
interactive["aria-pressed"] = expanded;
|
|
106
|
+
}
|
|
107
|
+
if (Tag === "div") interactive.tabIndex = 0;
|
|
108
|
+
return jsx("li", {
|
|
109
|
+
className: "w-[80%] shrink-0 snap-start sm:w-[45%] md:w-auto md:min-h-0 md:min-w-0",
|
|
110
|
+
children: jsxs(Tag, _objectSpread2(_objectSpread2({}, interactive), {}, {
|
|
111
|
+
"data-active": expanded ? "" : undefined,
|
|
112
|
+
className: "group relative block h-72 w-full overflow-hidden rounded-card text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 md:h-full",
|
|
113
|
+
children: [isImage(item.media) ? jsx("img", {
|
|
114
|
+
src: item.media.src,
|
|
115
|
+
alt: item.media.alt,
|
|
116
|
+
loading: "lazy",
|
|
117
|
+
className: "absolute inset-0 h-full w-full object-cover transition-transform duration-700 ease-emphasized group-hover:scale-105 group-data-[active]:scale-105 motion-reduce:transition-none motion-reduce:group-hover:scale-100"
|
|
118
|
+
}) : jsx("span", {
|
|
119
|
+
className: "absolute inset-0",
|
|
120
|
+
children: item.media
|
|
121
|
+
}), jsx("span", {
|
|
122
|
+
"aria-hidden": "true",
|
|
123
|
+
className: "absolute inset-0 bg-gradient-to-t from-gray-950/80 via-gray-950/20 to-transparent"
|
|
124
|
+
}), jsxs("span", {
|
|
125
|
+
className: "absolute inset-x-0 bottom-0 flex flex-col gap-1 p-4 text-primary-foreground",
|
|
126
|
+
children: [item.tag ? jsx("span", {
|
|
127
|
+
className: "w-max rounded-pill bg-primary-foreground/20 px-2.5 py-0.5 text-micro uppercase tracking-wider backdrop-blur",
|
|
128
|
+
children: item.tag
|
|
129
|
+
}) : null, item.client ? jsx("span", {
|
|
130
|
+
className: "text-caption text-primary-foreground/80",
|
|
131
|
+
children: item.client
|
|
132
|
+
}) : null, jsx("span", {
|
|
133
|
+
className: "text-body font-semibold",
|
|
134
|
+
children: item.title
|
|
135
|
+
})]
|
|
136
|
+
})]
|
|
137
|
+
}))
|
|
138
|
+
}, (_item$id = item.id) !== null && _item$id !== void 0 ? _item$id : i);
|
|
139
|
+
})
|
|
140
|
+
}));
|
|
141
|
+
});
|
|
142
|
+
BentoExpandGrid.displayName = "BentoExpandGrid";
|
|
143
|
+
|
|
144
|
+
export { BentoExpandGrid as default };
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { objectWithoutProperties as _objectWithoutProperties, objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
3
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
import React, { useRef, useMemo, useEffect } from 'react';
|
|
5
|
+
import { cn } from '../../utils/cn.js';
|
|
6
|
+
import { useReducedMotion } from '../../hooks/useReducedMotion.js';
|
|
7
|
+
import { observe } from '../../motion/engine/inView.js';
|
|
8
|
+
import { subscribe } from '../../motion/engine/scheduler.js';
|
|
9
|
+
import { easeOut } from '../../motion/engine/progress.js';
|
|
10
|
+
|
|
11
|
+
var _excluded = ["value", "from", "prefix", "suffix", "duration", "decimals", "locale", "format", "className"];
|
|
12
|
+
var decimalsOf = function decimalsOf(n) {
|
|
13
|
+
var s = String(n);
|
|
14
|
+
var dot = s.indexOf(".");
|
|
15
|
+
return dot === -1 ? 0 : s.length - dot - 1;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* A number that counts up when it scrolls into view. The server (and reduced motion)
|
|
19
|
+
* renders the real final value, so crawlers and no-JS readers never see "0". Screen readers
|
|
20
|
+
* read the final value once from a visually hidden copy; the animating digits are hidden.
|
|
21
|
+
*/
|
|
22
|
+
var CountUp = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
23
|
+
var value = _ref.value,
|
|
24
|
+
_ref$from = _ref.from,
|
|
25
|
+
from = _ref$from === void 0 ? 0 : _ref$from,
|
|
26
|
+
prefix = _ref.prefix,
|
|
27
|
+
suffix = _ref.suffix,
|
|
28
|
+
_ref$duration = _ref.duration,
|
|
29
|
+
duration = _ref$duration === void 0 ? 1600 : _ref$duration,
|
|
30
|
+
decimals = _ref.decimals,
|
|
31
|
+
_ref$locale = _ref.locale,
|
|
32
|
+
locale = _ref$locale === void 0 ? "en-IN" : _ref$locale,
|
|
33
|
+
format = _ref.format,
|
|
34
|
+
className = _ref.className,
|
|
35
|
+
rest = _objectWithoutProperties(_ref, _excluded);
|
|
36
|
+
var live = useRef(null);
|
|
37
|
+
var reduced = useReducedMotion();
|
|
38
|
+
var digits = decimals !== null && decimals !== void 0 ? decimals : decimalsOf(value);
|
|
39
|
+
var fmt = useMemo(function () {
|
|
40
|
+
if (format) return format;
|
|
41
|
+
var nf = new Intl.NumberFormat(locale, {
|
|
42
|
+
minimumFractionDigits: digits,
|
|
43
|
+
maximumFractionDigits: digits
|
|
44
|
+
});
|
|
45
|
+
return function (n) {
|
|
46
|
+
return nf.format(n);
|
|
47
|
+
};
|
|
48
|
+
}, [format, locale, digits]);
|
|
49
|
+
var finalText = fmt(value);
|
|
50
|
+
useEffect(function () {
|
|
51
|
+
var el = live.current;
|
|
52
|
+
if (!el || reduced || duration <= 0) return undefined;
|
|
53
|
+
// Below the fold: show the start value until it scrolls in. On screen: count right away.
|
|
54
|
+
if (el.getBoundingClientRect().top > innerHeight) el.textContent = fmt(from);
|
|
55
|
+
var unsubscribe = null;
|
|
56
|
+
var stop = function stop() {};
|
|
57
|
+
stop = observe(el, function (inView) {
|
|
58
|
+
if (!inView || unsubscribe) return;
|
|
59
|
+
stop();
|
|
60
|
+
var t0 = null;
|
|
61
|
+
unsubscribe = subscribe({
|
|
62
|
+
loop: true,
|
|
63
|
+
write: function write(_, now) {
|
|
64
|
+
if (t0 === null) t0 = now;
|
|
65
|
+
var t = Math.min(1, (now - t0) / duration);
|
|
66
|
+
el.textContent = t < 1 ? fmt(from + (value - from) * easeOut(t)) : fmt(value);
|
|
67
|
+
if (t >= 1) unsubscribe();
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}, {
|
|
71
|
+
threshold: 0.4
|
|
72
|
+
});
|
|
73
|
+
return function () {
|
|
74
|
+
stop();
|
|
75
|
+
if (unsubscribe) unsubscribe();
|
|
76
|
+
el.textContent = fmt(value);
|
|
77
|
+
};
|
|
78
|
+
}, [value, from, duration, fmt, reduced]);
|
|
79
|
+
return jsxs("span", _objectSpread2(_objectSpread2({
|
|
80
|
+
ref: ref,
|
|
81
|
+
className: cn("tabular-nums", className)
|
|
82
|
+
}, rest), {}, {
|
|
83
|
+
children: [jsxs("span", {
|
|
84
|
+
"aria-hidden": "true",
|
|
85
|
+
children: [prefix, jsx("span", {
|
|
86
|
+
ref: live,
|
|
87
|
+
children: finalText
|
|
88
|
+
}), suffix]
|
|
89
|
+
}), jsxs("span", {
|
|
90
|
+
className: "sr-only",
|
|
91
|
+
children: [prefix, finalText, suffix]
|
|
92
|
+
})]
|
|
93
|
+
}));
|
|
94
|
+
});
|
|
95
|
+
CountUp.displayName = "CountUp";
|
|
96
|
+
|
|
97
|
+
export { CountUp as default };
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { objectWithoutProperties as _objectWithoutProperties, objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
3
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { cn } from '../../utils/cn.js';
|
|
6
|
+
|
|
7
|
+
var _excluded = ["device", "url", "screenClassName", "screenRef", "className", "children"];
|
|
8
|
+
// Bezel parts read `--dt-chrome` (opacity, default 1) so DeviceMorphHero can fade them in.
|
|
9
|
+
var CHROME = "opacity-[var(--dt-chrome,1)]";
|
|
10
|
+
// Bezels are borders (not filled boxes) so the screen area stays see-through: DeviceMorphHero
|
|
11
|
+
// slides its full-bleed media layer under a transparent screen.
|
|
12
|
+
var FRAMES = {
|
|
13
|
+
phone: {
|
|
14
|
+
root: "w-[220px] md:w-[262px] aspect-[262/562]",
|
|
15
|
+
bezel: "inset-0 rounded-[2.75rem] md:rounded-[3.25rem] border-[10px] border-shell shadow-2xl",
|
|
16
|
+
screen: "inset-[10px] rounded-[2.1rem] md:rounded-[2.6rem]",
|
|
17
|
+
extras: jsxs(Fragment, {
|
|
18
|
+
children: [jsx("span", {
|
|
19
|
+
"aria-hidden": "true",
|
|
20
|
+
className: cn("absolute left-1/2 top-[18px] h-[22px] w-[30%] -translate-x-1/2 rounded-pill bg-shell", CHROME)
|
|
21
|
+
}), jsx("span", {
|
|
22
|
+
"aria-hidden": "true",
|
|
23
|
+
className: cn("absolute bottom-[16px] left-1/2 h-[4px] w-[34%] -translate-x-1/2 rounded-pill bg-shell-foreground/70", CHROME)
|
|
24
|
+
}), jsx("span", {
|
|
25
|
+
"aria-hidden": "true",
|
|
26
|
+
className: cn("absolute -left-[3px] top-[22%] h-[9%] w-[3px] rounded-l bg-shell-active", CHROME)
|
|
27
|
+
}), jsx("span", {
|
|
28
|
+
"aria-hidden": "true",
|
|
29
|
+
className: cn("absolute -right-[3px] top-[28%] h-[14%] w-[3px] rounded-r bg-shell-active", CHROME)
|
|
30
|
+
})]
|
|
31
|
+
})
|
|
32
|
+
},
|
|
33
|
+
tablet: {
|
|
34
|
+
root: "w-[320px] md:w-[440px] aspect-[3/4]",
|
|
35
|
+
bezel: "inset-0 rounded-[2rem] border-[14px] border-shell shadow-2xl",
|
|
36
|
+
screen: "inset-[14px] rounded-[1rem]",
|
|
37
|
+
extras: jsx("span", {
|
|
38
|
+
"aria-hidden": "true",
|
|
39
|
+
className: cn("absolute left-1/2 top-[5px] h-[4px] w-[4px] -translate-x-1/2 rounded-full bg-shell-active", CHROME)
|
|
40
|
+
})
|
|
41
|
+
},
|
|
42
|
+
laptop: {
|
|
43
|
+
root: "w-[340px] md:w-[640px] aspect-[16/10.6]",
|
|
44
|
+
bezel: "inset-x-0 top-0 bottom-[4%] rounded-t-[1.25rem] border-[10px] border-b-[22px] border-shell shadow-2xl",
|
|
45
|
+
screen: "left-[10px] right-[10px] top-[10px] bottom-[calc(4%+22px)] rounded-[0.25rem]",
|
|
46
|
+
extras: jsx("span", {
|
|
47
|
+
"aria-hidden": "true",
|
|
48
|
+
className: cn("absolute -inset-x-[6%] bottom-0 h-[4%] rounded-b-[1rem] bg-line shadow-lg", CHROME)
|
|
49
|
+
})
|
|
50
|
+
},
|
|
51
|
+
browser: {
|
|
52
|
+
root: "w-[340px] md:w-[720px] aspect-[16/10.5]",
|
|
53
|
+
bezel: "inset-0 rounded-card border border-t-[36px] border-line border-t-gray-100 shadow-2xl dark:border-t-gray-800",
|
|
54
|
+
screen: "inset-x-px bottom-px top-[36px] rounded-b-card",
|
|
55
|
+
extras: null
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* A CSS-only device mock-up (phone, tablet, laptop or browser window) around any
|
|
60
|
+
* screen content. Purely presentational: no motion, works anywhere.
|
|
61
|
+
*/
|
|
62
|
+
var DeviceFrame = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
63
|
+
var _ref$device = _ref.device,
|
|
64
|
+
device = _ref$device === void 0 ? "phone" : _ref$device,
|
|
65
|
+
url = _ref.url,
|
|
66
|
+
screenClassName = _ref.screenClassName,
|
|
67
|
+
screenRef = _ref.screenRef,
|
|
68
|
+
className = _ref.className,
|
|
69
|
+
children = _ref.children,
|
|
70
|
+
rest = _objectWithoutProperties(_ref, _excluded);
|
|
71
|
+
var f = FRAMES[device] || FRAMES.phone;
|
|
72
|
+
return jsxs("div", _objectSpread2(_objectSpread2({
|
|
73
|
+
ref: ref,
|
|
74
|
+
"data-device": device,
|
|
75
|
+
className: cn("relative shrink-0", f.root, className)
|
|
76
|
+
}, rest), {}, {
|
|
77
|
+
children: [jsx("div", {
|
|
78
|
+
"aria-hidden": "true",
|
|
79
|
+
className: cn("pointer-events-none absolute", f.bezel, CHROME)
|
|
80
|
+
}), device === "browser" ? jsxs("div", {
|
|
81
|
+
"aria-hidden": "true",
|
|
82
|
+
className: cn("absolute inset-x-0 top-0 flex h-[36px] items-center gap-1.5 px-3", CHROME),
|
|
83
|
+
children: [jsx("span", {
|
|
84
|
+
className: "h-2.5 w-2.5 rounded-full bg-error-400"
|
|
85
|
+
}), jsx("span", {
|
|
86
|
+
className: "h-2.5 w-2.5 rounded-full bg-warning-400"
|
|
87
|
+
}), jsx("span", {
|
|
88
|
+
className: "h-2.5 w-2.5 rounded-full bg-success-400"
|
|
89
|
+
}), url ? jsx("span", {
|
|
90
|
+
className: "ml-3 flex-1 truncate rounded-pill bg-surface px-3 py-0.5 text-micro text-muted dark:bg-background",
|
|
91
|
+
children: url
|
|
92
|
+
}) : null]
|
|
93
|
+
}) : null, jsx("div", {
|
|
94
|
+
ref: screenRef,
|
|
95
|
+
className: cn("absolute overflow-hidden bg-surface dark:bg-background", f.screen, screenClassName),
|
|
96
|
+
children: children
|
|
97
|
+
}), f.extras]
|
|
98
|
+
}));
|
|
99
|
+
});
|
|
100
|
+
DeviceFrame.displayName = "DeviceFrame";
|
|
101
|
+
|
|
102
|
+
export { DeviceFrame as default };
|