@rendra-ui/web 2.4.0 → 2.5.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 +24 -1
- package/dist/base.css +33 -1
- package/dist/{button-C6rjowQi.js → button-BzJgR2gH.js} +86 -21
- package/dist/button-BzJgR2gH.js.map +1 -0
- package/dist/chart.js +61 -15
- package/dist/chart.js.map +1 -1
- package/dist/cli/auditar.js +1 -1
- package/dist/cli/codigos.js +2 -2
- package/dist/cli/executar-auditar.js +1 -1
- package/dist/cli/help.js +1 -1
- package/dist/cli/trocar.js +2 -2
- package/dist/cli/typescript-loader.js +1 -1
- package/dist/{cn-DXDpTGsu.js → cn-Cw7M5kEP.js} +2 -2
- package/dist/{cn-DXDpTGsu.js.map → cn-Cw7M5kEP.js.map} +1 -1
- package/dist/{components-hp7iWioq.js → components-DkpspH9h.js} +2 -2
- package/dist/{components-hp7iWioq.js.map → components-DkpspH9h.js.map} +1 -1
- package/dist/components.css +169 -33
- package/dist/document-viewer.js +6 -6
- package/dist/document-viewer.js.map +1 -1
- package/dist/{empty-state-CdaDLcsB.js → empty-state-Cdb1vkMT.js} +36 -12
- package/dist/{empty-state-CdaDLcsB.js.map → empty-state-Cdb1vkMT.js.map} +1 -1
- package/dist/features-max--5VEt6M7.js +3 -0
- package/dist/index.js +1062 -339
- package/dist/index.js.map +1 -1
- package/dist/motion-context-5BRIQAJm.js +107 -0
- package/dist/motion-context-5BRIQAJm.js.map +1 -0
- package/dist/{rendra-provider-7jUgUHzR.js → rendra-provider-CRe0XdOU.js} +9 -5
- package/dist/rendra-provider-CRe0XdOU.js.map +1 -0
- package/dist/rich-text-editor.js +4 -4
- package/dist/router-bridge.js +5 -4
- package/dist/router-bridge.js.map +1 -1
- package/dist/tokens.css +63 -15
- package/dist/tooltip-BAMSaGbS.js +224 -0
- package/dist/tooltip-BAMSaGbS.js.map +1 -0
- package/dist/types/components/rendra-provider.d.ts +7 -1
- package/dist/types/components/rendra-router-bridge.d.ts +3 -1
- package/dist/types/components/ui/accordion.d.ts +1 -1
- package/dist/types/components/ui/badge.d.ts +1 -1
- package/dist/types/components/ui/button.d.ts +1 -1
- package/dist/types/components/ui/dropdown-menu.d.ts +5 -5
- package/dist/types/components/ui/picker-panel.d.ts +1 -1
- package/dist/types/components/ui/popover.d.ts +3 -3
- package/dist/types/components/ui/radio-group.d.ts +1 -1
- package/dist/types/components/ui/skeleton.d.ts +5 -1
- package/dist/types/components/ui/stat-card.d.ts +1 -1
- package/dist/types/components/ui/table.d.ts +0 -6
- package/dist/types/components/ui/tooltip.d.ts +1 -1
- package/dist/types/hooks/use-reduced-motion.d.ts +3 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/lib/motion/count.d.ts +17 -0
- package/dist/types/lib/motion/features-max.d.ts +1 -0
- package/dist/types/lib/motion/index.d.ts +5 -0
- package/dist/types/lib/motion/motion-context.d.ts +43 -0
- package/dist/types/lib/motion/native-events.d.ts +16 -0
- package/dist/types/lib/motion/presets.d.ts +92 -0
- package/dist/types/lib/motion/reorder.d.ts +7 -0
- package/dist/types/lib/motion/tokens.d.ts +66 -0
- package/dist/types/lib/motion/use-motion-presets.d.ts +8 -0
- package/dist/{use-breakpoint-Dyp-0E_c.js → use-breakpoint-O9eqFmsF.js} +2 -2
- package/dist/{use-breakpoint-Dyp-0E_c.js.map → use-breakpoint-O9eqFmsF.js.map} +1 -1
- package/dist/use-motion-presets-BrkgL8lG.js +401 -0
- package/dist/use-motion-presets-BrkgL8lG.js.map +1 -0
- package/dist/widget-grid.js +3 -3
- package/package.json +3 -1
- package/dist/button-C6rjowQi.js.map +0 -1
- package/dist/rendra-provider-7jUgUHzR.js.map +0 -1
- package/dist/tooltip-bdmbX6vC.js +0 -105
- package/dist/tooltip-bdmbX6vC.js.map +0 -1
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/*! Rendra Design System v2.5.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
|
|
2
|
+
import { LazyMotion, MotionConfig, domAnimation } from "motion/react";
|
|
3
|
+
import { createContext, useContext, useMemo, useState, useSyncExternalStore } from "react";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
//#region src/hooks/use-reduced-motion.ts
|
|
6
|
+
/** Fonte única da preferência (também usada pelo motion, que só a assina em `on`). */
|
|
7
|
+
function subscribeReducedMotion(cb) {
|
|
8
|
+
const mq = matchMedia("(prefers-reduced-motion: reduce)");
|
|
9
|
+
mq.addEventListener("change", cb);
|
|
10
|
+
return () => mq.removeEventListener("change", cb);
|
|
11
|
+
}
|
|
12
|
+
function getReducedMotion() {
|
|
13
|
+
return matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
14
|
+
}
|
|
15
|
+
function usePrefersReducedMotion() {
|
|
16
|
+
return useSyncExternalStore(subscribeReducedMotion, getReducedMotion, () => false);
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
//#region src/lib/motion/motion-context.tsx
|
|
20
|
+
var MotionContext = createContext({
|
|
21
|
+
mode: "off",
|
|
22
|
+
layoutReady: false
|
|
23
|
+
});
|
|
24
|
+
/** Modo de motion do provider mais próximo (`off` sem provider). */
|
|
25
|
+
function useMotionMode() {
|
|
26
|
+
return useContext(MotionContext).mode;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Em `on`, o chunk do `domMax` já chegou. Um `m.*` com `layout` ou `layoutId` só ganha o nó de
|
|
30
|
+
* projeção se for criado DEPOIS disso (o Motion não monta a projeção de um elemento que já
|
|
31
|
+
* estava na tela), então quem usa layout liga a prop e remonta o item quando isto vira `true`.
|
|
32
|
+
*/
|
|
33
|
+
function useLayoutReady() {
|
|
34
|
+
const { mode, layoutReady } = useContext(MotionContext);
|
|
35
|
+
return mode === "on" && layoutReady;
|
|
36
|
+
}
|
|
37
|
+
var RevealContext = createContext(false);
|
|
38
|
+
/** O componente está dentro de um `RevealScope`? */
|
|
39
|
+
function useRevealScope() {
|
|
40
|
+
return useContext(RevealContext);
|
|
41
|
+
}
|
|
42
|
+
/** Só troca o modo lido pelos componentes; não monta nem desmonta o LazyMotion. */
|
|
43
|
+
function MotionModeScope({ mode, children }) {
|
|
44
|
+
const { layoutReady } = useContext(MotionContext);
|
|
45
|
+
const value = useMemo(() => ({
|
|
46
|
+
mode,
|
|
47
|
+
layoutReady
|
|
48
|
+
}), [mode, layoutReady]);
|
|
49
|
+
return /* @__PURE__ */ jsx(MotionContext.Provider, {
|
|
50
|
+
value,
|
|
51
|
+
children
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/** O carregador do `domMax` (chunk à parte): layout, layoutId e arraste do Motion. */
|
|
55
|
+
var loadMax = () => import("./features-max--5VEt6M7.js").then((m) => m.default);
|
|
56
|
+
/**
|
|
57
|
+
* Em `off`, só o contexto (nenhum nó novo, nenhum LazyMotion). Em `on`, dois `LazyMotion` (os
|
|
58
|
+
* dois `strict`: só `m.*` entra, um `motion.*` esquecido quebra em vez de puxar o pacote inteiro):
|
|
59
|
+
* o de fora carrega o `domMax` sob demanda (layout e arraste), em chunk separado; o de dentro traz
|
|
60
|
+
* o `domAnimation` síncrono (animação e gestos) e é o que os `m.*` enxergam. Nessa ordem o
|
|
61
|
+
* renderer síncrono já está no contexto na primeira renderização (elementos e gestos funcionam
|
|
62
|
+
* na hora), e os recursos de layout se juntam quando o chunk chega. A ordem contrária esconderia
|
|
63
|
+
* o renderer até o chunk terminar de baixar.
|
|
64
|
+
*
|
|
65
|
+
* O `MotionConfig` recebe "reduzir movimento" da mesma fonte dos presets (o `matchMedia` de
|
|
66
|
+
* `use-reduced-motion.ts`, reativo): com `always`, o Motion também tira o deslocamento e o layout
|
|
67
|
+
* de qualquer animação que um componente escreva à mão, e mantém a opacidade. Não é uma segunda
|
|
68
|
+
* fonte: é a primeira, lida uma vez, entregue a dois consumidores.
|
|
69
|
+
*/
|
|
70
|
+
function MotionProvider({ mode, children }) {
|
|
71
|
+
if (mode !== "on") return /* @__PURE__ */ jsx(MotionModeScope, {
|
|
72
|
+
mode: "off",
|
|
73
|
+
children
|
|
74
|
+
});
|
|
75
|
+
return /* @__PURE__ */ jsx(OnProvider, { children });
|
|
76
|
+
}
|
|
77
|
+
function OnProvider({ children }) {
|
|
78
|
+
const [layoutReady, setLayoutReady] = useState(false);
|
|
79
|
+
const reduced = usePrefersReducedMotion();
|
|
80
|
+
const value = useMemo(() => ({
|
|
81
|
+
mode: "on",
|
|
82
|
+
layoutReady
|
|
83
|
+
}), [layoutReady]);
|
|
84
|
+
const load = useMemo(() => () => loadMax().then((features) => {
|
|
85
|
+
setTimeout(() => setLayoutReady(true), 0);
|
|
86
|
+
return features;
|
|
87
|
+
}), []);
|
|
88
|
+
return /* @__PURE__ */ jsx(LazyMotion, {
|
|
89
|
+
features: load,
|
|
90
|
+
strict: true,
|
|
91
|
+
children: /* @__PURE__ */ jsx(LazyMotion, {
|
|
92
|
+
features: domAnimation,
|
|
93
|
+
strict: true,
|
|
94
|
+
children: /* @__PURE__ */ jsx(MotionConfig, {
|
|
95
|
+
reducedMotion: reduced ? "always" : "never",
|
|
96
|
+
children: /* @__PURE__ */ jsx(MotionContext.Provider, {
|
|
97
|
+
value,
|
|
98
|
+
children
|
|
99
|
+
})
|
|
100
|
+
})
|
|
101
|
+
})
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
//#endregion
|
|
105
|
+
export { getReducedMotion as a, useRevealScope as i, useLayoutReady as n, subscribeReducedMotion as o, useMotionMode as r, usePrefersReducedMotion as s, MotionProvider as t };
|
|
106
|
+
|
|
107
|
+
//# sourceMappingURL=motion-context-5BRIQAJm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"motion-context-5BRIQAJm.js","names":[],"sources":["../src/hooks/use-reduced-motion.ts","../src/lib/motion/motion-context.tsx"],"sourcesContent":["import { useSyncExternalStore } from 'react'\n\n/*\n * Único hook de leitura de \"menos movimento\" do sistema operacional (prefers-reduced-motion).\n * Usado pelo Spinner e pelo Progress indeterminado para parar a animação sem depender só do\n * CSS, e assim ficar testável (mocke matchMedia para simular a preferência).\n */\n\n/** Fonte única da preferência (também usada pelo motion, que só a assina em `on`). */\nexport function subscribeReducedMotion(cb: () => void) {\n const mq = matchMedia('(prefers-reduced-motion: reduce)')\n mq.addEventListener('change', cb)\n return () => mq.removeEventListener('change', cb)\n}\n\nexport function getReducedMotion() {\n return matchMedia('(prefers-reduced-motion: reduce)').matches\n}\n\nexport function usePrefersReducedMotion() {\n return useSyncExternalStore(subscribeReducedMotion, getReducedMotion, () => false)\n}\n","import { domAnimation, LazyMotion, MotionConfig } from 'motion/react'\nimport { createContext, useContext, useMemo, useState, type ReactNode } from 'react'\nimport { usePrefersReducedMotion } from '@/hooks/use-reduced-motion'\n\n/*\n * Modo de motion do Rendra. `off` (padrão): nada do Motion é montado, e o DOM e o\n * comportamento são os de sempre. `on`: os componentes trocam o elemento por `m.*` e animam.\n * O estado vive neste contexto próprio, não no do RendraProvider: o provider só o alimenta\n * pela prop `motion`, e uma tela (a de comparação) aninha o contexto para trocar on e off.\n */\n\nexport type MotionMode = 'off' | 'on'\n\ninterface MotionState {\n mode: MotionMode\n /**\n * O chunk do `domMax` (layout e arraste) já chegou. O contexto muda quando ele chega, para\n * os componentes que leem o modo renderizarem de novo: um `m.*` montado antes disso não tem\n * nó de projeção, e `layout`/`layoutId` só passam a valer na renderização seguinte.\n */\n layoutReady: boolean\n}\n\nconst MotionContext = createContext<MotionState>({ mode: 'off', layoutReady: false })\n\n/** Modo de motion do provider mais próximo (`off` sem provider). */\nexport function useMotionMode(): MotionMode {\n return useContext(MotionContext).mode\n}\n\n/**\n * Em `on`, o chunk do `domMax` já chegou. Um `m.*` com `layout` ou `layoutId` só ganha o nó de\n * projeção se for criado DEPOIS disso (o Motion não monta a projeção de um elemento que já\n * estava na tela), então quem usa layout liga a prop e remonta o item quando isto vira `true`.\n */\nexport function useLayoutReady(): boolean {\n const { mode, layoutReady } = useContext(MotionContext)\n return mode === 'on' && layoutReady\n}\n\nconst RevealContext = createContext(false)\n\n/**\n * Marca um trecho da árvore como \"chegada de painel\" (o dashboard): lá, o gráfico desenha no\n * tempo do reveal (900 ms) em vez do tempo de rotina (`draw`, 420 ms). Fora dele, o gráfico de\n * uma tela de uso diário desenha uma vez e rápido.\n */\nexport function RevealScope({ children }: { children: ReactNode }) {\n return <RevealContext.Provider value>{children}</RevealContext.Provider>\n}\n\n/** O componente está dentro de um `RevealScope`? */\nexport function useRevealScope(): boolean {\n return useContext(RevealContext)\n}\n\n/** Só troca o modo lido pelos componentes; não monta nem desmonta o LazyMotion. */\nexport function MotionModeScope({ mode, children }: { mode: MotionMode; children: ReactNode }) {\n const { layoutReady } = useContext(MotionContext)\n const value = useMemo(() => ({ mode, layoutReady }), [mode, layoutReady])\n return <MotionContext.Provider value={value}>{children}</MotionContext.Provider>\n}\n\n/** O carregador do `domMax` (chunk à parte): layout, layoutId e arraste do Motion. */\nconst loadMax = () => import('./features-max').then((m) => m.default)\n\n/**\n * Em `off`, só o contexto (nenhum nó novo, nenhum LazyMotion). Em `on`, dois `LazyMotion` (os\n * dois `strict`: só `m.*` entra, um `motion.*` esquecido quebra em vez de puxar o pacote inteiro):\n * o de fora carrega o `domMax` sob demanda (layout e arraste), em chunk separado; o de dentro traz\n * o `domAnimation` síncrono (animação e gestos) e é o que os `m.*` enxergam. Nessa ordem o\n * renderer síncrono já está no contexto na primeira renderização (elementos e gestos funcionam\n * na hora), e os recursos de layout se juntam quando o chunk chega. A ordem contrária esconderia\n * o renderer até o chunk terminar de baixar.\n *\n * O `MotionConfig` recebe \"reduzir movimento\" da mesma fonte dos presets (o `matchMedia` de\n * `use-reduced-motion.ts`, reativo): com `always`, o Motion também tira o deslocamento e o layout\n * de qualquer animação que um componente escreva à mão, e mantém a opacidade. Não é uma segunda\n * fonte: é a primeira, lida uma vez, entregue a dois consumidores.\n */\nexport function MotionProvider({ mode, children }: { mode: MotionMode; children: ReactNode }) {\n if (mode !== 'on') return <MotionModeScope mode=\"off\">{children}</MotionModeScope>\n return <OnProvider>{children}</OnProvider>\n}\n\nfunction OnProvider({ children }: { children: ReactNode }) {\n const [layoutReady, setLayoutReady] = useState(false)\n const reduced = usePrefersReducedMotion()\n const value = useMemo(() => ({ mode: 'on' as const, layoutReady }), [layoutReady])\n // O LazyMotion registra os recursos DEPOIS de a promessa do carregador resolver; o aviso vai\n // para o ciclo seguinte, para a renderização que ele provoca já enxergar o layout.\n const load = useMemo(\n () => () =>\n loadMax().then((features) => {\n setTimeout(() => setLayoutReady(true), 0)\n return features\n }),\n [],\n )\n return (\n <LazyMotion features={load} strict>\n <LazyMotion features={domAnimation} strict>\n <MotionConfig reducedMotion={reduced ? 'always' : 'never'}>\n <MotionContext.Provider value={value}>{children}</MotionContext.Provider>\n </MotionConfig>\n </LazyMotion>\n </LazyMotion>\n )\n}\n"],"mappings":";;;;;;AASA,SAAgB,uBAAuB,IAAgB;CACrD,MAAM,KAAK,WAAW,kCAAkC;CACxD,GAAG,iBAAiB,UAAU,EAAE;CAChC,aAAa,GAAG,oBAAoB,UAAU,EAAE;AAClD;AAEA,SAAgB,mBAAmB;CACjC,OAAO,WAAW,kCAAkC,CAAC,CAAC;AACxD;AAEA,SAAgB,0BAA0B;CACxC,OAAO,qBAAqB,wBAAwB,wBAAwB,KAAK;AACnF;;;ACEA,IAAM,gBAAgB,cAA2B;CAAE,MAAM;CAAO,aAAa;AAAM,CAAC;;AAGpF,SAAgB,gBAA4B;CAC1C,OAAO,WAAW,aAAa,CAAC,CAAC;AACnC;;;;;;AAOA,SAAgB,iBAA0B;CACxC,MAAM,EAAE,MAAM,gBAAgB,WAAW,aAAa;CACtD,OAAO,SAAS,QAAQ;AAC1B;AAEA,IAAM,gBAAgB,cAAc,KAAK;;AAYzC,SAAgB,iBAA0B;CACxC,OAAO,WAAW,aAAa;AACjC;;AAGA,SAAgB,gBAAgB,EAAE,MAAM,YAAuD;CAC7F,MAAM,EAAE,gBAAgB,WAAW,aAAa;CAChD,MAAM,QAAQ,eAAe;EAAE;EAAM;CAAY,IAAI,CAAC,MAAM,WAAW,CAAC;CACxE,OAAO,oBAAC,cAAc,UAAf;EAA+B;EAAQ;CAAiC,CAAA;AACjF;;AAGA,IAAM,gBAAgB,OAAO,6BAAiB,CAAC,MAAM,MAAM,EAAE,OAAO;;;;;;;;;;;;;;;AAgBpE,SAAgB,eAAe,EAAE,MAAM,YAAuD;CAC5F,IAAI,SAAS,MAAM,OAAO,oBAAC,iBAAD;EAAiB,MAAK;EAAO;CAA0B,CAAA;CACjF,OAAO,oBAAC,YAAD,EAAa,SAAqB,CAAA;AAC3C;AAEA,SAAS,WAAW,EAAE,YAAqC;CACzD,MAAM,CAAC,aAAa,kBAAkB,SAAS,KAAK;CACpD,MAAM,UAAU,wBAAwB;CACxC,MAAM,QAAQ,eAAe;EAAE,MAAM;EAAe;CAAY,IAAI,CAAC,WAAW,CAAC;CAGjF,MAAM,OAAO,oBAET,QAAQ,CAAC,CAAC,MAAM,aAAa;EAC3B,iBAAiB,eAAe,IAAI,GAAG,CAAC;EACxC,OAAO;CACT,CAAC,GACH,CAAC,CACH;CACA,OACE,oBAAC,YAAD;EAAY,UAAU;EAAM,QAAA;EAC1B,UAAA,oBAAC,YAAD;GAAY,UAAU;GAAc,QAAA;GAClC,UAAA,oBAAC,cAAD;IAAc,eAAe,UAAU,WAAW;IAChD,UAAA,oBAAC,cAAc,UAAf;KAA+B;KAAQ;IAAiC,CAAA;GAC5D,CAAA;EACJ,CAAA;CACF,CAAA;AAEhB"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
/*! Rendra Design System v2.
|
|
2
|
-
import {
|
|
1
|
+
/*! Rendra Design System v2.5.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
|
|
2
|
+
import { t as MotionProvider } from "./motion-context-5BRIQAJm.js";
|
|
3
3
|
import { createContext, useContext, useMemo, useSyncExternalStore } from "react";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
5
|
//#region src/components/rendra-provider.tsx
|
|
5
6
|
/** Sem roteador nenhum: o link é só um `<a href>`. */
|
|
6
7
|
function DefaultLink({ to, children, ...rest }) {
|
|
@@ -43,7 +44,7 @@ var RendraContext = createContext({
|
|
|
43
44
|
* Sem `RendraProvider` na árvore, os hooks abaixo caem para um comportamento simples,
|
|
44
45
|
* baseado só em `window.location`/`history`, e os componentes continuam funcionando.
|
|
45
46
|
*/
|
|
46
|
-
function RendraProvider({ children, linkComponent, useCurrentPath: useCurrentPathProp, navigate, goBack, useBreadcrumbs }) {
|
|
47
|
+
function RendraProvider({ children, linkComponent, useCurrentPath: useCurrentPathProp, navigate, goBack, useBreadcrumbs, motion = "off" }) {
|
|
47
48
|
const value = useMemo(() => ({
|
|
48
49
|
linkComponent,
|
|
49
50
|
useCurrentPath: useCurrentPathProp,
|
|
@@ -59,7 +60,10 @@ function RendraProvider({ children, linkComponent, useCurrentPath: useCurrentPat
|
|
|
59
60
|
]);
|
|
60
61
|
return /* @__PURE__ */ jsx(RendraContext.Provider, {
|
|
61
62
|
value,
|
|
62
|
-
children
|
|
63
|
+
children: /* @__PURE__ */ jsx(MotionProvider, {
|
|
64
|
+
mode: motion,
|
|
65
|
+
children
|
|
66
|
+
})
|
|
63
67
|
});
|
|
64
68
|
}
|
|
65
69
|
/** Componente de link do provider ativo (ou `<a href>`, sem provider). */
|
|
@@ -85,4 +89,4 @@ function useRendraBreadcrumbs() {
|
|
|
85
89
|
//#endregion
|
|
86
90
|
export { useRendraNavigate as a, useRendraLink as i, useCurrentPath as n, useRendraBreadcrumbs as r, RendraProvider as t };
|
|
87
91
|
|
|
88
|
-
//# sourceMappingURL=rendra-provider-
|
|
92
|
+
//# sourceMappingURL=rendra-provider-CRe0XdOU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rendra-provider-CRe0XdOU.js","names":[],"sources":["../src/components/rendra-provider.tsx"],"sourcesContent":["import {\n createContext,\n useContext,\n useMemo,\n useSyncExternalStore,\n type AnchorHTMLAttributes,\n type ComponentType,\n type ReactNode,\n} from 'react'\nimport { MotionProvider, type MotionMode } from '@/lib/motion/motion-context'\n\n/**\n * Link com a mesma interface do `<a>`/`Link`: recebe `to`, `className`, `children`,\n * `aria-*`, `onClick` e repassa o resto.\n */\nexport interface RendraLinkProps {\n to: string\n className?: string\n children?: ReactNode\n [key: string]: unknown\n}\n\nexport interface RendraBreadcrumbItem {\n label: string\n to?: string\n}\n\nexport interface RendraNavigateOptions {\n replace?: boolean\n}\n\nexport interface RendraProviderProps {\n children: ReactNode\n /** Componente de link do roteador do host (ex.: `Link` do react-router). */\n linkComponent: ComponentType<RendraLinkProps>\n /** Devolve o caminho atual (ex.: `useLocation().pathname`). */\n useCurrentPath: () => string\n /** Navega para um caminho, com `replace` opcional. */\n navigate: (to: string, options?: RendraNavigateOptions) => void\n /** Volta à tela anterior. */\n goBack: () => void\n /** Trilha da rota atual (ex.: via `useMatches` e `handle.crumb`). Opcional. */\n useBreadcrumbs?: () => RendraBreadcrumbItem[]\n /**\n * Animações dos componentes. `off` (padrão): sem nenhuma animação do Motion, a árvore e o\n * comportamento de sempre. `on`: entradas, saídas e layout animados pelo Motion.\n */\n motion?: MotionMode\n}\n\ninterface RendraContextValue {\n linkComponent: ComponentType<RendraLinkProps>\n useCurrentPath: () => string\n navigate: (to: string, options?: RendraNavigateOptions) => void\n goBack: () => void\n useBreadcrumbs: () => RendraBreadcrumbItem[]\n}\n\n/** Sem roteador nenhum: o link é só um `<a href>`. */\nfunction DefaultLink({ to, children, ...rest }: RendraLinkProps) {\n return (\n <a href={to} {...(rest as AnchorHTMLAttributes<HTMLAnchorElement>)}>\n {children}\n </a>\n )\n}\n\nfunction subscribeToLocation(onChange: () => void) {\n window.addEventListener('popstate', onChange)\n return () => window.removeEventListener('popstate', onChange)\n}\n\n/** Sem roteador nenhum: lê `window.location.pathname` direto. */\nfunction useDefaultCurrentPath(): string {\n return useSyncExternalStore(\n subscribeToLocation,\n () => window.location.pathname,\n () => '/',\n )\n}\n\n/** Sem roteador nenhum: navega com `window.location`. */\nfunction defaultNavigate(to: string, options?: RendraNavigateOptions) {\n if (options?.replace) {\n window.location.replace(to)\n } else {\n window.location.assign(to)\n }\n}\n\n/** Sem roteador nenhum: volta pelo histórico do navegador. */\nfunction defaultGoBack() {\n window.history.back()\n}\n\n/** Sem roteador nenhum: nenhuma trilha para montar. */\nfunction defaultUseBreadcrumbs(): RendraBreadcrumbItem[] {\n return []\n}\n\nconst defaultValue: RendraContextValue = {\n linkComponent: DefaultLink,\n useCurrentPath: useDefaultCurrentPath,\n navigate: defaultNavigate,\n goBack: defaultGoBack,\n useBreadcrumbs: defaultUseBreadcrumbs,\n}\n\nconst RendraContext = createContext<RendraContextValue>(defaultValue)\n\n/**\n * Única peça que sabe como navegar (`react-router`, outro roteador, ou nenhum).\n * Sem `RendraProvider` na árvore, os hooks abaixo caem para um comportamento simples,\n * baseado só em `window.location`/`history`, e os componentes continuam funcionando.\n */\nexport function RendraProvider({\n children,\n linkComponent,\n useCurrentPath: useCurrentPathProp,\n navigate,\n goBack,\n useBreadcrumbs,\n motion = 'off',\n}: RendraProviderProps) {\n const value = useMemo<RendraContextValue>(\n () => ({\n linkComponent,\n useCurrentPath: useCurrentPathProp,\n navigate,\n goBack,\n useBreadcrumbs: useBreadcrumbs ?? defaultUseBreadcrumbs,\n }),\n [linkComponent, useCurrentPathProp, navigate, goBack, useBreadcrumbs],\n )\n return (\n <RendraContext.Provider value={value}>\n <MotionProvider mode={motion}>{children}</MotionProvider>\n </RendraContext.Provider>\n )\n}\n\n/** Componente de link do provider ativo (ou `<a href>`, sem provider). */\nexport function useRendraLink(): ComponentType<RendraLinkProps> {\n return useContext(RendraContext).linkComponent\n}\n\n/** Caminho atual (ex.: `/clientes/novo`), do provider ativo ou de `window.location`. */\nexport function useCurrentPath(): string {\n const ctx = useContext(RendraContext)\n return ctx.useCurrentPath()\n}\n\n/** Navegar e voltar, do provider ativo ou de `window.location`/`history`. */\nexport function useRendraNavigate(): {\n navigate: (to: string, options?: RendraNavigateOptions) => void\n goBack: () => void\n} {\n const ctx = useContext(RendraContext)\n return { navigate: ctx.navigate, goBack: ctx.goBack }\n}\n\n/** Trilha da rota atual, do provider ativo ou vazia, sem roteador. */\nexport function useRendraBreadcrumbs(): RendraBreadcrumbItem[] {\n const ctx = useContext(RendraContext)\n return ctx.useBreadcrumbs()\n}\n"],"mappings":";;;;;;AA2DA,SAAS,YAAY,EAAE,IAAI,UAAU,GAAG,QAAyB;CAC/D,OACE,oBAAC,KAAD;EAAG,MAAM;EAAI,GAAK;EACf;CACA,CAAA;AAEP;AAEA,SAAS,oBAAoB,UAAsB;CACjD,OAAO,iBAAiB,YAAY,QAAQ;CAC5C,aAAa,OAAO,oBAAoB,YAAY,QAAQ;AAC9D;;AAGA,SAAS,wBAAgC;CACvC,OAAO,qBACL,2BACM,OAAO,SAAS,gBAChB,GACR;AACF;;AAGA,SAAS,gBAAgB,IAAY,SAAiC;CACpE,IAAI,SAAS,SACX,OAAO,SAAS,QAAQ,EAAE;MAE1B,OAAO,SAAS,OAAO,EAAE;AAE7B;;AAGA,SAAS,gBAAgB;CACvB,OAAO,QAAQ,KAAK;AACtB;;AAGA,SAAS,wBAAgD;CACvD,OAAO,CAAC;AACV;AAUA,IAAM,gBAAgB,cAAkC;CAPtD,eAAe;CACf,gBAAgB;CAChB,UAAU;CACV,QAAQ;CACR,gBAAgB;AAGsC,CAAY;;;;;;AAOpE,SAAgB,eAAe,EAC7B,UACA,eACA,gBAAgB,oBAChB,UACA,QACA,gBACA,SAAS,SACa;CACtB,MAAM,QAAQ,eACL;EACL;EACA,gBAAgB;EAChB;EACA;EACA,gBAAgB,kBAAkB;CACpC,IACA;EAAC;EAAe;EAAoB;EAAU;EAAQ;CAAc,CACtE;CACA,OACE,oBAAC,cAAc,UAAf;EAA+B;EAC7B,UAAA,oBAAC,gBAAD;GAAgB,MAAM;GAAS;EAAyB,CAAA;CAClC,CAAA;AAE5B;;AAGA,SAAgB,gBAAgD;CAC9D,OAAO,WAAW,aAAa,CAAC,CAAC;AACnC;;AAGA,SAAgB,iBAAyB;CAEvC,OADY,WAAW,aAChB,CAAA,CAAI,eAAe;AAC5B;;AAGA,SAAgB,oBAGd;CACA,MAAM,MAAM,WAAW,aAAa;CACpC,OAAO;EAAE,UAAU,IAAI;EAAU,QAAQ,IAAI;CAAO;AACtD;;AAGA,SAAgB,uBAA+C;CAE7D,OADY,WAAW,aAChB,CAAA,CAAI,eAAe;AAC5B"}
|
package/dist/rich-text-editor.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
/*! Rendra Design System v2.
|
|
2
|
-
import { t as cn } from "./cn-
|
|
3
|
-
import { a as DropdownMenuContent, d as DropdownMenuSeparator, h as DropdownMenuTrigger, r as DropdownMenu, s as DropdownMenuItem, t as Tooltip } from "./tooltip-
|
|
1
|
+
/*! Rendra Design System v2.5.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
|
|
2
|
+
import { t as cn } from "./cn-Cw7M5kEP.js";
|
|
3
|
+
import { a as DropdownMenuContent, d as DropdownMenuSeparator, h as DropdownMenuTrigger, r as DropdownMenu, s as DropdownMenuItem, t as Tooltip } from "./tooltip-BAMSaGbS.js";
|
|
4
4
|
import { AlignCenter, AlignJustify, AlignLeft, AlignRight, Bold, Code, Code2, Eraser, ImagePlus, Italic, Link2, List, ListOrdered, Minus, Quote, Redo2, Strikethrough, Table, Underline, Undo2 } from "lucide-react";
|
|
5
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
5
|
import { useEffect, useRef, useState } from "react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
import { Image } from "@tiptap/extension-image";
|
|
8
8
|
import { Placeholder } from "@tiptap/extension-placeholder";
|
|
9
9
|
import { TableKit } from "@tiptap/extension-table";
|
package/dist/router-bridge.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/*! Rendra Design System v2.
|
|
2
|
-
import { t as RendraProvider } from "./rendra-provider-
|
|
3
|
-
import { jsx } from "react/jsx-runtime";
|
|
1
|
+
/*! Rendra Design System v2.5.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
|
|
2
|
+
import { t as RendraProvider } from "./rendra-provider-CRe0XdOU.js";
|
|
4
3
|
import { useCallback } from "react";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
5
|
import { Link, Outlet, useLocation, useMatches, useNavigate } from "react-router";
|
|
6
6
|
//#region src/components/rendra-router-bridge.tsx
|
|
7
7
|
/** `Link` do react-router com a interface do `RendraLinkProps` (repassa o resto). */
|
|
@@ -32,7 +32,7 @@ function useBreadcrumbsFromMatches() {
|
|
|
32
32
|
* componentes de `src/components/ui` e o `AppShell` não importam `react-router` diretamente.
|
|
33
33
|
* Sem `children`, renderiza `<Outlet />`, para ser usado como elemento raiz das rotas.
|
|
34
34
|
*/
|
|
35
|
-
function RendraRouterBridge({ children } = {}) {
|
|
35
|
+
function RendraRouterBridge({ children, motion } = {}) {
|
|
36
36
|
const navigate = useNavigate();
|
|
37
37
|
const go = useCallback((to, options) => navigate(to, options), [navigate]);
|
|
38
38
|
const goBack = useCallback(() => navigate(-1), [navigate]);
|
|
@@ -42,6 +42,7 @@ function RendraRouterBridge({ children } = {}) {
|
|
|
42
42
|
navigate: go,
|
|
43
43
|
goBack,
|
|
44
44
|
useBreadcrumbs: useBreadcrumbsFromMatches,
|
|
45
|
+
motion,
|
|
45
46
|
children: children ?? /* @__PURE__ */ jsx(Outlet, {})
|
|
46
47
|
});
|
|
47
48
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router-bridge.js","names":[],"sources":["../src/components/rendra-router-bridge.tsx"],"sourcesContent":["import { useCallback, type ReactNode } from 'react'\nimport { Link, Outlet, useLocation, useMatches, useNavigate, type UIMatch } from 'react-router'\nimport {\n RendraProvider,\n type RendraBreadcrumbItem,\n type RendraLinkProps,\n} from '@/components/rendra-provider'\n\n/**\n * Metadados de rota lidos pela trilha: handle: { crumb: 'Clientes' }. Convenção do\n * react-router (`handle`), que não existe em outros roteadores; por isso fica aqui, na\n * ponte, e não em src/components/app-shell/header.tsx.\n */\nexport interface RouteHandle {\n crumb?: string | ((params: Record<string, string | undefined>) => string)\n}\n\n/** `Link` do react-router com a interface do `RendraLinkProps` (repassa o resto). */\nfunction RouterLink({ to, children, ...rest }: RendraLinkProps) {\n return (\n <Link to={to} {...rest}>\n {children}\n </Link>\n )\n}\n\n/** Caminho atual do react-router. */\nfunction useCurrentPathFromRouter(): string {\n return useLocation().pathname\n}\n\n/** Trilha a partir de `useMatches`/`handle.crumb`, a mesma convenção do header. */\nfunction useBreadcrumbsFromMatches(): RendraBreadcrumbItem[] {\n const matches = useMatches() as UIMatch<unknown, RouteHandle | undefined>[]\n return matches\n .filter((m) => m.handle?.crumb)\n .map((m, i, all) => {\n const crumb = m.handle!.crumb!\n return {\n label: typeof crumb === 'function' ? crumb(m.params) : crumb,\n to: i < all.length - 1 ? m.pathname : undefined,\n }\n })\n}\n\n/**\n * Liga o `RendraProvider` ao `react-router` do boilerplate: link, caminho atual, navegar\n * e a trilha. É o único lugar do app que sabe que o roteador é o `react-router`; os\n * componentes de `src/components/ui` e o `AppShell` não importam `react-router` diretamente.\n * Sem `children`, renderiza `<Outlet />`, para ser usado como elemento raiz das rotas.\n */\nexport function RendraRouterBridge({
|
|
1
|
+
{"version":3,"file":"router-bridge.js","names":[],"sources":["../src/components/rendra-router-bridge.tsx"],"sourcesContent":["import { useCallback, type ReactNode } from 'react'\nimport { Link, Outlet, useLocation, useMatches, useNavigate, type UIMatch } from 'react-router'\nimport {\n RendraProvider,\n type RendraBreadcrumbItem,\n type RendraLinkProps,\n} from '@/components/rendra-provider'\nimport type { MotionMode } from '@/lib/motion/motion-context'\n\n/**\n * Metadados de rota lidos pela trilha: handle: { crumb: 'Clientes' }. Convenção do\n * react-router (`handle`), que não existe em outros roteadores; por isso fica aqui, na\n * ponte, e não em src/components/app-shell/header.tsx.\n */\nexport interface RouteHandle {\n crumb?: string | ((params: Record<string, string | undefined>) => string)\n}\n\n/** `Link` do react-router com a interface do `RendraLinkProps` (repassa o resto). */\nfunction RouterLink({ to, children, ...rest }: RendraLinkProps) {\n return (\n <Link to={to} {...rest}>\n {children}\n </Link>\n )\n}\n\n/** Caminho atual do react-router. */\nfunction useCurrentPathFromRouter(): string {\n return useLocation().pathname\n}\n\n/** Trilha a partir de `useMatches`/`handle.crumb`, a mesma convenção do header. */\nfunction useBreadcrumbsFromMatches(): RendraBreadcrumbItem[] {\n const matches = useMatches() as UIMatch<unknown, RouteHandle | undefined>[]\n return matches\n .filter((m) => m.handle?.crumb)\n .map((m, i, all) => {\n const crumb = m.handle!.crumb!\n return {\n label: typeof crumb === 'function' ? crumb(m.params) : crumb,\n to: i < all.length - 1 ? m.pathname : undefined,\n }\n })\n}\n\n/**\n * Liga o `RendraProvider` ao `react-router` do boilerplate: link, caminho atual, navegar\n * e a trilha. É o único lugar do app que sabe que o roteador é o `react-router`; os\n * componentes de `src/components/ui` e o `AppShell` não importam `react-router` diretamente.\n * Sem `children`, renderiza `<Outlet />`, para ser usado como elemento raiz das rotas.\n */\nexport function RendraRouterBridge({\n children,\n motion,\n}: { children?: ReactNode; motion?: MotionMode } = {}) {\n const navigate = useNavigate()\n const go = useCallback(\n (to: string, options?: { replace?: boolean }) => navigate(to, options),\n [navigate],\n )\n const goBack = useCallback(() => navigate(-1), [navigate])\n return (\n <RendraProvider\n linkComponent={RouterLink}\n useCurrentPath={useCurrentPathFromRouter}\n navigate={go}\n goBack={goBack}\n useBreadcrumbs={useBreadcrumbsFromMatches}\n motion={motion}\n >\n {children ?? <Outlet />}\n </RendraProvider>\n )\n}\n"],"mappings":";;;;;;;AAmBA,SAAS,WAAW,EAAE,IAAI,UAAU,GAAG,QAAyB;CAC9D,OACE,oBAAC,MAAD;EAAU;EAAI,GAAI;EACf;CACG,CAAA;AAEV;;AAGA,SAAS,2BAAmC;CAC1C,OAAO,YAAY,CAAC,CAAC;AACvB;;AAGA,SAAS,4BAAoD;CAE3D,OADgB,WACT,CAAA,CACJ,QAAQ,MAAM,EAAE,QAAQ,KAAK,CAAC,CAC9B,KAAK,GAAG,GAAG,QAAQ;EAClB,MAAM,QAAQ,EAAE,OAAQ;EACxB,OAAO;GACL,OAAO,OAAO,UAAU,aAAa,MAAM,EAAE,MAAM,IAAI;GACvD,IAAI,IAAI,IAAI,SAAS,IAAI,EAAE,WAAW,KAAA;EACxC;CACF,CAAC;AACL;;;;;;;AAQA,SAAgB,mBAAmB,EACjC,UACA,WACiD,CAAC,GAAG;CACrD,MAAM,WAAW,YAAY;CAC7B,MAAM,KAAK,aACR,IAAY,YAAoC,SAAS,IAAI,OAAO,GACrE,CAAC,QAAQ,CACX;CACA,MAAM,SAAS,kBAAkB,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC;CACzD,OACE,oBAAC,gBAAD;EACE,eAAe;EACf,gBAAgB;EAChB,UAAU;EACF;EACR,gBAAgB;EACR;EAEP,UAAA,YAAY,oBAAC,QAAD,CAAS,CAAA;CACR,CAAA;AAEpB"}
|
package/dist/tokens.css
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! Rendra Design System v2.
|
|
1
|
+
/*! Rendra Design System v2.5.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
|
|
2
2
|
|
|
3
3
|
@layer theme, base, rendra.base, components, rendra.components, utilities;
|
|
4
4
|
@layer theme, base, components, utilities;
|
|
@@ -285,6 +285,26 @@
|
|
|
285
285
|
--rendra-label-color: var(--rendra-foreground);
|
|
286
286
|
}
|
|
287
287
|
:root,
|
|
288
|
+
[data-rendra-root] {
|
|
289
|
+
--rendra-duration-press: 120ms;
|
|
290
|
+
--rendra-duration-hover: 150ms;
|
|
291
|
+
--rendra-duration-fast: 120ms;
|
|
292
|
+
--rendra-duration-base: 200ms;
|
|
293
|
+
--rendra-duration-move: 250ms;
|
|
294
|
+
--rendra-duration-slow: 320ms;
|
|
295
|
+
--rendra-duration-draw: 420ms;
|
|
296
|
+
--rendra-duration-pulse: 1000ms;
|
|
297
|
+
--rendra-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
|
|
298
|
+
--rendra-ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
|
|
299
|
+
--rendra-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
300
|
+
--rendra-ease-move: cubic-bezier(0.77, 0, 0.175, 1);
|
|
301
|
+
--rendra-ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
|
|
302
|
+
--rendra-reveal-enter: 600ms;
|
|
303
|
+
--rendra-reveal-stagger: 120ms;
|
|
304
|
+
--rendra-reveal-count: 1200ms;
|
|
305
|
+
--rendra-reveal-draw: 900ms;
|
|
306
|
+
}
|
|
307
|
+
:root,
|
|
288
308
|
[data-rendra-root],
|
|
289
309
|
[data-shape='rounded'] {
|
|
290
310
|
--rendra-shape-control: calc(var(--rendra-radius) - 2px);
|
|
@@ -331,6 +351,14 @@
|
|
|
331
351
|
transform: translateX(400%);
|
|
332
352
|
}
|
|
333
353
|
}
|
|
354
|
+
@keyframes rd-shimmer {
|
|
355
|
+
from {
|
|
356
|
+
transform: translateX(-100%);
|
|
357
|
+
}
|
|
358
|
+
to {
|
|
359
|
+
transform: translateX(100%);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
334
362
|
:root {
|
|
335
363
|
--rendra-swatch-check-light: #ffffff;
|
|
336
364
|
--rendra-swatch-check-dark: #0b1d37;
|
|
@@ -388,6 +416,26 @@
|
|
|
388
416
|
inherits: false;
|
|
389
417
|
initial-value: 1;
|
|
390
418
|
}
|
|
419
|
+
@property --tw-rotate-x {
|
|
420
|
+
syntax: '*';
|
|
421
|
+
inherits: false;
|
|
422
|
+
}
|
|
423
|
+
@property --tw-rotate-y {
|
|
424
|
+
syntax: '*';
|
|
425
|
+
inherits: false;
|
|
426
|
+
}
|
|
427
|
+
@property --tw-rotate-z {
|
|
428
|
+
syntax: '*';
|
|
429
|
+
inherits: false;
|
|
430
|
+
}
|
|
431
|
+
@property --tw-skew-x {
|
|
432
|
+
syntax: '*';
|
|
433
|
+
inherits: false;
|
|
434
|
+
}
|
|
435
|
+
@property --tw-skew-y {
|
|
436
|
+
syntax: '*';
|
|
437
|
+
inherits: false;
|
|
438
|
+
}
|
|
391
439
|
@property --tw-pan-x {
|
|
392
440
|
syntax: '*';
|
|
393
441
|
inherits: false;
|
|
@@ -522,19 +570,6 @@
|
|
|
522
570
|
inherits: false;
|
|
523
571
|
initial-value: solid;
|
|
524
572
|
}
|
|
525
|
-
@property --tw-duration {
|
|
526
|
-
syntax: '*';
|
|
527
|
-
inherits: false;
|
|
528
|
-
}
|
|
529
|
-
@property --tw-ease {
|
|
530
|
-
syntax: '*';
|
|
531
|
-
inherits: false;
|
|
532
|
-
}
|
|
533
|
-
@property --tw-content {
|
|
534
|
-
syntax: '*';
|
|
535
|
-
initial-value: '';
|
|
536
|
-
inherits: false;
|
|
537
|
-
}
|
|
538
573
|
@property --tw-blur {
|
|
539
574
|
syntax: '*';
|
|
540
575
|
inherits: false;
|
|
@@ -588,6 +623,19 @@
|
|
|
588
623
|
syntax: '*';
|
|
589
624
|
inherits: false;
|
|
590
625
|
}
|
|
626
|
+
@property --tw-duration {
|
|
627
|
+
syntax: '*';
|
|
628
|
+
inherits: false;
|
|
629
|
+
}
|
|
630
|
+
@property --tw-ease {
|
|
631
|
+
syntax: '*';
|
|
632
|
+
inherits: false;
|
|
633
|
+
}
|
|
634
|
+
@property --tw-content {
|
|
635
|
+
syntax: '*';
|
|
636
|
+
initial-value: '';
|
|
637
|
+
inherits: false;
|
|
638
|
+
}
|
|
591
639
|
@keyframes spin {
|
|
592
640
|
to {
|
|
593
641
|
transform: rotate(360deg);
|
|
@@ -689,7 +737,7 @@
|
|
|
689
737
|
@keyframes rd-pop {
|
|
690
738
|
0% {
|
|
691
739
|
opacity: 0;
|
|
692
|
-
transform: scale(0.
|
|
740
|
+
transform: scale(0.8);
|
|
693
741
|
}
|
|
694
742
|
60% {
|
|
695
743
|
opacity: 1;
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/*! Rendra Design System v2.5.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
|
|
2
|
+
import { t as cn } from "./cn-Cw7M5kEP.js";
|
|
3
|
+
import { r as useMotionMode } from "./motion-context-5BRIQAJm.js";
|
|
4
|
+
import { t as useMotionPresets } from "./use-motion-presets-BrkgL8lG.js";
|
|
5
|
+
import { Check, ChevronRight } from "lucide-react";
|
|
6
|
+
import { AnimatePresence, m } from "motion/react";
|
|
7
|
+
import { DropdownMenu, Tooltip } from "radix-ui";
|
|
8
|
+
import { createContext, forwardRef, useContext, useState } from "react";
|
|
9
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
//#region src/components/ui/dropdown-menu.tsx
|
|
11
|
+
var MenuOpenContext = createContext(null);
|
|
12
|
+
var SubOpenContext = createContext(null);
|
|
13
|
+
function MirroredRoot({ open, defaultOpen, onOpenChange, ...rest }) {
|
|
14
|
+
const [inner, setInner] = useState(defaultOpen ?? false);
|
|
15
|
+
const current = open ?? inner;
|
|
16
|
+
return /* @__PURE__ */ jsx(MenuOpenContext.Provider, {
|
|
17
|
+
value: current,
|
|
18
|
+
children: /* @__PURE__ */ jsx(DropdownMenu.Root, {
|
|
19
|
+
...rest,
|
|
20
|
+
open: current,
|
|
21
|
+
onOpenChange: (next) => {
|
|
22
|
+
setInner(next);
|
|
23
|
+
onOpenChange?.(next);
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function MirroredSub({ open, defaultOpen, onOpenChange, ...rest }) {
|
|
29
|
+
const [inner, setInner] = useState(defaultOpen ?? false);
|
|
30
|
+
const current = open ?? inner;
|
|
31
|
+
return /* @__PURE__ */ jsx(SubOpenContext.Provider, {
|
|
32
|
+
value: current,
|
|
33
|
+
children: /* @__PURE__ */ jsx(DropdownMenu.Sub, {
|
|
34
|
+
...rest,
|
|
35
|
+
open: current,
|
|
36
|
+
onOpenChange: (next) => {
|
|
37
|
+
setInner(next);
|
|
38
|
+
onOpenChange?.(next);
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function DropdownMenu$1(props) {
|
|
44
|
+
return useMotionMode() === "on" ? /* @__PURE__ */ jsx(MirroredRoot, { ...props }) : /* @__PURE__ */ jsx(DropdownMenu.Root, { ...props });
|
|
45
|
+
}
|
|
46
|
+
var DropdownMenuTrigger = DropdownMenu.Trigger;
|
|
47
|
+
var DropdownMenuGroup = DropdownMenu.Group;
|
|
48
|
+
function DropdownMenuSub(props) {
|
|
49
|
+
return useMotionMode() === "on" ? /* @__PURE__ */ jsx(MirroredSub, { ...props }) : /* @__PURE__ */ jsx(DropdownMenu.Sub, { ...props });
|
|
50
|
+
}
|
|
51
|
+
var DropdownMenuRadioGroup = DropdownMenu.RadioGroup;
|
|
52
|
+
var panelBase = "z-50 w-max min-w-3xs max-w-popover origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-surface border bg-popover p-1 text-popover-foreground shadow-md";
|
|
53
|
+
var panelOff = cn(panelBase, "animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:duration-(--rendra-duration-fast) data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95");
|
|
54
|
+
var item = "relative flex min-h-touch cursor-pointer items-center gap-2 rounded-item px-3 text-sm outline-none select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-highlighted:bg-accent data-highlighted:text-accent-foreground md:min-h-0 md:py-2 [&_svg]:size-icon-sm [&_svg]:shrink-0 [&_svg]:text-muted-foreground";
|
|
55
|
+
function DropdownMenuContent({ className, sideOffset = 8, children, asChild, ...props }) {
|
|
56
|
+
const open = useContext(MenuOpenContext);
|
|
57
|
+
const motion = useMotionMode();
|
|
58
|
+
const presets = useMotionPresets();
|
|
59
|
+
if (motion === "on" && open !== null && !asChild) return /* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsx(DropdownMenu.Portal, {
|
|
60
|
+
forceMount: true,
|
|
61
|
+
children: /* @__PURE__ */ jsx(DropdownMenu.Content, {
|
|
62
|
+
forceMount: true,
|
|
63
|
+
asChild: true,
|
|
64
|
+
sideOffset,
|
|
65
|
+
collisionPadding: 16,
|
|
66
|
+
"data-rendra": "DDM-001",
|
|
67
|
+
className: cn(panelBase, className),
|
|
68
|
+
...props,
|
|
69
|
+
children: /* @__PURE__ */ jsx(m.div, {
|
|
70
|
+
...presets.open(),
|
|
71
|
+
children
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
}, "menu") });
|
|
75
|
+
return /* @__PURE__ */ jsx(DropdownMenu.Portal, { children: /* @__PURE__ */ jsx(DropdownMenu.Content, {
|
|
76
|
+
sideOffset,
|
|
77
|
+
collisionPadding: 16,
|
|
78
|
+
"data-rendra": "DDM-001",
|
|
79
|
+
className: cn(panelOff, className),
|
|
80
|
+
asChild,
|
|
81
|
+
...props,
|
|
82
|
+
children
|
|
83
|
+
}) });
|
|
84
|
+
}
|
|
85
|
+
function DropdownMenuItem({ className, destructive, ...props }) {
|
|
86
|
+
return /* @__PURE__ */ jsx(DropdownMenu.Item, {
|
|
87
|
+
className: cn(item, destructive && "text-destructive data-highlighted:bg-destructive-soft data-highlighted:text-destructive-soft-foreground [&_svg]:text-current", className),
|
|
88
|
+
...props
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function DropdownMenuCheckboxItem({ className, children, ...props }) {
|
|
92
|
+
return /* @__PURE__ */ jsxs(DropdownMenu.CheckboxItem, {
|
|
93
|
+
className: cn(item, "pl-8", className),
|
|
94
|
+
...props,
|
|
95
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
96
|
+
className: "absolute left-2 flex size-icon-sm items-center justify-center",
|
|
97
|
+
children: /* @__PURE__ */ jsx(DropdownMenu.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, { className: "text-primary-text" }) })
|
|
98
|
+
}), children]
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
function DropdownMenuRadioItem({ className, children, ...props }) {
|
|
102
|
+
return /* @__PURE__ */ jsxs(DropdownMenu.RadioItem, {
|
|
103
|
+
className: cn(item, "pl-8", className),
|
|
104
|
+
...props,
|
|
105
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
106
|
+
className: "absolute left-2 flex size-icon-sm items-center justify-center",
|
|
107
|
+
children: /* @__PURE__ */ jsx(DropdownMenu.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, { className: "text-primary-text" }) })
|
|
108
|
+
}), children]
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
function DropdownMenuLabel({ className, ...props }) {
|
|
112
|
+
return /* @__PURE__ */ jsx(DropdownMenu.Label, {
|
|
113
|
+
className: cn("px-2 py-2 text-xs font-medium text-muted-foreground", className),
|
|
114
|
+
...props
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
function DropdownMenuSeparator({ className, ...props }) {
|
|
118
|
+
return /* @__PURE__ */ jsx(DropdownMenu.Separator, {
|
|
119
|
+
className: cn("-mx-1 my-1 h-px bg-border", className),
|
|
120
|
+
...props
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
function DropdownMenuSubTrigger({ className, children, ...props }) {
|
|
124
|
+
return /* @__PURE__ */ jsxs(DropdownMenu.SubTrigger, {
|
|
125
|
+
className: cn(item, "data-[state=open]:bg-accent", className),
|
|
126
|
+
...props,
|
|
127
|
+
children: [children, /* @__PURE__ */ jsx(ChevronRight, { className: "ml-auto" })]
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
function DropdownMenuSubContent({ className, children, asChild, ...props }) {
|
|
131
|
+
const open = useContext(SubOpenContext);
|
|
132
|
+
const motion = useMotionMode();
|
|
133
|
+
const presets = useMotionPresets();
|
|
134
|
+
if (motion === "on" && open !== null && !asChild) return /* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsx(DropdownMenu.Portal, {
|
|
135
|
+
forceMount: true,
|
|
136
|
+
children: /* @__PURE__ */ jsx(DropdownMenu.SubContent, {
|
|
137
|
+
forceMount: true,
|
|
138
|
+
asChild: true,
|
|
139
|
+
collisionPadding: 16,
|
|
140
|
+
className: cn(panelBase, className),
|
|
141
|
+
...props,
|
|
142
|
+
children: /* @__PURE__ */ jsx(m.div, {
|
|
143
|
+
...presets.open(),
|
|
144
|
+
children
|
|
145
|
+
})
|
|
146
|
+
})
|
|
147
|
+
}, "submenu") });
|
|
148
|
+
return /* @__PURE__ */ jsx(DropdownMenu.Portal, { children: /* @__PURE__ */ jsx(DropdownMenu.SubContent, {
|
|
149
|
+
collisionPadding: 16,
|
|
150
|
+
className: cn(panelOff, className),
|
|
151
|
+
asChild,
|
|
152
|
+
...props,
|
|
153
|
+
children
|
|
154
|
+
}) });
|
|
155
|
+
}
|
|
156
|
+
//#endregion
|
|
157
|
+
//#region src/components/ui/tooltip.tsx
|
|
158
|
+
/**
|
|
159
|
+
* Tooltip: só para informação complementar, nunca essencial (não existe hover no toque).
|
|
160
|
+
* Informação essencial vai em texto de ajuda visível ou em Popover acionado por toque.
|
|
161
|
+
*/
|
|
162
|
+
function TooltipProvider({ children }) {
|
|
163
|
+
return /* @__PURE__ */ jsx(Tooltip.Provider, {
|
|
164
|
+
delayDuration: 300,
|
|
165
|
+
skipDelayDuration: 150,
|
|
166
|
+
children
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
var contentCls = "z-50 max-w-xs origin-(--radix-tooltip-content-transform-origin) wrap-break-word rounded-control bg-foreground px-3 py-2 text-xs font-medium text-background";
|
|
170
|
+
/**
|
|
171
|
+
* O corpo animado do tooltip em `on`. O Radix entrega ao filho (asChild) o `data-state`, e é por
|
|
172
|
+
* ele que se sabe se o tooltip abriu "instantâneo" (`instant-open`: o usuário já estava com outro
|
|
173
|
+
* aberto, ou foi o foco do teclado). Nesse caso não anima: depois do primeiro, os outros abrem sem
|
|
174
|
+
* atraso e sem animação, e a barra inteira parece mais rápida (W7).
|
|
175
|
+
*/
|
|
176
|
+
var TooltipBody = forwardRef(function TooltipBody(props, ref) {
|
|
177
|
+
const presets = useMotionPresets();
|
|
178
|
+
const instant = props["data-state"] === "instant-open";
|
|
179
|
+
return /* @__PURE__ */ jsx(m.div, {
|
|
180
|
+
ref,
|
|
181
|
+
...props,
|
|
182
|
+
...presets.tooltip(instant)
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
function Tooltip$1({ content, children, side = "top", disabled }) {
|
|
186
|
+
const motion = useMotionMode();
|
|
187
|
+
const [open, setOpen] = useState(false);
|
|
188
|
+
if (disabled) return /* @__PURE__ */ jsx(Fragment$1, { children });
|
|
189
|
+
if (motion === "on") return /* @__PURE__ */ jsxs(Tooltip.Root, {
|
|
190
|
+
open,
|
|
191
|
+
onOpenChange: setOpen,
|
|
192
|
+
children: [/* @__PURE__ */ jsx(Tooltip.Trigger, {
|
|
193
|
+
asChild: true,
|
|
194
|
+
children
|
|
195
|
+
}), /* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsx(Tooltip.Portal, {
|
|
196
|
+
forceMount: true,
|
|
197
|
+
children: /* @__PURE__ */ jsx(Tooltip.Content, {
|
|
198
|
+
forceMount: true,
|
|
199
|
+
asChild: true,
|
|
200
|
+
side,
|
|
201
|
+
sideOffset: 8,
|
|
202
|
+
collisionPadding: 16,
|
|
203
|
+
"data-rendra": "TIP-001",
|
|
204
|
+
className: contentCls,
|
|
205
|
+
children: /* @__PURE__ */ jsx(TooltipBody, { children: content })
|
|
206
|
+
})
|
|
207
|
+
}, "tooltip") })]
|
|
208
|
+
});
|
|
209
|
+
return /* @__PURE__ */ jsxs(Tooltip.Root, { children: [/* @__PURE__ */ jsx(Tooltip.Trigger, {
|
|
210
|
+
asChild: true,
|
|
211
|
+
children
|
|
212
|
+
}), /* @__PURE__ */ jsx(Tooltip.Portal, { children: /* @__PURE__ */ jsx(Tooltip.Content, {
|
|
213
|
+
side,
|
|
214
|
+
sideOffset: 8,
|
|
215
|
+
collisionPadding: 16,
|
|
216
|
+
"data-rendra": "TIP-001",
|
|
217
|
+
className: cn(contentCls, "animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:duration-(--rendra-duration-fast) data-[state=closed]:fade-out-0 data-[state=instant-open]:animate-none"),
|
|
218
|
+
children: content
|
|
219
|
+
}) })] });
|
|
220
|
+
}
|
|
221
|
+
//#endregion
|
|
222
|
+
export { DropdownMenuContent as a, DropdownMenuLabel as c, DropdownMenuSeparator as d, DropdownMenuSub as f, DropdownMenuTrigger as h, DropdownMenuCheckboxItem as i, DropdownMenuRadioGroup as l, DropdownMenuSubTrigger as m, TooltipProvider as n, DropdownMenuGroup as o, DropdownMenuSubContent as p, DropdownMenu$1 as r, DropdownMenuItem as s, Tooltip$1 as t, DropdownMenuRadioItem as u };
|
|
223
|
+
|
|
224
|
+
//# sourceMappingURL=tooltip-BAMSaGbS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tooltip-BAMSaGbS.js","names":[],"sources":["../src/components/ui/dropdown-menu.tsx","../src/components/ui/tooltip.tsx"],"sourcesContent":["import { Check, ChevronRight } from 'lucide-react'\nimport { AnimatePresence, m } from 'motion/react'\nimport { DropdownMenu as D } from 'radix-ui'\nimport { createContext, useContext, useState, type ComponentProps } from 'react'\nimport { cn } from '@/lib/cn'\nimport { useMotionMode, useMotionPresets } from '@/lib/motion'\n\n/*\n * Em `on` o menu e o submenu precisam saber se estão abertos para manter o conteúdo montado\n * durante a saída animada. `Root` e `Sub` viram wrappers com exatamente os mesmos tipos do\n * Radix que espelham o estado (controlado ou não) num contexto; em `off` são o `D.Root` e o\n * `D.Sub` de sempre. O estado do submenu vive no próprio `D.Sub`, por isso o wrapper dele.\n */\nconst MenuOpenContext = createContext<boolean | null>(null)\nconst SubOpenContext = createContext<boolean | null>(null)\n\nfunction MirroredRoot({ open, defaultOpen, onOpenChange, ...rest }: ComponentProps<typeof D.Root>) {\n const [inner, setInner] = useState(defaultOpen ?? false)\n const current = open ?? inner\n return (\n <MenuOpenContext.Provider value={current}>\n <D.Root\n {...rest}\n open={current}\n onOpenChange={(next) => {\n setInner(next)\n onOpenChange?.(next)\n }}\n />\n </MenuOpenContext.Provider>\n )\n}\n\nfunction MirroredSub({ open, defaultOpen, onOpenChange, ...rest }: ComponentProps<typeof D.Sub>) {\n const [inner, setInner] = useState(defaultOpen ?? false)\n const current = open ?? inner\n return (\n <SubOpenContext.Provider value={current}>\n <D.Sub\n {...rest}\n open={current}\n onOpenChange={(next) => {\n setInner(next)\n onOpenChange?.(next)\n }}\n />\n </SubOpenContext.Provider>\n )\n}\n\nexport function DropdownMenu(props: ComponentProps<typeof D.Root>) {\n return useMotionMode() === 'on' ? <MirroredRoot {...props} /> : <D.Root {...props} />\n}\nexport const DropdownMenuTrigger = D.Trigger\nexport const DropdownMenuGroup = D.Group\nexport function DropdownMenuSub(props: ComponentProps<typeof D.Sub>) {\n return useMotionMode() === 'on' ? <MirroredSub {...props} /> : <D.Sub {...props} />\n}\nexport const DropdownMenuRadioGroup = D.RadioGroup\n\n// O menu e o submenu nascem do gatilho (W6); a saída é mais curta que a entrada (W5).\nconst panelBase =\n 'z-50 w-max min-w-3xs max-w-popover origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-surface border bg-popover p-1 text-popover-foreground shadow-md'\nconst panelOff = cn(\n panelBase,\n 'animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:duration-(--rendra-duration-fast) data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95',\n)\n\n// Itens com 44px no mobile (toque) e compactos a partir de md.\nconst item =\n 'relative flex min-h-touch cursor-pointer items-center gap-2 rounded-item px-3 text-sm outline-none select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-highlighted:bg-accent data-highlighted:text-accent-foreground md:min-h-0 md:py-2 [&_svg]:size-icon-sm [&_svg]:shrink-0 [&_svg]:text-muted-foreground'\n\nexport function DropdownMenuContent({\n className,\n sideOffset = 8,\n children,\n asChild,\n ...props\n}: ComponentProps<typeof D.Content>) {\n const open = useContext(MenuOpenContext)\n const motion = useMotionMode()\n const presets = useMotionPresets()\n\n if (motion === 'on' && open !== null && !asChild) {\n return (\n <AnimatePresence>\n {open && (\n <D.Portal forceMount key=\"menu\">\n <D.Content\n forceMount\n asChild\n sideOffset={sideOffset}\n collisionPadding={16}\n data-rendra=\"DDM-001\"\n className={cn(panelBase, className)}\n {...props}\n >\n <m.div {...presets.open()}>{children}</m.div>\n </D.Content>\n </D.Portal>\n )}\n </AnimatePresence>\n )\n }\n\n return (\n <D.Portal>\n <D.Content\n sideOffset={sideOffset}\n collisionPadding={16}\n data-rendra=\"DDM-001\"\n className={cn(panelOff, className)}\n asChild={asChild}\n {...props}\n >\n {children}\n </D.Content>\n </D.Portal>\n )\n}\n\ninterface ItemProps extends ComponentProps<typeof D.Item> {\n /** Item destrutivo (excluir, sair): texto na cor destrutiva. */\n destructive?: boolean\n}\n\nexport function DropdownMenuItem({ className, destructive, ...props }: ItemProps) {\n return (\n <D.Item\n className={cn(\n item,\n destructive &&\n 'text-destructive data-highlighted:bg-destructive-soft data-highlighted:text-destructive-soft-foreground [&_svg]:text-current',\n className,\n )}\n {...props}\n />\n )\n}\n\nexport function DropdownMenuCheckboxItem({\n className,\n children,\n ...props\n}: ComponentProps<typeof D.CheckboxItem>) {\n return (\n <D.CheckboxItem className={cn(item, 'pl-8', className)} {...props}>\n <span className=\"absolute left-2 flex size-icon-sm items-center justify-center\">\n <D.ItemIndicator>\n <Check className=\"text-primary-text\" />\n </D.ItemIndicator>\n </span>\n {children}\n </D.CheckboxItem>\n )\n}\n\nexport function DropdownMenuRadioItem({\n className,\n children,\n ...props\n}: ComponentProps<typeof D.RadioItem>) {\n return (\n <D.RadioItem className={cn(item, 'pl-8', className)} {...props}>\n <span className=\"absolute left-2 flex size-icon-sm items-center justify-center\">\n <D.ItemIndicator>\n <Check className=\"text-primary-text\" />\n </D.ItemIndicator>\n </span>\n {children}\n </D.RadioItem>\n )\n}\n\nexport function DropdownMenuLabel({ className, ...props }: ComponentProps<typeof D.Label>) {\n return (\n <D.Label\n className={cn('px-2 py-2 text-xs font-medium text-muted-foreground', className)}\n {...props}\n />\n )\n}\n\nexport function DropdownMenuSeparator({ className, ...props }: ComponentProps<typeof D.Separator>) {\n return <D.Separator className={cn('-mx-1 my-1 h-px bg-border', className)} {...props} />\n}\n\nexport function DropdownMenuSubTrigger({\n className,\n children,\n ...props\n}: ComponentProps<typeof D.SubTrigger>) {\n return (\n <D.SubTrigger className={cn(item, 'data-[state=open]:bg-accent', className)} {...props}>\n {children}\n <ChevronRight className=\"ml-auto\" />\n </D.SubTrigger>\n )\n}\n\nexport function DropdownMenuSubContent({\n className,\n children,\n asChild,\n ...props\n}: ComponentProps<typeof D.SubContent>) {\n const open = useContext(SubOpenContext)\n const motion = useMotionMode()\n const presets = useMotionPresets()\n\n if (motion === 'on' && open !== null && !asChild) {\n return (\n <AnimatePresence>\n {open && (\n <D.Portal forceMount key=\"submenu\">\n <D.SubContent\n forceMount\n asChild\n collisionPadding={16}\n className={cn(panelBase, className)}\n {...props}\n >\n <m.div {...presets.open()}>{children}</m.div>\n </D.SubContent>\n </D.Portal>\n )}\n </AnimatePresence>\n )\n }\n\n return (\n <D.Portal>\n <D.SubContent\n collisionPadding={16}\n className={cn(panelOff, className)}\n asChild={asChild}\n {...props}\n >\n {children}\n </D.SubContent>\n </D.Portal>\n )\n}\n","import { AnimatePresence, m } from 'motion/react'\nimport { Tooltip as T } from 'radix-ui'\nimport { forwardRef, useState, type ComponentPropsWithoutRef, type ReactNode } from 'react'\nimport { cn } from '@/lib/cn'\nimport { useMotionMode, useMotionPresets } from '@/lib/motion'\n\n/**\n * Tooltip: só para informação complementar, nunca essencial (não existe hover no toque).\n * Informação essencial vai em texto de ajuda visível ou em Popover acionado por toque.\n */\nexport function TooltipProvider({ children }: { children: ReactNode }) {\n return (\n <T.Provider delayDuration={300} skipDelayDuration={150}>\n {children}\n </T.Provider>\n )\n}\n\ninterface TooltipProps {\n content: ReactNode\n children: ReactNode\n side?: 'top' | 'right' | 'bottom' | 'left'\n /** Desliga o tooltip sem mudar a árvore (ex.: sidebar expandida já mostra o rótulo). */\n disabled?: boolean\n}\n\n// O tooltip nasce do gatilho (W6). A origem vem do Radix.\nconst contentCls =\n 'z-50 max-w-xs origin-(--radix-tooltip-content-transform-origin) wrap-break-word rounded-control bg-foreground px-3 py-2 text-xs font-medium text-background'\n\n/**\n * O corpo animado do tooltip em `on`. O Radix entrega ao filho (asChild) o `data-state`, e é por\n * ele que se sabe se o tooltip abriu \"instantâneo\" (`instant-open`: o usuário já estava com outro\n * aberto, ou foi o foco do teclado). Nesse caso não anima: depois do primeiro, os outros abrem sem\n * atraso e sem animação, e a barra inteira parece mais rápida (W7).\n */\nconst TooltipBody = forwardRef<HTMLDivElement, ComponentPropsWithoutRef<typeof m.div>>(\n function TooltipBody(props, ref) {\n const presets = useMotionPresets()\n const instant = (props as { 'data-state'?: string })['data-state'] === 'instant-open'\n return <m.div ref={ref} {...props} {...presets.tooltip(instant)} />\n },\n)\n\nexport function Tooltip({ content, children, side = 'top', disabled }: TooltipProps) {\n const motion = useMotionMode()\n // Só em `on`: o estado aberto fica aqui para o conteúdo continuar montado durante a saída.\n // O Radix segue dono do atraso: `onOpenChange` só dispara depois do `delayDuration`.\n const [open, setOpen] = useState(false)\n if (disabled) return <>{children}</>\n if (motion === 'on') {\n return (\n <T.Root open={open} onOpenChange={setOpen}>\n <T.Trigger asChild>{children}</T.Trigger>\n <AnimatePresence>\n {open && (\n <T.Portal forceMount key=\"tooltip\">\n <T.Content\n forceMount\n asChild\n side={side}\n sideOffset={8}\n collisionPadding={16}\n data-rendra=\"TIP-001\"\n className={contentCls}\n >\n <TooltipBody>{content}</TooltipBody>\n </T.Content>\n </T.Portal>\n )}\n </AnimatePresence>\n </T.Root>\n )\n }\n return (\n <T.Root>\n <T.Trigger asChild>{children}</T.Trigger>\n <T.Portal>\n <T.Content\n side={side}\n sideOffset={8}\n collisionPadding={16}\n data-rendra=\"TIP-001\"\n className={cn(\n contentCls,\n // `instant-open` não anima; a saída é mais curta que a entrada (W5, W7).\n 'animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:duration-(--rendra-duration-fast) data-[state=closed]:fade-out-0 data-[state=instant-open]:animate-none',\n )}\n >\n {content}\n </T.Content>\n </T.Portal>\n </T.Root>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ComponentType, type ReactNode } from 'react';
|
|
2
|
+
import { type MotionMode } from '../lib/motion/motion-context';
|
|
2
3
|
/**
|
|
3
4
|
* Link com a mesma interface do `<a>`/`Link`: recebe `to`, `className`, `children`,
|
|
4
5
|
* `aria-*`, `onClick` e repassa o resto.
|
|
@@ -28,13 +29,18 @@ export interface RendraProviderProps {
|
|
|
28
29
|
goBack: () => void;
|
|
29
30
|
/** Trilha da rota atual (ex.: via `useMatches` e `handle.crumb`). Opcional. */
|
|
30
31
|
useBreadcrumbs?: () => RendraBreadcrumbItem[];
|
|
32
|
+
/**
|
|
33
|
+
* Animações dos componentes. `off` (padrão): sem nenhuma animação do Motion, a árvore e o
|
|
34
|
+
* comportamento de sempre. `on`: entradas, saídas e layout animados pelo Motion.
|
|
35
|
+
*/
|
|
36
|
+
motion?: MotionMode;
|
|
31
37
|
}
|
|
32
38
|
/**
|
|
33
39
|
* Única peça que sabe como navegar (`react-router`, outro roteador, ou nenhum).
|
|
34
40
|
* Sem `RendraProvider` na árvore, os hooks abaixo caem para um comportamento simples,
|
|
35
41
|
* baseado só em `window.location`/`history`, e os componentes continuam funcionando.
|
|
36
42
|
*/
|
|
37
|
-
export declare function RendraProvider({ children, linkComponent, useCurrentPath: useCurrentPathProp, navigate, goBack, useBreadcrumbs, }: RendraProviderProps): import("react").JSX.Element;
|
|
43
|
+
export declare function RendraProvider({ children, linkComponent, useCurrentPath: useCurrentPathProp, navigate, goBack, useBreadcrumbs, motion, }: RendraProviderProps): import("react").JSX.Element;
|
|
38
44
|
/** Componente de link do provider ativo (ou `<a href>`, sem provider). */
|
|
39
45
|
export declare function useRendraLink(): ComponentType<RendraLinkProps>;
|
|
40
46
|
/** Caminho atual (ex.: `/clientes/novo`), do provider ativo ou de `window.location`. */
|