@dreamtree-org/twreact-ui 2.1.2 → 2.2.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/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
package/README.md
CHANGED
|
@@ -124,23 +124,27 @@ Server Component to these Client Components. You also cannot dot into a client e
|
|
|
124
124
|
In Vite, Rollup can log `Module level directives cause errors when bundled, "use client" … was ignored`.
|
|
125
125
|
This message is harmless. To hide it, filter `MODULE_LEVEL_DIRECTIVE` in `build.rollupOptions.onwarn`.
|
|
126
126
|
|
|
127
|
-
### Optional entry points: charts
|
|
127
|
+
### Optional entry points: charts, rich text and motion
|
|
128
128
|
|
|
129
129
|
Charts and the rich-text editor wrap third-party libraries, so they live on their own entry points
|
|
130
|
-
and use **optional peer dependencies**.
|
|
131
|
-
|
|
130
|
+
and use **optional peer dependencies**. The motion (scroll-storytelling) components need no
|
|
131
|
+
dependency at all but are kept off the root so app bundles never carry them. If you never import
|
|
132
|
+
these entry points you install nothing extra, and nothing changes in your bundle — the root
|
|
133
|
+
`@dreamtree-org/twreact-ui` import never touches them.
|
|
132
134
|
|
|
133
135
|
| Entry point | Exports | Install first |
|
|
134
136
|
|---|---|---|
|
|
135
137
|
| `@dreamtree-org/twreact-ui/charts` | `LineChart`, `BarChart`, `AreaChart`, `DonutChart`, `Sparkline`, `ScatterChart` | `npm install recharts` (recharts 2.15+ or 3.x; React 18 apps also `npm install react-is@18`) |
|
|
136
138
|
| `@dreamtree-org/twreact-ui/rich-text` | `RichTextEditor` | `npm install @tiptap/react @tiptap/pm @tiptap/starter-kit` (Tiptap 3) |
|
|
139
|
+
| `@dreamtree-org/twreact-ui/motion` | `ScrollStage`, `Reveal`, `RevealGroup`, `LogoMarquee`, `CountUp`, `StatStrip`, `StackedCards`, `DeviceFrame`, `DeviceMorphHero`, `BentoExpandGrid`, `TestimonialSpotlight`, `PhotoCollage`, `RotatingBadge`, `SmoothScrollProvider`, `useScrollProgress`, `useSmoothScroll` | Nothing. Optional: `npm install lenis` for `SmoothScrollProvider` |
|
|
137
140
|
|
|
138
141
|
```jsx
|
|
139
142
|
import { LineChart, DonutChart } from '@dreamtree-org/twreact-ui/charts';
|
|
140
143
|
import { RichTextEditor } from '@dreamtree-org/twreact-ui/rich-text';
|
|
144
|
+
import { StackedCards, LogoMarquee } from '@dreamtree-org/twreact-ui/motion';
|
|
141
145
|
```
|
|
142
146
|
|
|
143
|
-
|
|
147
|
+
All three ship ESM (with `'use client'`), CommonJS and TypeScript declarations, and resolve under every
|
|
144
148
|
TypeScript `moduleResolution` (`bundler`, `node16`/`nodenext` and legacy `node`). Their styles are
|
|
145
149
|
already in `dist/index.css`. Rich-text output is HTML from the user — **sanitize it on the server**
|
|
146
150
|
before you store or render it (see [doc/RichTextEditor.md](doc/RichTextEditor.md#security-sanitize-the-html-on-the-server)).
|
|
@@ -858,6 +862,45 @@ import { RichTextEditor } from '@dreamtree-org/twreact-ui/rich-text';
|
|
|
858
862
|
> The HTML comes from the user. Sanitize it on the server (e.g. DOMPurify / `sanitize-html`) before
|
|
859
863
|
> storing or rendering it; this library ships no sanitizer.
|
|
860
864
|
|
|
865
|
+
### Motion: scroll storytelling (optional entry point)
|
|
866
|
+
|
|
867
|
+
Import from `@dreamtree-org/twreact-ui/motion` — landing-page sections that tell a story as the
|
|
868
|
+
page scrolls (overview: [`doc/Motion.md`](doc/Motion.md)). One shared `requestAnimationFrame` +
|
|
869
|
+
`IntersectionObserver` engine drives them by writing CSS variables (`--dt-p`, 0–1), so React does
|
|
870
|
+
not re-render per frame and only on-screen sections do any work. No animation library is bundled;
|
|
871
|
+
the entry is gated at **12 KB gzipped** (`npm run motion:size`).
|
|
872
|
+
|
|
873
|
+
| Component | Use for |
|
|
874
|
+
|---|---|
|
|
875
|
+
| [`ScrollStage`](doc/ScrollStage.md) | A pinned scene: content sticks while the page scrolls `length` vh (default 300, 150 below `md`); progress in `--dt-p`, `children(progress)` and `onProgress` |
|
|
876
|
+
| [`useScrollProgress`](doc/useScrollProgress.md) | The hook under it: `useScrollProgress(ref, { mode: 'view' \| 'pin', start, end, onChange })` → `{ get, subscribe }` |
|
|
877
|
+
| [`Reveal`](doc/Reveal.md) / [`RevealGroup`](doc/RevealGroup.md) | Entrances on scroll (`fade-up`, `fade`, `scale`, `clip`, `split-words`), with `delay` / `stagger` |
|
|
878
|
+
| [`LogoMarquee`](doc/LogoMarquee.md) | Endless client strip (`speed` px/s, `rows`, `fadeEdges`); the loop copy is `aria-hidden` |
|
|
879
|
+
| [`CountUp`](doc/CountUp.md) / [`StatStrip`](doc/StatStrip.md) | Numbers that count up on view (`en-IN` grouping by default); the server renders the real value |
|
|
880
|
+
| [`StackedCards`](doc/StackedCards.md) | Sticky cards that stack, shrink and dim, with an alternating tilt |
|
|
881
|
+
| [`DeviceFrame`](doc/DeviceFrame.md) | CSS-only phone / tablet / laptop / browser mock-up |
|
|
882
|
+
| [`DeviceMorphHero`](doc/DeviceMorphHero.md) | Full-bleed media that shrinks into a device, which slides aside as the copy fades in |
|
|
883
|
+
| [`BentoExpandGrid`](doc/BentoExpandGrid.md) | Photo grid whose hovered or focused tile grows; a snap scroller on phones |
|
|
884
|
+
| [`TestimonialSpotlight`](doc/TestimonialSpotlight.md) | Quotes beside a logo tile grid; tab-list dots, pausable autoplay |
|
|
885
|
+
| [`PhotoCollage`](doc/PhotoCollage.md) / [`RotatingBadge`](doc/RotatingBadge.md) | Overlapping photos with parallax and stat chips; a turning circular text badge |
|
|
886
|
+
| [`SmoothScrollProvider`](doc/SmoothScrollProvider.md) / [`useSmoothScroll`](doc/useSmoothScroll.md) | Opt-in Lenis smooth scroll (`npm install lenis`, pass `lenis={Lenis}`); `scrollTo` works either way |
|
|
887
|
+
|
|
888
|
+
```jsx
|
|
889
|
+
import { DeviceMorphHero, LogoMarquee, StatStrip, StackedCards } from '@dreamtree-org/twreact-ui/motion';
|
|
890
|
+
|
|
891
|
+
<DeviceMorphHero media={{ video: '/intro.mp4', poster: '/intro.jpg', alt: 'Product tour' }} device="phone" content={<HeroCopy />} />
|
|
892
|
+
<LogoMarquee items={['Schoo360', 'TradeOS', { src: '/acme.svg', alt: 'Acme' }]} speed={40} />
|
|
893
|
+
<StatStrip items={[{ value: 500, suffix: '+', label: 'Projects' }, { value: 14, label: 'Years' }]} />
|
|
894
|
+
<StackedCards items={pillars} stickyTop={80} tilt={1} scaleBack={0.95} />
|
|
895
|
+
```
|
|
896
|
+
|
|
897
|
+
**Server rendering and reduced motion.** The server renders every component in its final state —
|
|
898
|
+
real numbers, visible text, the device beside the copy — and motion only starts after hydration.
|
|
899
|
+
With `prefers-reduced-motion: reduce`, pins become normal flow, counters show the final number,
|
|
900
|
+
marquees become a static wrapped row, and tilt and parallax drop to 0. Content already on screen at
|
|
901
|
+
load is never hidden by `Reveal`. Scroll defaults come from the new `scroll` tokens
|
|
902
|
+
(`scroll.stickyTop` 80px, `scroll.sceneLength` 300vh, `scroll.sceneLengthMobile` 150vh).
|
|
903
|
+
|
|
861
904
|
### Page blocks
|
|
862
905
|
|
|
863
906
|
Page-level patterns extracted from the Dreamtree products. Build pages from these before composing layouts by hand.
|
|
@@ -36,6 +36,8 @@ is not yet supported.
|
|
|
36
36
|
npm install recharts # React 18 apps also: npm install react-is@18
|
|
37
37
|
# rich text: @dreamtree-org/twreact-ui/rich-text
|
|
38
38
|
npm install @tiptap/react @tiptap/pm @tiptap/starter-kit
|
|
39
|
+
# motion (scroll storytelling): @dreamtree-org/twreact-ui/motion — needs nothing;
|
|
40
|
+
npm install lenis # only for SmoothScrollProvider (optional)
|
|
39
41
|
```
|
|
40
42
|
|
|
41
43
|
Apps that don't import these subpaths install and bundle nothing extra.
|
|
@@ -135,6 +137,7 @@ The library exports four kinds of things from `@dreamtree-org/twreact-ui`:
|
|
|
135
137
|
| **Blocks** | `AppShell`, `PageHeader`, `StatCard`, `StatusPill`, `EmptyState`, `ErrorState`, `LoadingState`, `ConfirmDialog`, `BottomActionBar` (+ `BottomActionBar.Spacer`), `ProductCard` (storefront product tile) — page-level patterns; build pages from these before composing layouts by hand |
|
|
136
138
|
| **Charts** (`@dreamtree-org/twreact-ui/charts`, peer `recharts`) | `LineChart`, `BarChart`, `AreaChart`, `DonutChart`, `Sparkline`, `ScatterChart` — NOT exported from the root |
|
|
137
139
|
| **Rich text** (`@dreamtree-org/twreact-ui/rich-text`, peers `@tiptap/react @tiptap/pm @tiptap/starter-kit`) | `RichTextEditor` — NOT exported from the root |
|
|
140
|
+
| **Motion** (`@dreamtree-org/twreact-ui/motion`, optional peer `lenis`) | `ScrollStage`, `Reveal`, `RevealGroup`, `LogoMarquee`, `CountUp`, `StatStrip`, `StackedCards`, `DeviceFrame`, `DeviceMorphHero`, `BentoExpandGrid`, `TestimonialSpotlight`, `PhotoCollage`, `RotatingBadge`, `SmoothScrollProvider`, hooks `useScrollProgress`, `useSmoothScroll` — scroll-storytelling sections for landing pages; NOT exported from the root |
|
|
138
141
|
|
|
139
142
|
### Hooks
|
|
140
143
|
|
|
@@ -241,6 +244,7 @@ When suggesting a component or new variant value, use this exact vocabulary.
|
|
|
241
244
|
- Haptics are opt-in: `haptics` on `Switch` / `Checkbox` (selection tick), `Sheet` (tick on a new snap point) and `ConfirmDialog` (warning on destructive open, success on confirm). Default `false`; never the only signal. For custom cues use `useHaptics().trigger('success')`.
|
|
242
245
|
- Charts (`/charts`) — `<LineChart data={rows} index="month" categories={['revenue', 'costs']} />`; same shape for `BarChart` (`stacked`, `horizontal`) and `AreaChart` (`stacked`); `DonutChart` takes `index` (name key) + `category` (value key) + `centerLabel`; `Sparkline` takes `category` + `color`; `ScatterChart` takes `x` + `y` (numeric keys) plus optional `index` (entity name) and `category` (series), e.g. `<ScatterChart data={projects} x="health" y="variance" index="project" category="department" />`. Colours are tokens (`colors={['primary', 'success-600']}`), never hex. Always pass `title` (accessible name) and, for key charts, a `description` with the takeaway. `valueFormatter` formats tooltip/axis/table values.
|
|
243
246
|
- `RichTextEditor` (`/rich-text`) — `label`/`error`/`helperText` like `Input`; `value` + `onChange(html)` (or `outputFormat="json"`); `toolbar={['bold', 'italic', 'link']}` to trim. Tell the user to **sanitize the HTML server-side**; never render it with `dangerouslySetInnerHTML` unsanitized.
|
|
247
|
+
- Motion (`/motion`) — landing-page storytelling. `ScrollStage length={300}` pins its child while the page scrolls (CSS reads `var(--dt-p, 1)`, always with the `1` fallback = final state); `useScrollProgress(ref, { mode: 'view' | 'pin' })` for custom scenes. `Reveal effect="fade-up|fade|scale|clip|split-words"` / `RevealGroup stagger={80}` for entrances. `LogoMarquee items={['Acme', { src, alt }]} speed={40}`; `StatStrip items={[{ value: 500, suffix: '+', label: 'Projects' }]}` (or one `CountUp value`); `StackedCards items={[{ kicker, title, body, bullets, metric: { value, label }, cta, media: { src, alt } }]} tilt={1}`; `DeviceMorphHero media={{ video, poster, alt }} device="phone" content={<Copy />}`; `DeviceFrame device="browser" url="…"` for a static mock-up; `BentoExpandGrid items={[{ media: { src, alt }, title, tag, client, href }]}`; `TestimonialSpotlight items={[{ quote, name, role, logo }]}`; `PhotoCollage images chips badge={<RotatingBadge text="BRAND • SINCE 2012 • " />}`. Smooth scroll is opt-in: `import Lenis from 'lenis'` and wrap the page in `<SmoothScrollProvider lenis={Lenis}>`; `useSmoothScroll().scrollTo('#id')` works with or without it. Everything renders its final state on the server and under reduced motion — don't add your own `prefers-reduced-motion` handling, and never fake counters with "0" in the markup.
|
|
244
248
|
- `Tour` — onboarding coach marks: `steps=[{ target: '[data-tour="x"]', title, content, placement }]`, `open`, `onClose(reason)`; a missing target falls back to a centred card.
|
|
245
249
|
|
|
246
250
|
**Tokens:** colours are CSS variables (`--dt-primary-600`, `--dt-surface`, …) generated from
|
|
@@ -424,6 +428,18 @@ import { RichTextEditor } from '@dreamtree-org/twreact-ui/rich-text';
|
|
|
424
428
|
<RichTextEditor label="Description" placeholder="Describe the task…" value={html} onChange={setHtml} maxHeight={320} />
|
|
425
429
|
```
|
|
426
430
|
|
|
431
|
+
### Motion (optional entry point)
|
|
432
|
+
|
|
433
|
+
```jsx
|
|
434
|
+
import { DeviceMorphHero, LogoMarquee, StatStrip, StackedCards, Reveal } from '@dreamtree-org/twreact-ui/motion';
|
|
435
|
+
|
|
436
|
+
<DeviceMorphHero media={{ video: '/intro.mp4', poster: '/intro.jpg', alt: 'Product tour' }} device="phone" content={<HeroCopy />} />
|
|
437
|
+
<LogoMarquee items={clients} speed={40} />
|
|
438
|
+
<StatStrip items={[{ value: 500, suffix: '+', label: 'Projects' }, { value: 14, label: 'Years' }]} />
|
|
439
|
+
<Reveal as="h2" effect="split-words" className="text-page-title">What we do</Reveal>
|
|
440
|
+
<StackedCards items={pillars} stickyTop={80} tilt={1} />
|
|
441
|
+
```
|
|
442
|
+
|
|
427
443
|
### cn
|
|
428
444
|
|
|
429
445
|
```jsx
|
|
@@ -457,10 +473,11 @@ import { cn } from '@dreamtree-org/twreact-ui';
|
|
|
457
473
|
`tailwind.config.js` `content[]` includes
|
|
458
474
|
`./node_modules/@dreamtree-org/twreact-ui/dist/**/*.{js,mjs}`.
|
|
459
475
|
6. **Don't deep-import.** The public modules are `@dreamtree-org/twreact-ui`
|
|
460
|
-
plus the
|
|
461
|
-
`@dreamtree-org/twreact-ui/rich-text` (each needs its peer installed)
|
|
476
|
+
plus the optional entry points `@dreamtree-org/twreact-ui/charts`,
|
|
477
|
+
`@dreamtree-org/twreact-ui/rich-text` (each needs its peer installed) and
|
|
478
|
+
`@dreamtree-org/twreact-ui/motion` (no peer; `lenis` only for smooth scroll).
|
|
462
479
|
Don't suggest `@dreamtree-org/twreact-ui/src/components/core/Button`, and
|
|
463
|
-
never import charts
|
|
480
|
+
never import charts, `RichTextEditor` or the motion components from the root.
|
|
464
481
|
7. **React 18 only.** If the user is on React 19, warn them: this
|
|
465
482
|
library has not yet been verified on React 19.
|
|
466
483
|
8. **Accessibility-first.** Icon-only buttons need `aria-label`.
|
|
@@ -36,7 +36,10 @@ function _iterableToArrayLimit(r, l) {
|
|
|
36
36
|
f = true,
|
|
37
37
|
o = false;
|
|
38
38
|
try {
|
|
39
|
-
if (i = (t = t.call(r)).next, 0 === l)
|
|
39
|
+
if (i = (t = t.call(r)).next, 0 === l) {
|
|
40
|
+
if (Object(t) !== t) return;
|
|
41
|
+
f = !1;
|
|
42
|
+
} else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
|
|
40
43
|
} catch (r) {
|
|
41
44
|
o = true, n = r;
|
|
42
45
|
} finally {
|
|
@@ -116,6 +119,15 @@ function _toPropertyKey(t) {
|
|
|
116
119
|
var i = _toPrimitive(t, "string");
|
|
117
120
|
return "symbol" == typeof i ? i : i + "";
|
|
118
121
|
}
|
|
122
|
+
function _typeof(o) {
|
|
123
|
+
"@babel/helpers - typeof";
|
|
124
|
+
|
|
125
|
+
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
|
|
126
|
+
return typeof o;
|
|
127
|
+
} : function (o) {
|
|
128
|
+
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
|
|
129
|
+
}, _typeof(o);
|
|
130
|
+
}
|
|
119
131
|
function _unsupportedIterableToArray(r, a) {
|
|
120
132
|
if (r) {
|
|
121
133
|
if ("string" == typeof r) return _arrayLikeToArray(r, a);
|
|
@@ -135,4 +147,5 @@ exports._objectSpread2 = _objectSpread2;
|
|
|
135
147
|
exports._objectWithoutProperties = _objectWithoutProperties;
|
|
136
148
|
exports._slicedToArray = _slicedToArray;
|
|
137
149
|
exports._toConsumableArray = _toConsumableArray;
|
|
150
|
+
exports._typeof = _typeof;
|
|
138
151
|
exports.cn = cn;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
|
|
5
|
+
// useLayoutEffect warns during SSR; fall back to useEffect on the server.
|
|
6
|
+
var useIsomorphicLayoutEffect = typeof window !== "undefined" ? React.useLayoutEffect : React.useEffect;
|
|
7
|
+
/**
|
|
8
|
+
* Internal (not exported from the package): a ref that always holds the latest
|
|
9
|
+
* `value`. Lets an effect call the newest consumer callback (e.g. `onChange`)
|
|
10
|
+
* without listing it as a dependency, so a parent passing an inline function
|
|
11
|
+
* does not re-run the effect on every render.
|
|
12
|
+
*/
|
|
13
|
+
function useLatestRef(value) {
|
|
14
|
+
var ref = React.useRef(value);
|
|
15
|
+
useIsomorphicLayoutEffect(function () {
|
|
16
|
+
ref.current = value;
|
|
17
|
+
});
|
|
18
|
+
return ref;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
exports.useLatestRef = useLatestRef;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
|
|
5
|
+
// Internal (not exported). SSR-safe media-query subscription.
|
|
6
|
+
function getMediaQueryList(query) {
|
|
7
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return null;
|
|
8
|
+
return window.matchMedia(query) || null;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Subscribes `onChange` to a MediaQueryList's change events. Uses
|
|
12
|
+
* `addEventListener` where available and falls back to the deprecated
|
|
13
|
+
* `addListener` (Safari < 14). Returns the unsubscribe function.
|
|
14
|
+
*/
|
|
15
|
+
function subscribeMediaQuery(query, onChange) {
|
|
16
|
+
var mql = getMediaQueryList(query);
|
|
17
|
+
if (!mql) return function () {};
|
|
18
|
+
if (typeof mql.addEventListener === "function") {
|
|
19
|
+
mql.addEventListener("change", onChange);
|
|
20
|
+
return function () {
|
|
21
|
+
var _mql$removeEventListe;
|
|
22
|
+
return (_mql$removeEventListe = mql.removeEventListener) === null || _mql$removeEventListe === void 0 ? void 0 : _mql$removeEventListe.call(mql, "change", onChange);
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
if (typeof mql.addListener === "function") {
|
|
26
|
+
mql.addListener(onChange);
|
|
27
|
+
return function () {
|
|
28
|
+
var _mql$removeListener;
|
|
29
|
+
return (_mql$removeListener = mql.removeListener) === null || _mql$removeListener === void 0 ? void 0 : _mql$removeListener.call(mql, onChange);
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return function () {};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* `true` while `query` matches; follows changes live.
|
|
36
|
+
*
|
|
37
|
+
* On the server (and while hydrating) it returns `defaultValue`, so server and
|
|
38
|
+
* client markup agree; the real value is applied right after hydration. Without
|
|
39
|
+
* `window.matchMedia` it always returns `defaultValue`.
|
|
40
|
+
*
|
|
41
|
+
* @param {string} query - a CSS media query, e.g. "(max-width: 639px)".
|
|
42
|
+
* @param {{ defaultValue?: boolean }} [options]
|
|
43
|
+
* @returns {boolean}
|
|
44
|
+
*/
|
|
45
|
+
function useMediaQuery(query) {
|
|
46
|
+
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
|
|
47
|
+
_ref$defaultValue = _ref.defaultValue,
|
|
48
|
+
defaultValue = _ref$defaultValue === void 0 ? false : _ref$defaultValue;
|
|
49
|
+
var subscribe = React.useCallback(function (onChange) {
|
|
50
|
+
return subscribeMediaQuery(query, onChange);
|
|
51
|
+
}, [query]);
|
|
52
|
+
var getSnapshot = function getSnapshot() {
|
|
53
|
+
var mql = getMediaQueryList(query);
|
|
54
|
+
return mql ? Boolean(mql.matches) : defaultValue;
|
|
55
|
+
};
|
|
56
|
+
var getServerSnapshot = function getServerSnapshot() {
|
|
57
|
+
return defaultValue;
|
|
58
|
+
};
|
|
59
|
+
return React.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Internal (not exported). Shared by the charts and the overlay primitives.
|
|
63
|
+
var REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
|
|
64
|
+
/**
|
|
65
|
+
* `true` while the user asks the OS for reduced motion; follows changes live.
|
|
66
|
+
* `false` on the server and while hydrating, so the first render matches.
|
|
67
|
+
*
|
|
68
|
+
* @returns {boolean}
|
|
69
|
+
*/
|
|
70
|
+
function useReducedMotion() {
|
|
71
|
+
return useMediaQuery(REDUCED_MOTION_QUERY, {
|
|
72
|
+
defaultValue: false
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
exports.useMediaQuery = useMediaQuery;
|
|
77
|
+
exports.useReducedMotion = useReducedMotion;
|