@rendra-ui/web 2.5.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -2
- package/dist/base.css +1 -1
- package/dist/{button-BzJgR2gH.js → button-B6-644xP.js} +7 -7
- package/dist/button-B6-644xP.js.map +1 -0
- package/dist/chart.js +15 -13
- 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-Cw7M5kEP.js → cn-TBlI6-gS.js} +2 -2
- package/dist/{cn-Cw7M5kEP.js.map → cn-TBlI6-gS.js.map} +1 -1
- package/dist/{components-DkpspH9h.js → components-Btk1cUg2.js} +2 -2
- package/dist/{components-DkpspH9h.js.map → components-Btk1cUg2.js.map} +1 -1
- package/dist/components.css +1 -1
- package/dist/document-viewer.js +4 -4
- package/dist/{empty-state-Cdb1vkMT.js → empty-state-DrQjqxvp.js} +11 -11
- package/dist/{empty-state-Cdb1vkMT.js.map → empty-state-DrQjqxvp.js.map} +1 -1
- package/dist/{features-max--5VEt6M7.js → features-max-CC6CorTg.js} +1 -1
- package/dist/index.js +90 -77
- package/dist/index.js.map +1 -1
- package/dist/motion-context-BL545cb6.js +222 -0
- package/dist/motion-context-BL545cb6.js.map +1 -0
- package/dist/motion-on-DMoTsWrG.js +29 -0
- package/dist/motion-on-DMoTsWrG.js.map +1 -0
- package/dist/motion.js +3 -0
- package/dist/{rendra-provider-CRe0XdOU.js → rendra-provider-CeCkPafT.js} +3 -3
- package/dist/rendra-provider-CeCkPafT.js.map +1 -0
- package/dist/rich-text-editor.js +3 -3
- package/dist/router-bridge.js +2 -2
- package/dist/router-bridge.js.map +1 -1
- package/dist/tokens.css +1 -1
- package/dist/{tooltip-BAMSaGbS.js → tooltip-kgsorOg6.js} +15 -15
- package/dist/tooltip-kgsorOg6.js.map +1 -0
- package/dist/types/components/rendra-provider.d.ts +7 -2
- package/dist/types/components/rendra-router-bridge.d.ts +2 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/lib/motion/index.d.ts +1 -1
- package/dist/types/lib/motion/motion-context.d.ts +21 -6
- package/dist/types/lib/motion/motion-on.d.ts +12 -0
- package/dist/types/motion.d.ts +1 -0
- package/dist/{use-breakpoint-O9eqFmsF.js → use-breakpoint-CNxDwEpc.js} +2 -2
- package/dist/{use-breakpoint-O9eqFmsF.js.map → use-breakpoint-CNxDwEpc.js.map} +1 -1
- package/dist/{use-motion-presets-BrkgL8lG.js → use-motion-presets-DCJPBfNJ.js} +3 -3
- package/dist/{use-motion-presets-BrkgL8lG.js.map → use-motion-presets-DCJPBfNJ.js.map} +1 -1
- package/dist/widget-grid.js +2 -2
- package/package.json +8 -1
- package/dist/button-BzJgR2gH.js.map +0 -1
- package/dist/motion-context-5BRIQAJm.js +0 -107
- package/dist/motion-context-5BRIQAJm.js.map +0 -1
- package/dist/rendra-provider-CRe0XdOU.js.map +0 -1
- package/dist/tooltip-BAMSaGbS.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! Rendra Design System v2.
|
|
1
|
+
/*! Rendra Design System v2.6.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
|
|
2
2
|
import { useSyncExternalStore } from "react";
|
|
3
3
|
//#region src/hooks/use-breakpoint.ts
|
|
4
4
|
/**
|
|
@@ -46,4 +46,4 @@ function useBreakpoint() {
|
|
|
46
46
|
//#endregion
|
|
47
47
|
export { useBreakpoint as n, breakpoints as t };
|
|
48
48
|
|
|
49
|
-
//# sourceMappingURL=use-breakpoint-
|
|
49
|
+
//# sourceMappingURL=use-breakpoint-CNxDwEpc.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-breakpoint-
|
|
1
|
+
{"version":3,"file":"use-breakpoint-CNxDwEpc.js","names":[],"sources":["../src/hooks/use-breakpoint.ts"],"sourcesContent":["import { useSyncExternalStore } from 'react'\n\n/**\n * Pontos de quebra, espelhando os padrões do Tailwind (sm 40rem, md 48rem, lg 64rem...).\n * Único hook de detecção de tela do sistema. Para adaptação ao espaço disponível\n * dentro de um bloco (e não à tela), use container queries (@container) no CSS.\n */\nexport const breakpoints = { sm: 640, md: 768, lg: 1024, xl: 1280, '2xl': 1536 } as const\nexport type Breakpoint = keyof typeof breakpoints\n\nconst order: Breakpoint[] = ['sm', 'md', 'lg', 'xl', '2xl']\n\nfunction subscribe(cb: () => void) {\n const lists = order.map((bp) => matchMedia(`(min-width: ${breakpoints[bp]}px)`))\n lists.forEach((mq) => mq.addEventListener('change', cb))\n return () => lists.forEach((mq) => mq.removeEventListener('change', cb))\n}\n\nfunction getCurrent(): Breakpoint | 'base' {\n let current: Breakpoint | 'base' = 'base'\n for (const bp of order) if (matchMedia(`(min-width: ${breakpoints[bp]}px)`).matches) current = bp\n return current\n}\n\nexport function useBreakpoint() {\n const current = useSyncExternalStore(subscribe, getCurrent, () => 'lg' as const)\n const rank = current === 'base' ? -1 : order.indexOf(current)\n const up = (bp: Breakpoint) => rank >= order.indexOf(bp)\n return {\n current,\n up,\n /** Abaixo de 768px: componentes se reconstroem no formato mobile. */\n isMobile: !up('md'),\n isTablet: up('md') && !up('lg'),\n isDesktop: up('lg'),\n }\n}\n"],"mappings":";;;;;;;;AAOA,IAAa,cAAc;CAAE,IAAI;CAAK,IAAI;CAAK,IAAI;CAAM,IAAI;CAAM,OAAO;AAAK;AAG/E,IAAM,QAAsB;CAAC;CAAM;CAAM;CAAM;CAAM;AAAK;AAE1D,SAAS,UAAU,IAAgB;CACjC,MAAM,QAAQ,MAAM,KAAK,OAAO,WAAW,eAAe,YAAY,IAAI,IAAI,CAAC;CAC/E,MAAM,SAAS,OAAO,GAAG,iBAAiB,UAAU,EAAE,CAAC;CACvD,aAAa,MAAM,SAAS,OAAO,GAAG,oBAAoB,UAAU,EAAE,CAAC;AACzE;AAEA,SAAS,aAAkC;CACzC,IAAI,UAA+B;CACnC,KAAK,MAAM,MAAM,OAAO,IAAI,WAAW,eAAe,YAAY,IAAI,IAAI,CAAC,CAAC,SAAS,UAAU;CAC/F,OAAO;AACT;AAEA,SAAgB,gBAAgB;CAC9B,MAAM,UAAU,qBAAqB,WAAW,kBAAkB,IAAa;CAC/E,MAAM,OAAO,YAAY,SAAS,KAAK,MAAM,QAAQ,OAAO;CAC5D,MAAM,MAAM,OAAmB,QAAQ,MAAM,QAAQ,EAAE;CACvD,OAAO;EACL;EACA;;EAEA,UAAU,CAAC,GAAG,IAAI;EAClB,UAAU,GAAG,IAAI,KAAK,CAAC,GAAG,IAAI;EAC9B,WAAW,GAAG,IAAI;CACpB;AACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/*! Rendra Design System v2.
|
|
2
|
-
import { a as
|
|
1
|
+
/*! Rendra Design System v2.6.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
|
|
2
|
+
import { a as useMotionMode, c as getReducedMotion, l as subscribeReducedMotion } from "./motion-context-BL545cb6.js";
|
|
3
3
|
import { useMemo, useSyncExternalStore } from "react";
|
|
4
4
|
//#region src/lib/motion/tokens.ts
|
|
5
5
|
/**
|
|
@@ -398,4 +398,4 @@ function useMotionPresets() {
|
|
|
398
398
|
//#endregion
|
|
399
399
|
export { toCubicBezier as n, useMotionPresets as t };
|
|
400
400
|
|
|
401
|
-
//# sourceMappingURL=use-motion-presets-
|
|
401
|
+
//# sourceMappingURL=use-motion-presets-DCJPBfNJ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-motion-presets-BrkgL8lG.js","names":[],"sources":["../src/lib/motion/tokens.ts","../src/lib/motion/presets.ts","../src/lib/motion/use-motion-presets.ts"],"sourcesContent":["/*\n * Durações e curvas do motion (linguagem única, web e app). A fonte é o globals.css:\n * --rendra-duration-* bloco :root fora de camada (vai para o dist/tokens.css do pacote);\n * --rendra-ease-* no mesmo bloco, então o host as sobrescreve; o @theme guarda os nomes\n * do Tailwind (--ease-out, --ease-move...) como alias delas.\n * As constantes daqui são a reserva em tempo de execução (SSR, variável ausente ou inválida), e\n * tokens.test.ts confere que elas batem com o globals.css. Valores em segundos e vetores de 4\n * números, o formato que o Motion aceita.\n */\n\nexport type Bezier = [number, number, number, number]\n\n/**\n * Reserva das durações, em segundos (SSR, ou variável ausente).\n * `press` e `fast` valem o mesmo (120 ms) com propósitos diferentes: o toque e a saída de overlay.\n */\nexport const DURATION = {\n press: 0.12,\n hover: 0.15,\n fast: 0.12,\n base: 0.2,\n move: 0.25,\n slow: 0.32,\n draw: 0.42,\n pulse: 1,\n}\nexport type DurationName = keyof typeof DURATION\n\n/**\n * Reveal: entrada de uso único (dashboard: bloco, cascata, contador e desenho do gráfico), mais\n * lenta que as interações do dia a dia. Reserva em segundos (SSR, ou variável ausente).\n */\nexport const REVEAL = { enter: 0.6, stagger: 0.12, count: 1.2, draw: 0.9 }\nexport type RevealName = keyof typeof REVEAL\n\n/**\n * Curvas do globals.css (`--rendra-ease-*`). `spring` é a curva \"back\" (quique): só para a cota\n * rara de encanto. `move` desloca na tela; `drawer` é a curva de gaveta e folha.\n */\nexport const EASE: Record<'out' | 'inOut' | 'spring' | 'move' | 'drawer', Bezier> = {\n out: [0.22, 1, 0.36, 1],\n inOut: [0.65, 0, 0.35, 1],\n spring: [0.34, 1.56, 0.64, 1],\n move: [0.77, 0, 0.175, 1],\n drawer: [0.32, 0.72, 0, 1],\n}\nexport type EaseName = keyof typeof EASE\n\n/** Nome da variável CSS de cada curva (`inOut` vira `in-out`). */\nconst EASE_VAR: Record<EaseName, string> = {\n out: 'out',\n inOut: 'in-out',\n spring: 'spring',\n move: 'move',\n drawer: 'drawer',\n}\n\n/**\n * Molas no formato \"duração e quique\" (Motion). `settle` assenta sem passar do ponto (layout,\n * overlay que entra, soltura do arraste); `sheet` é a folha depois do gesto, com quique mínimo.\n * Mola não é variável CSS: mora aqui, e o app a espelha em `dampingRatio`.\n */\nexport const SPRING = {\n settle: { duration: 0.4, bounce: 0 },\n sheet: { duration: 0.3, bounce: 0.2 },\n}\n\n/** Escalas da linguagem: entrada de overlay, tooltip, ponto pequeno, toque, pop e salto curto. */\nexport const SCALE = { enter: 0.95, tooltip: 0.97, small: 0.9, press: 0.97, pop: 0.8, bump: 1.08 }\n\n/** Desfoque (px) que disfarça o cruzamento entre dois estados (troca de passo). Abaixo de 20. */\nexport const BLUR = 2\n\nexport interface MotionTokens {\n duration: Record<DurationName, number>\n reveal: Record<RevealName, number>\n ease: Record<EaseName, Bezier>\n}\n\nfunction toSeconds(value: string): number | null {\n const v = value.trim()\n const n = parseFloat(v)\n if (!Number.isFinite(n)) return null\n if (v.endsWith('ms')) return n / 1000\n if (v.endsWith('s')) return n\n return null\n}\n\n/** `cubic-bezier(a, b, c, d)` em vetor; qualquer outra coisa (`ease-in`, vazio) vira `null`. */\nfunction toBezier(value: string): Bezier | null {\n const m = /^cubic-bezier\\(([^)]+)\\)$/.exec(value.trim())\n if (!m) return null\n const parts = m[1]!.split(',').map((n) => parseFloat(n))\n if (parts.length !== 4 || parts.some((n) => !Number.isFinite(n))) return null\n return parts as Bezier\n}\n\n/** Lê as durações e as curvas do documento; o que faltar (ou sem window) vem da reserva. */\nexport function readMotionTokens(): MotionTokens {\n const duration = { ...DURATION }\n const reveal = { ...REVEAL }\n const ease = { ...EASE }\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n const style = getComputedStyle(document.documentElement)\n for (const name of Object.keys(DURATION) as DurationName[]) {\n const read = toSeconds(style.getPropertyValue(`--rendra-duration-${name}`))\n if (read !== null) duration[name] = read\n }\n for (const name of Object.keys(REVEAL) as RevealName[]) {\n const read = toSeconds(style.getPropertyValue(`--rendra-reveal-${name}`))\n if (read !== null) reveal[name] = read\n }\n for (const name of Object.keys(EASE) as EaseName[]) {\n const read = toBezier(style.getPropertyValue(`--rendra-ease-${EASE_VAR[name]}`))\n if (read !== null) ease[name] = read\n }\n }\n return { duration, reveal, ease }\n}\n","import type { Target, TargetAndTransition, Transition } from 'motion/react'\nimport { BLUR, readMotionTokens, SCALE, SPRING, type Bezier, type MotionTokens } from './tokens'\n\n/*\n * Presets do caminho `on` (linguagem única de movimento): fade, scale/open, sheet, tooltip,\n * indicator, pop, slide, reveal, press, move, settle e stagger. Toda duração e toda curva vêm de\n * readMotionTokens (globals.css); nenhum número de duração mora neste arquivo (o presets.test.ts\n * varre o código-fonte atrás de literal). As molas e as escalas vêm de tokens.ts.\n *\n * Duas regras moram aqui:\n * - Assimetria: o que o usuário decidiu (abrir) entra no tempo `base`, e o que o sistema\n * responde ao fechar sai em `fast`, só em opacidade. Gaveta e folha saem em `base`, de volta\n * pelo lado de onde vieram.\n * - Reduzido: sem deslocamento, escala, filtro nem cascata; a opacidade usa `base` (não zero),\n * porque o esmaecimento é o que explica a mudança de estado.\n */\n\nexport interface MotionPreset {\n initial: Target\n animate: TargetAndTransition\n exit: TargetAndTransition\n transition: Transition\n}\n\n/** Toque: o alvo do `whileTap` (`undefined` no reduzido) e a transição de ida e de volta. */\nexport interface PressPreset {\n whileTap: TargetAndTransition | undefined\n transition: Transition\n}\n\nexport type SlideFrom = 'left' | 'right' | 'top' | 'bottom'\n\n/** Distância do slide: `full` (painel que entra da borda) ou `short` (conteúdo que assenta). */\nexport type SlideDistance = 'full' | 'short'\n\nconst SHORT_PX = 8\n\nexport interface Presets {\n reduced: boolean\n /** Toque do botão, do polegar e dos controles: 120 ms, `ease.out`, escala 0,97. */\n press: PressPreset\n /** Alias de `press.whileTap`, o nome antigo. Sem movimento reduzido vem `undefined`. */\n tap: TargetAndTransition | undefined\n /**\n * Salto curto de escala (célula do OTP), com a transição dentro do alvo. Estável entre\n * renders; `undefined` se reduzido.\n */\n bump: TargetAndTransition | undefined\n tokens: MotionTokens\n fade: MotionPreset\n /** Alias de `open()`: escala 0,95 com mola a partir da origem, saída rápida só em opacidade. */\n scale: MotionPreset\n /**\n * Cota rara de encanto (check do passo concluído): 0,8 -> 1 com a curva back, em `slow`. Nunca\n * em controle de uso frequente.\n */\n pop: MotionPreset\n /**\n * Indicador de controle frequente (check do Checkbox, ponto do Radio): 0,9 -> 1 com opacidade\n * em `fast`, sem quique e sem partir de zero.\n */\n indicator: MotionPreset\n slide: (from: SlideFrom, distance?: SlideDistance) => MotionPreset\n /**\n * Overlay ancorado (popover, menu, modal, painel do select). Número = escala de partida\n * (padrão 0,95); `{ y }` = entrada plana, sem escala, para a superfície em tela cheia.\n * Entra em mola criticamente amortecida (sem quique) em `base` e sai em `fast`, em opacidade.\n */\n open: (from?: number | { y: number }) => MotionPreset\n /** Gaveta e folha: entram de `from` em `slow` com `ease.drawer`, saem em `fast` pelo mesmo lado. */\n sheet: (from: SlideFrom) => MotionPreset\n /** Tooltip: escala 0,97 em `fast`; aberto em `instant-open` não anima. */\n tooltip: (instant: boolean) => MotionPreset\n /**\n * Troca de conteúdo no lugar (passo do wizard), sem esperar a saída: o que sai esmaece com\n * `blur` de 2 px em `fast`; o que entra vem de `direction` (1 avança, -1 volta), 8 px, em\n * `base`. O desfoque disfarça o cruzamento: sem ele o olho vê dois objetos trocando de lugar.\n */\n swap: (direction: 1 | -1) => MotionPreset\n /**\n * Entrada de uso único (reveal do dashboard): desloca 8 px e dura `reveal.enter`, mais lenta\n * que `slide`. Não serve a interação repetida (overlay, tab, botão).\n */\n reveal: (from: SlideFrom) => MotionPreset\n /** Deslocamento na tela (indicador, reordenação): `move` em `ease.move`. */\n move: Transition\n /** Nome antigo de `move`. */\n layout: Transition\n /** Mola sem quique: onde há gesto ou soltura (drop do kanban, folha que volta). */\n settle: Transition\n /** Mola da folha depois do arraste (quique mínimo). */\n springSheet: Transition\n /**\n * A mesma mola da folha em rigidez e amortecimento (massa 1), que é o que o arraste do Motion\n * (`dragTransition`) pede para a volta à origem: rigidez = (2π / duração)², amortecimento =\n * 2 (1 - quique) raiz(rigidez).\n */\n sheetBounce: { bounceStiffness: number; bounceDamping: number }\n /** Atraso de entrada do item `index`, limitado a `limit` itens (padrão 8: 480 ms). */\n stagger: (index: number, limit?: number) => Transition\n /** Atraso do bloco `index` no reveal (passo `reveal.stagger`), limitado a `limit` blocos. */\n staggerReveal: (index: number, limit?: number) => Transition\n}\n\n/** Mola em \"duração e quique\" para rigidez e amortecimento (massa 1). */\nfunction springToBounce({ duration, bounce }: { duration: number; bounce: number }) {\n const stiffness = ((2 * Math.PI) / duration) ** 2\n return {\n bounceStiffness: Math.round(stiffness),\n bounceDamping: Math.round(2 * (1 - bounce) * Math.sqrt(stiffness)),\n }\n}\n\nexport function createPresets(tokens: MotionTokens, reduced: boolean): Presets {\n const { duration, reveal, ease } = tokens\n const base: Transition = { duration: duration.base, ease: ease.out }\n const fastOut: Transition = { duration: duration.fast, ease: ease.out }\n const settle: Transition = { type: 'spring', ...SPRING.settle }\n const enter: Transition = {\n type: 'spring',\n duration: duration.base,\n bounce: SPRING.settle.bounce,\n }\n\n /** O que sobra sob \"reduzir movimento\": só opacidade, em `base`. */\n const flat = (): MotionPreset => ({\n initial: { opacity: 0 },\n animate: { opacity: 1 },\n exit: { opacity: 0 },\n transition: base,\n })\n const make = (initial: Target, animate: Target, time: number, curve = ease.out): MotionPreset =>\n reduced\n ? flat()\n : {\n initial,\n animate,\n exit: initial,\n transition: { duration: time, ease: curve },\n }\n\n const offset = (from: SlideFrom, distance: SlideDistance): Target => {\n const far = distance === 'full' ? '100%' : SHORT_PX\n const sign = from === 'left' || from === 'top' ? -1 : 1\n const value = typeof far === 'string' ? `${sign * 100}%` : sign * far\n return from === 'left' || from === 'right' ? { x: value, opacity: 0 } : { y: value, opacity: 0 }\n }\n const settled = (initial: Target): Target => ({\n opacity: 1,\n ...(initial.x !== undefined ? { x: 0 } : {}),\n ...(initial.y !== undefined ? { y: 0 } : {}),\n })\n\n const fade: MotionPreset = reduced\n ? flat()\n : {\n initial: { opacity: 0 },\n animate: { opacity: 1 },\n exit: { opacity: 0, transition: fastOut },\n transition: base,\n }\n\n const open = (from: number | { y: number } = SCALE.enter): MotionPreset => {\n if (reduced) return flat()\n const initial: Target =\n typeof from === 'number' ? { opacity: 0, scale: from } : { opacity: 0, y: from.y }\n const to: Target = typeof from === 'number' ? { opacity: 1, scale: 1 } : { opacity: 1, y: 0 }\n return {\n initial,\n animate: { ...to, transition: enter },\n exit: { opacity: 0, transition: fastOut },\n transition: enter,\n }\n }\n\n const sheet = (from: SlideFrom): MotionPreset => {\n if (reduced) return flat()\n const sign = from === 'left' || from === 'top' ? -1 : 1\n const axis = from === 'left' || from === 'right' ? 'x' : 'y'\n const away = { [axis]: `${sign * 100}%` }\n return {\n initial: away,\n animate: { [axis]: 0 },\n exit: { ...away, transition: { duration: duration.fast, ease: ease.drawer } },\n transition: { duration: duration.slow, ease: ease.drawer },\n }\n }\n\n const tooltip = (instant: boolean): MotionPreset => {\n if (reduced) return instant ? { ...flat(), transition: { duration: 0 } } : flat()\n return {\n initial: { opacity: 0, scale: SCALE.tooltip },\n animate: { opacity: 1, scale: 1 },\n exit: { opacity: 0, transition: fastOut },\n transition: instant ? { duration: 0 } : fastOut,\n }\n }\n\n const blurred = `blur(${BLUR}px)`\n const swap = (direction: 1 | -1): MotionPreset => {\n if (reduced) return flat()\n return {\n initial: { opacity: 0, x: direction * SHORT_PX, filter: blurred },\n animate: { opacity: 1, x: 0, filter: 'blur(0px)', transition: base },\n exit: { opacity: 0, filter: blurred, transition: fastOut },\n transition: base,\n }\n }\n\n const indicatorInitial: Target = { opacity: 0, scale: SCALE.small }\n const press: PressPreset = {\n whileTap: reduced ? undefined : { scale: SCALE.press },\n transition: { duration: duration.press, ease: ease.out },\n }\n const move: Transition = reduced ? { duration: 0 } : { duration: duration.move, ease: ease.move }\n\n return {\n reduced,\n press,\n tap: press.whileTap,\n bump: reduced ? undefined : { scale: [SCALE.bump, 1], transition: fastOut },\n tokens,\n fade,\n scale: open(),\n pop: make(\n { opacity: 0, scale: SCALE.pop },\n { opacity: 1, scale: 1 },\n duration.slow,\n ease.spring,\n ),\n indicator: reduced\n ? flat()\n : {\n initial: indicatorInitial,\n animate: { opacity: 1, scale: 1 },\n exit: indicatorInitial,\n transition: fastOut,\n },\n slide: (from, distance = 'full') => {\n const initial = offset(from, distance)\n return make(initial, settled(initial), distance === 'full' ? duration.slow : duration.base)\n },\n open,\n sheet,\n tooltip,\n swap,\n reveal: (from) => {\n const initial = offset(from, 'short')\n return make(initial, settled(initial), reveal.enter)\n },\n move,\n layout: move,\n settle: reduced ? { duration: 0 } : settle,\n springSheet: reduced ? { duration: 0 } : { type: 'spring', ...SPRING.sheet },\n sheetBounce: springToBounce(SPRING.sheet),\n stagger: (index, limit = 8) => ({\n delay: reduced ? 0 : Math.min(index, limit) * (duration.fast / 2),\n }),\n staggerReveal: (index, limit = 8) => ({\n delay: reduced ? 0 : Math.min(index, limit) * reveal.stagger,\n }),\n }\n}\n\n/** Curva no formato do recharts: `cubic-bezier(a,b,c,d)`, sem espaços. */\nexport function toCubicBezier([\n a,\n b,\n c,\n d,\n]: Bezier): `cubic-bezier(${number},${number},${number},${number})` {\n return `cubic-bezier(${a},${b},${c},${d})`\n}\n\n/** Presets com os tokens lidos agora do documento. */\nexport function presetsFromDocument(reduced: boolean): Presets {\n return createPresets(readMotionTokens(), reduced)\n}\n","import { useMemo, useSyncExternalStore } from 'react'\nimport { getReducedMotion, subscribeReducedMotion } from '@/hooks/use-reduced-motion'\nimport { useMotionMode } from './motion-context'\nimport { createPresets, presetsFromDocument, type Presets } from './presets'\nimport { DURATION, EASE, REVEAL } from './tokens'\n\n/** Em `off` ninguém lê o documento nem assina o matchMedia: um objeto único e inerte. */\nconst OFF_PRESETS = createPresets({ duration: DURATION, reveal: REVEAL, ease: EASE }, false)\nconst noSubscribe = () => () => {}\nconst never = () => false\n\n/**\n * Presets do motion para o componente. A preferência \"reduzir movimento\" vem do mesmo\n * `matchMedia` do hook do projeto (`use-reduced-motion.ts`: Spinner, Progress), a fonte única,\n * reativa e testável, sem `MotionConfig reducedMotion` somando por cima. Só em `on` a\n * preferência é assinada e os tokens lidos do documento; em `off` o custo é zero.\n */\nexport function useMotionPresets(): Presets {\n const on = useMotionMode() === 'on'\n const reduced = useSyncExternalStore(\n on ? subscribeReducedMotion : noSubscribe,\n on ? getReducedMotion : never,\n never,\n )\n return useMemo(() => (on ? presetsFromDocument(reduced) : OFF_PRESETS), [on, reduced])\n}\n"],"mappings":";;;;;;;;AAgBA,IAAa,WAAW;CACtB,OAAO;CACP,OAAO;CACP,MAAM;CACN,MAAM;CACN,MAAM;CACN,MAAM;CACN,MAAM;CACN,OAAO;AACT;;;;;AAOA,IAAa,SAAS;CAAE,OAAO;CAAK,SAAS;CAAM,OAAO;CAAK,MAAM;AAAI;;;;;AAOzE,IAAa,OAAuE;CAClF,KAAK;EAAC;EAAM;EAAG;EAAM;CAAC;CACtB,OAAO;EAAC;EAAM;EAAG;EAAM;CAAC;CACxB,QAAQ;EAAC;EAAM;EAAM;EAAM;CAAC;CAC5B,MAAM;EAAC;EAAM;EAAG;EAAO;CAAC;CACxB,QAAQ;EAAC;EAAM;EAAM;EAAG;CAAC;AAC3B;;AAIA,IAAM,WAAqC;CACzC,KAAK;CACL,OAAO;CACP,QAAQ;CACR,MAAM;CACN,QAAQ;AACV;;;;;;AAOA,IAAa,SAAS;CACpB,QAAQ;EAAE,UAAU;EAAK,QAAQ;CAAE;CACnC,OAAO;EAAE,UAAU;EAAK,QAAQ;CAAI;AACtC;;AAGA,IAAa,QAAQ;CAAE,OAAO;CAAM,SAAS;CAAM,OAAO;CAAK,OAAO;CAAM,KAAK;CAAK,MAAM;AAAK;AAWjG,SAAS,UAAU,OAA8B;CAC/C,MAAM,IAAI,MAAM,KAAK;CACrB,MAAM,IAAI,WAAW,CAAC;CACtB,IAAI,CAAC,OAAO,SAAS,CAAC,GAAG,OAAO;CAChC,IAAI,EAAE,SAAS,IAAI,GAAG,OAAO,IAAI;CACjC,IAAI,EAAE,SAAS,GAAG,GAAG,OAAO;CAC5B,OAAO;AACT;;AAGA,SAAS,SAAS,OAA8B;CAC9C,MAAM,IAAI,4BAA4B,KAAK,MAAM,KAAK,CAAC;CACvD,IAAI,CAAC,GAAG,OAAO;CACf,MAAM,QAAQ,EAAE,EAAE,CAAE,MAAM,GAAG,CAAC,CAAC,KAAK,MAAM,WAAW,CAAC,CAAC;CACvD,IAAI,MAAM,WAAW,KAAK,MAAM,MAAM,MAAM,CAAC,OAAO,SAAS,CAAC,CAAC,GAAG,OAAO;CACzE,OAAO;AACT;;AAGA,SAAgB,mBAAiC;CAC/C,MAAM,WAAW,EAAE,GAAG,SAAS;CAC/B,MAAM,SAAS,EAAE,GAAG,OAAO;CAC3B,MAAM,OAAO,EAAE,GAAG,KAAK;CACvB,IAAI,OAAO,WAAW,eAAe,OAAO,aAAa,aAAa;EACpE,MAAM,QAAQ,iBAAiB,SAAS,eAAe;EACvD,KAAK,MAAM,QAAQ,OAAO,KAAK,QAAQ,GAAqB;GAC1D,MAAM,OAAO,UAAU,MAAM,iBAAiB,qBAAqB,MAAM,CAAC;GAC1E,IAAI,SAAS,MAAM,SAAS,QAAQ;EACtC;EACA,KAAK,MAAM,QAAQ,OAAO,KAAK,MAAM,GAAmB;GACtD,MAAM,OAAO,UAAU,MAAM,iBAAiB,mBAAmB,MAAM,CAAC;GACxE,IAAI,SAAS,MAAM,OAAO,QAAQ;EACpC;EACA,KAAK,MAAM,QAAQ,OAAO,KAAK,IAAI,GAAiB;GAClD,MAAM,OAAO,SAAS,MAAM,iBAAiB,iBAAiB,SAAS,OAAO,CAAC;GAC/E,IAAI,SAAS,MAAM,KAAK,QAAQ;EAClC;CACF;CACA,OAAO;EAAE;EAAU;EAAQ;CAAK;AAClC;;;ACnFA,IAAM,WAAW;;AAsEjB,SAAS,eAAe,EAAE,UAAU,UAAgD;CAClF,MAAM,aAAc,IAAI,KAAK,KAAM,aAAa;CAChD,OAAO;EACL,iBAAiB,KAAK,MAAM,SAAS;EACrC,eAAe,KAAK,MAAM,KAAK,IAAI,UAAU,KAAK,KAAK,SAAS,CAAC;CACnE;AACF;AAEA,SAAgB,cAAc,QAAsB,SAA2B;CAC7E,MAAM,EAAE,UAAU,QAAQ,SAAS;CACnC,MAAM,OAAmB;EAAE,UAAU,SAAS;EAAM,MAAM,KAAK;CAAI;CACnE,MAAM,UAAsB;EAAE,UAAU,SAAS;EAAM,MAAM,KAAK;CAAI;CACtE,MAAM,SAAqB;EAAE,MAAM;EAAU,GAAG,OAAO;CAAO;CAC9D,MAAM,QAAoB;EACxB,MAAM;EACN,UAAU,SAAS;EACnB,QAAQ,OAAO,OAAO;CACxB;;CAGA,MAAM,cAA4B;EAChC,SAAS,EAAE,SAAS,EAAE;EACtB,SAAS,EAAE,SAAS,EAAE;EACtB,MAAM,EAAE,SAAS,EAAE;EACnB,YAAY;CACd;CACA,MAAM,QAAQ,SAAiB,SAAiB,MAAc,QAAQ,KAAK,QACzE,UACI,KAAK,IACL;EACE;EACA;EACA,MAAM;EACN,YAAY;GAAE,UAAU;GAAM,MAAM;EAAM;CAC5C;CAEN,MAAM,UAAU,MAAiB,aAAoC;EACnE,MAAM,MAAM,aAAa,SAAS,SAAS;EAC3C,MAAM,OAAO,SAAS,UAAU,SAAS,QAAQ,KAAK;EACtD,MAAM,QAAQ,OAAO,QAAQ,WAAW,GAAG,OAAO,IAAI,KAAK,OAAO;EAClE,OAAO,SAAS,UAAU,SAAS,UAAU;GAAE,GAAG;GAAO,SAAS;EAAE,IAAI;GAAE,GAAG;GAAO,SAAS;EAAE;CACjG;CACA,MAAM,WAAW,aAA6B;EAC5C,SAAS;EACT,GAAI,QAAQ,MAAM,KAAA,IAAY,EAAE,GAAG,EAAE,IAAI,CAAC;EAC1C,GAAI,QAAQ,MAAM,KAAA,IAAY,EAAE,GAAG,EAAE,IAAI,CAAC;CAC5C;CAEA,MAAM,OAAqB,UACvB,KAAK,IACL;EACE,SAAS,EAAE,SAAS,EAAE;EACtB,SAAS,EAAE,SAAS,EAAE;EACtB,MAAM;GAAE,SAAS;GAAG,YAAY;EAAQ;EACxC,YAAY;CACd;CAEJ,MAAM,QAAQ,OAA+B,MAAM,UAAwB;EACzE,IAAI,SAAS,OAAO,KAAK;EAIzB,OAAO;GACL,SAHA,OAAO,SAAS,WAAW;IAAE,SAAS;IAAG,OAAO;GAAK,IAAI;IAAE,SAAS;IAAG,GAAG,KAAK;GAAE;GAIjF,SAAS;IAAE,GAHM,OAAO,SAAS,WAAW;KAAE,SAAS;KAAG,OAAO;IAAE,IAAI;KAAE,SAAS;KAAG,GAAG;IAAE;IAGxE,YAAY;GAAM;GACpC,MAAM;IAAE,SAAS;IAAG,YAAY;GAAQ;GACxC,YAAY;EACd;CACF;CAEA,MAAM,SAAS,SAAkC;EAC/C,IAAI,SAAS,OAAO,KAAK;EACzB,MAAM,OAAO,SAAS,UAAU,SAAS,QAAQ,KAAK;EACtD,MAAM,OAAO,SAAS,UAAU,SAAS,UAAU,MAAM;EACzD,MAAM,OAAO,GAAG,OAAO,GAAG,OAAO,IAAI,GAAG;EACxC,OAAO;GACL,SAAS;GACT,SAAS,GAAG,OAAO,EAAE;GACrB,MAAM;IAAE,GAAG;IAAM,YAAY;KAAE,UAAU,SAAS;KAAM,MAAM,KAAK;IAAO;GAAE;GAC5E,YAAY;IAAE,UAAU,SAAS;IAAM,MAAM,KAAK;GAAO;EAC3D;CACF;CAEA,MAAM,WAAW,YAAmC;EAClD,IAAI,SAAS,OAAO,UAAU;GAAE,GAAG,KAAK;GAAG,YAAY,EAAE,UAAU,EAAE;EAAE,IAAI,KAAK;EAChF,OAAO;GACL,SAAS;IAAE,SAAS;IAAG,OAAO,MAAM;GAAQ;GAC5C,SAAS;IAAE,SAAS;IAAG,OAAO;GAAE;GAChC,MAAM;IAAE,SAAS;IAAG,YAAY;GAAQ;GACxC,YAAY,UAAU,EAAE,UAAU,EAAE,IAAI;EAC1C;CACF;CAEA,MAAM,UAAU;CAChB,MAAM,QAAQ,cAAoC;EAChD,IAAI,SAAS,OAAO,KAAK;EACzB,OAAO;GACL,SAAS;IAAE,SAAS;IAAG,GAAG,YAAY;IAAU,QAAQ;GAAQ;GAChE,SAAS;IAAE,SAAS;IAAG,GAAG;IAAG,QAAQ;IAAa,YAAY;GAAK;GACnE,MAAM;IAAE,SAAS;IAAG,QAAQ;IAAS,YAAY;GAAQ;GACzD,YAAY;EACd;CACF;CAEA,MAAM,mBAA2B;EAAE,SAAS;EAAG,OAAO,MAAM;CAAM;CAClE,MAAM,QAAqB;EACzB,UAAU,UAAU,KAAA,IAAY,EAAE,OAAO,MAAM,MAAM;EACrD,YAAY;GAAE,UAAU,SAAS;GAAO,MAAM,KAAK;EAAI;CACzD;CACA,MAAM,OAAmB,UAAU,EAAE,UAAU,EAAE,IAAI;EAAE,UAAU,SAAS;EAAM,MAAM,KAAK;CAAK;CAEhG,OAAO;EACL;EACA;EACA,KAAK,MAAM;EACX,MAAM,UAAU,KAAA,IAAY;GAAE,OAAO,CAAC,MAAM,MAAM,CAAC;GAAG,YAAY;EAAQ;EAC1E;EACA;EACA,OAAO,KAAK;EACZ,KAAK,KACH;GAAE,SAAS;GAAG,OAAO,MAAM;EAAI,GAC/B;GAAE,SAAS;GAAG,OAAO;EAAE,GACvB,SAAS,MACT,KAAK,MACP;EACA,WAAW,UACP,KAAK,IACL;GACE,SAAS;GACT,SAAS;IAAE,SAAS;IAAG,OAAO;GAAE;GAChC,MAAM;GACN,YAAY;EACd;EACJ,QAAQ,MAAM,WAAW,WAAW;GAClC,MAAM,UAAU,OAAO,MAAM,QAAQ;GACrC,OAAO,KAAK,SAAS,QAAQ,OAAO,GAAG,aAAa,SAAS,SAAS,OAAO,SAAS,IAAI;EAC5F;EACA;EACA;EACA;EACA;EACA,SAAS,SAAS;GAChB,MAAM,UAAU,OAAO,MAAM,OAAO;GACpC,OAAO,KAAK,SAAS,QAAQ,OAAO,GAAG,OAAO,KAAK;EACrD;EACA;EACA,QAAQ;EACR,QAAQ,UAAU,EAAE,UAAU,EAAE,IAAI;EACpC,aAAa,UAAU,EAAE,UAAU,EAAE,IAAI;GAAE,MAAM;GAAU,GAAG,OAAO;EAAM;EAC3E,aAAa,eAAe,OAAO,KAAK;EACxC,UAAU,OAAO,QAAQ,OAAO,EAC9B,OAAO,UAAU,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,SAAS,OAAO,GACjE;EACA,gBAAgB,OAAO,QAAQ,OAAO,EACpC,OAAO,UAAU,IAAI,KAAK,IAAI,OAAO,KAAK,IAAI,OAAO,QACvD;CACF;AACF;;AAGA,SAAgB,cAAc,CAC5B,GACA,GACA,GACA,IACkE;CAClE,OAAO,gBAAgB,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;AAC1C;;AAGA,SAAgB,oBAAoB,SAA2B;CAC7D,OAAO,cAAc,iBAAiB,GAAG,OAAO;AAClD;;;;AC9QA,IAAM,cAAc,cAAc;CAAE,UAAU;CAAU,QAAQ;CAAQ,MAAM;AAAK,GAAG,KAAK;AAC3F,IAAM,0BAA0B,CAAC;AACjC,IAAM,cAAc;;;;;;;AAQpB,SAAgB,mBAA4B;CAC1C,MAAM,KAAK,cAAc,MAAM;CAC/B,MAAM,UAAU,qBACd,KAAK,yBAAyB,aAC9B,KAAK,mBAAmB,OACxB,KACF;CACA,OAAO,cAAe,KAAK,oBAAoB,OAAO,IAAI,aAAc,CAAC,IAAI,OAAO,CAAC;AACvF"}
|
|
1
|
+
{"version":3,"file":"use-motion-presets-DCJPBfNJ.js","names":[],"sources":["../src/lib/motion/tokens.ts","../src/lib/motion/presets.ts","../src/lib/motion/use-motion-presets.ts"],"sourcesContent":["/*\n * Durações e curvas do motion (linguagem única, web e app). A fonte é o globals.css:\n * --rendra-duration-* bloco :root fora de camada (vai para o dist/tokens.css do pacote);\n * --rendra-ease-* no mesmo bloco, então o host as sobrescreve; o @theme guarda os nomes\n * do Tailwind (--ease-out, --ease-move...) como alias delas.\n * As constantes daqui são a reserva em tempo de execução (SSR, variável ausente ou inválida), e\n * tokens.test.ts confere que elas batem com o globals.css. Valores em segundos e vetores de 4\n * números, o formato que o Motion aceita.\n */\n\nexport type Bezier = [number, number, number, number]\n\n/**\n * Reserva das durações, em segundos (SSR, ou variável ausente).\n * `press` e `fast` valem o mesmo (120 ms) com propósitos diferentes: o toque e a saída de overlay.\n */\nexport const DURATION = {\n press: 0.12,\n hover: 0.15,\n fast: 0.12,\n base: 0.2,\n move: 0.25,\n slow: 0.32,\n draw: 0.42,\n pulse: 1,\n}\nexport type DurationName = keyof typeof DURATION\n\n/**\n * Reveal: entrada de uso único (dashboard: bloco, cascata, contador e desenho do gráfico), mais\n * lenta que as interações do dia a dia. Reserva em segundos (SSR, ou variável ausente).\n */\nexport const REVEAL = { enter: 0.6, stagger: 0.12, count: 1.2, draw: 0.9 }\nexport type RevealName = keyof typeof REVEAL\n\n/**\n * Curvas do globals.css (`--rendra-ease-*`). `spring` é a curva \"back\" (quique): só para a cota\n * rara de encanto. `move` desloca na tela; `drawer` é a curva de gaveta e folha.\n */\nexport const EASE: Record<'out' | 'inOut' | 'spring' | 'move' | 'drawer', Bezier> = {\n out: [0.22, 1, 0.36, 1],\n inOut: [0.65, 0, 0.35, 1],\n spring: [0.34, 1.56, 0.64, 1],\n move: [0.77, 0, 0.175, 1],\n drawer: [0.32, 0.72, 0, 1],\n}\nexport type EaseName = keyof typeof EASE\n\n/** Nome da variável CSS de cada curva (`inOut` vira `in-out`). */\nconst EASE_VAR: Record<EaseName, string> = {\n out: 'out',\n inOut: 'in-out',\n spring: 'spring',\n move: 'move',\n drawer: 'drawer',\n}\n\n/**\n * Molas no formato \"duração e quique\" (Motion). `settle` assenta sem passar do ponto (layout,\n * overlay que entra, soltura do arraste); `sheet` é a folha depois do gesto, com quique mínimo.\n * Mola não é variável CSS: mora aqui, e o app a espelha em `dampingRatio`.\n */\nexport const SPRING = {\n settle: { duration: 0.4, bounce: 0 },\n sheet: { duration: 0.3, bounce: 0.2 },\n}\n\n/** Escalas da linguagem: entrada de overlay, tooltip, ponto pequeno, toque, pop e salto curto. */\nexport const SCALE = { enter: 0.95, tooltip: 0.97, small: 0.9, press: 0.97, pop: 0.8, bump: 1.08 }\n\n/** Desfoque (px) que disfarça o cruzamento entre dois estados (troca de passo). Abaixo de 20. */\nexport const BLUR = 2\n\nexport interface MotionTokens {\n duration: Record<DurationName, number>\n reveal: Record<RevealName, number>\n ease: Record<EaseName, Bezier>\n}\n\nfunction toSeconds(value: string): number | null {\n const v = value.trim()\n const n = parseFloat(v)\n if (!Number.isFinite(n)) return null\n if (v.endsWith('ms')) return n / 1000\n if (v.endsWith('s')) return n\n return null\n}\n\n/** `cubic-bezier(a, b, c, d)` em vetor; qualquer outra coisa (`ease-in`, vazio) vira `null`. */\nfunction toBezier(value: string): Bezier | null {\n const m = /^cubic-bezier\\(([^)]+)\\)$/.exec(value.trim())\n if (!m) return null\n const parts = m[1]!.split(',').map((n) => parseFloat(n))\n if (parts.length !== 4 || parts.some((n) => !Number.isFinite(n))) return null\n return parts as Bezier\n}\n\n/** Lê as durações e as curvas do documento; o que faltar (ou sem window) vem da reserva. */\nexport function readMotionTokens(): MotionTokens {\n const duration = { ...DURATION }\n const reveal = { ...REVEAL }\n const ease = { ...EASE }\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n const style = getComputedStyle(document.documentElement)\n for (const name of Object.keys(DURATION) as DurationName[]) {\n const read = toSeconds(style.getPropertyValue(`--rendra-duration-${name}`))\n if (read !== null) duration[name] = read\n }\n for (const name of Object.keys(REVEAL) as RevealName[]) {\n const read = toSeconds(style.getPropertyValue(`--rendra-reveal-${name}`))\n if (read !== null) reveal[name] = read\n }\n for (const name of Object.keys(EASE) as EaseName[]) {\n const read = toBezier(style.getPropertyValue(`--rendra-ease-${EASE_VAR[name]}`))\n if (read !== null) ease[name] = read\n }\n }\n return { duration, reveal, ease }\n}\n","import type { Target, TargetAndTransition, Transition } from 'motion/react'\nimport { BLUR, readMotionTokens, SCALE, SPRING, type Bezier, type MotionTokens } from './tokens'\n\n/*\n * Presets do caminho `on` (linguagem única de movimento): fade, scale/open, sheet, tooltip,\n * indicator, pop, slide, reveal, press, move, settle e stagger. Toda duração e toda curva vêm de\n * readMotionTokens (globals.css); nenhum número de duração mora neste arquivo (o presets.test.ts\n * varre o código-fonte atrás de literal). As molas e as escalas vêm de tokens.ts.\n *\n * Duas regras moram aqui:\n * - Assimetria: o que o usuário decidiu (abrir) entra no tempo `base`, e o que o sistema\n * responde ao fechar sai em `fast`, só em opacidade. Gaveta e folha saem em `base`, de volta\n * pelo lado de onde vieram.\n * - Reduzido: sem deslocamento, escala, filtro nem cascata; a opacidade usa `base` (não zero),\n * porque o esmaecimento é o que explica a mudança de estado.\n */\n\nexport interface MotionPreset {\n initial: Target\n animate: TargetAndTransition\n exit: TargetAndTransition\n transition: Transition\n}\n\n/** Toque: o alvo do `whileTap` (`undefined` no reduzido) e a transição de ida e de volta. */\nexport interface PressPreset {\n whileTap: TargetAndTransition | undefined\n transition: Transition\n}\n\nexport type SlideFrom = 'left' | 'right' | 'top' | 'bottom'\n\n/** Distância do slide: `full` (painel que entra da borda) ou `short` (conteúdo que assenta). */\nexport type SlideDistance = 'full' | 'short'\n\nconst SHORT_PX = 8\n\nexport interface Presets {\n reduced: boolean\n /** Toque do botão, do polegar e dos controles: 120 ms, `ease.out`, escala 0,97. */\n press: PressPreset\n /** Alias de `press.whileTap`, o nome antigo. Sem movimento reduzido vem `undefined`. */\n tap: TargetAndTransition | undefined\n /**\n * Salto curto de escala (célula do OTP), com a transição dentro do alvo. Estável entre\n * renders; `undefined` se reduzido.\n */\n bump: TargetAndTransition | undefined\n tokens: MotionTokens\n fade: MotionPreset\n /** Alias de `open()`: escala 0,95 com mola a partir da origem, saída rápida só em opacidade. */\n scale: MotionPreset\n /**\n * Cota rara de encanto (check do passo concluído): 0,8 -> 1 com a curva back, em `slow`. Nunca\n * em controle de uso frequente.\n */\n pop: MotionPreset\n /**\n * Indicador de controle frequente (check do Checkbox, ponto do Radio): 0,9 -> 1 com opacidade\n * em `fast`, sem quique e sem partir de zero.\n */\n indicator: MotionPreset\n slide: (from: SlideFrom, distance?: SlideDistance) => MotionPreset\n /**\n * Overlay ancorado (popover, menu, modal, painel do select). Número = escala de partida\n * (padrão 0,95); `{ y }` = entrada plana, sem escala, para a superfície em tela cheia.\n * Entra em mola criticamente amortecida (sem quique) em `base` e sai em `fast`, em opacidade.\n */\n open: (from?: number | { y: number }) => MotionPreset\n /** Gaveta e folha: entram de `from` em `slow` com `ease.drawer`, saem em `fast` pelo mesmo lado. */\n sheet: (from: SlideFrom) => MotionPreset\n /** Tooltip: escala 0,97 em `fast`; aberto em `instant-open` não anima. */\n tooltip: (instant: boolean) => MotionPreset\n /**\n * Troca de conteúdo no lugar (passo do wizard), sem esperar a saída: o que sai esmaece com\n * `blur` de 2 px em `fast`; o que entra vem de `direction` (1 avança, -1 volta), 8 px, em\n * `base`. O desfoque disfarça o cruzamento: sem ele o olho vê dois objetos trocando de lugar.\n */\n swap: (direction: 1 | -1) => MotionPreset\n /**\n * Entrada de uso único (reveal do dashboard): desloca 8 px e dura `reveal.enter`, mais lenta\n * que `slide`. Não serve a interação repetida (overlay, tab, botão).\n */\n reveal: (from: SlideFrom) => MotionPreset\n /** Deslocamento na tela (indicador, reordenação): `move` em `ease.move`. */\n move: Transition\n /** Nome antigo de `move`. */\n layout: Transition\n /** Mola sem quique: onde há gesto ou soltura (drop do kanban, folha que volta). */\n settle: Transition\n /** Mola da folha depois do arraste (quique mínimo). */\n springSheet: Transition\n /**\n * A mesma mola da folha em rigidez e amortecimento (massa 1), que é o que o arraste do Motion\n * (`dragTransition`) pede para a volta à origem: rigidez = (2π / duração)², amortecimento =\n * 2 (1 - quique) raiz(rigidez).\n */\n sheetBounce: { bounceStiffness: number; bounceDamping: number }\n /** Atraso de entrada do item `index`, limitado a `limit` itens (padrão 8: 480 ms). */\n stagger: (index: number, limit?: number) => Transition\n /** Atraso do bloco `index` no reveal (passo `reveal.stagger`), limitado a `limit` blocos. */\n staggerReveal: (index: number, limit?: number) => Transition\n}\n\n/** Mola em \"duração e quique\" para rigidez e amortecimento (massa 1). */\nfunction springToBounce({ duration, bounce }: { duration: number; bounce: number }) {\n const stiffness = ((2 * Math.PI) / duration) ** 2\n return {\n bounceStiffness: Math.round(stiffness),\n bounceDamping: Math.round(2 * (1 - bounce) * Math.sqrt(stiffness)),\n }\n}\n\nexport function createPresets(tokens: MotionTokens, reduced: boolean): Presets {\n const { duration, reveal, ease } = tokens\n const base: Transition = { duration: duration.base, ease: ease.out }\n const fastOut: Transition = { duration: duration.fast, ease: ease.out }\n const settle: Transition = { type: 'spring', ...SPRING.settle }\n const enter: Transition = {\n type: 'spring',\n duration: duration.base,\n bounce: SPRING.settle.bounce,\n }\n\n /** O que sobra sob \"reduzir movimento\": só opacidade, em `base`. */\n const flat = (): MotionPreset => ({\n initial: { opacity: 0 },\n animate: { opacity: 1 },\n exit: { opacity: 0 },\n transition: base,\n })\n const make = (initial: Target, animate: Target, time: number, curve = ease.out): MotionPreset =>\n reduced\n ? flat()\n : {\n initial,\n animate,\n exit: initial,\n transition: { duration: time, ease: curve },\n }\n\n const offset = (from: SlideFrom, distance: SlideDistance): Target => {\n const far = distance === 'full' ? '100%' : SHORT_PX\n const sign = from === 'left' || from === 'top' ? -1 : 1\n const value = typeof far === 'string' ? `${sign * 100}%` : sign * far\n return from === 'left' || from === 'right' ? { x: value, opacity: 0 } : { y: value, opacity: 0 }\n }\n const settled = (initial: Target): Target => ({\n opacity: 1,\n ...(initial.x !== undefined ? { x: 0 } : {}),\n ...(initial.y !== undefined ? { y: 0 } : {}),\n })\n\n const fade: MotionPreset = reduced\n ? flat()\n : {\n initial: { opacity: 0 },\n animate: { opacity: 1 },\n exit: { opacity: 0, transition: fastOut },\n transition: base,\n }\n\n const open = (from: number | { y: number } = SCALE.enter): MotionPreset => {\n if (reduced) return flat()\n const initial: Target =\n typeof from === 'number' ? { opacity: 0, scale: from } : { opacity: 0, y: from.y }\n const to: Target = typeof from === 'number' ? { opacity: 1, scale: 1 } : { opacity: 1, y: 0 }\n return {\n initial,\n animate: { ...to, transition: enter },\n exit: { opacity: 0, transition: fastOut },\n transition: enter,\n }\n }\n\n const sheet = (from: SlideFrom): MotionPreset => {\n if (reduced) return flat()\n const sign = from === 'left' || from === 'top' ? -1 : 1\n const axis = from === 'left' || from === 'right' ? 'x' : 'y'\n const away = { [axis]: `${sign * 100}%` }\n return {\n initial: away,\n animate: { [axis]: 0 },\n exit: { ...away, transition: { duration: duration.fast, ease: ease.drawer } },\n transition: { duration: duration.slow, ease: ease.drawer },\n }\n }\n\n const tooltip = (instant: boolean): MotionPreset => {\n if (reduced) return instant ? { ...flat(), transition: { duration: 0 } } : flat()\n return {\n initial: { opacity: 0, scale: SCALE.tooltip },\n animate: { opacity: 1, scale: 1 },\n exit: { opacity: 0, transition: fastOut },\n transition: instant ? { duration: 0 } : fastOut,\n }\n }\n\n const blurred = `blur(${BLUR}px)`\n const swap = (direction: 1 | -1): MotionPreset => {\n if (reduced) return flat()\n return {\n initial: { opacity: 0, x: direction * SHORT_PX, filter: blurred },\n animate: { opacity: 1, x: 0, filter: 'blur(0px)', transition: base },\n exit: { opacity: 0, filter: blurred, transition: fastOut },\n transition: base,\n }\n }\n\n const indicatorInitial: Target = { opacity: 0, scale: SCALE.small }\n const press: PressPreset = {\n whileTap: reduced ? undefined : { scale: SCALE.press },\n transition: { duration: duration.press, ease: ease.out },\n }\n const move: Transition = reduced ? { duration: 0 } : { duration: duration.move, ease: ease.move }\n\n return {\n reduced,\n press,\n tap: press.whileTap,\n bump: reduced ? undefined : { scale: [SCALE.bump, 1], transition: fastOut },\n tokens,\n fade,\n scale: open(),\n pop: make(\n { opacity: 0, scale: SCALE.pop },\n { opacity: 1, scale: 1 },\n duration.slow,\n ease.spring,\n ),\n indicator: reduced\n ? flat()\n : {\n initial: indicatorInitial,\n animate: { opacity: 1, scale: 1 },\n exit: indicatorInitial,\n transition: fastOut,\n },\n slide: (from, distance = 'full') => {\n const initial = offset(from, distance)\n return make(initial, settled(initial), distance === 'full' ? duration.slow : duration.base)\n },\n open,\n sheet,\n tooltip,\n swap,\n reveal: (from) => {\n const initial = offset(from, 'short')\n return make(initial, settled(initial), reveal.enter)\n },\n move,\n layout: move,\n settle: reduced ? { duration: 0 } : settle,\n springSheet: reduced ? { duration: 0 } : { type: 'spring', ...SPRING.sheet },\n sheetBounce: springToBounce(SPRING.sheet),\n stagger: (index, limit = 8) => ({\n delay: reduced ? 0 : Math.min(index, limit) * (duration.fast / 2),\n }),\n staggerReveal: (index, limit = 8) => ({\n delay: reduced ? 0 : Math.min(index, limit) * reveal.stagger,\n }),\n }\n}\n\n/** Curva no formato do recharts: `cubic-bezier(a,b,c,d)`, sem espaços. */\nexport function toCubicBezier([\n a,\n b,\n c,\n d,\n]: Bezier): `cubic-bezier(${number},${number},${number},${number})` {\n return `cubic-bezier(${a},${b},${c},${d})`\n}\n\n/** Presets com os tokens lidos agora do documento. */\nexport function presetsFromDocument(reduced: boolean): Presets {\n return createPresets(readMotionTokens(), reduced)\n}\n","import { useMemo, useSyncExternalStore } from 'react'\nimport { getReducedMotion, subscribeReducedMotion } from '@/hooks/use-reduced-motion'\nimport { useMotionMode } from './motion-context'\nimport { createPresets, presetsFromDocument, type Presets } from './presets'\nimport { DURATION, EASE, REVEAL } from './tokens'\n\n/** Em `off` ninguém lê o documento nem assina o matchMedia: um objeto único e inerte. */\nconst OFF_PRESETS = createPresets({ duration: DURATION, reveal: REVEAL, ease: EASE }, false)\nconst noSubscribe = () => () => {}\nconst never = () => false\n\n/**\n * Presets do motion para o componente. A preferência \"reduzir movimento\" vem do mesmo\n * `matchMedia` do hook do projeto (`use-reduced-motion.ts`: Spinner, Progress), a fonte única,\n * reativa e testável, sem `MotionConfig reducedMotion` somando por cima. Só em `on` a\n * preferência é assinada e os tokens lidos do documento; em `off` o custo é zero.\n */\nexport function useMotionPresets(): Presets {\n const on = useMotionMode() === 'on'\n const reduced = useSyncExternalStore(\n on ? subscribeReducedMotion : noSubscribe,\n on ? getReducedMotion : never,\n never,\n )\n return useMemo(() => (on ? presetsFromDocument(reduced) : OFF_PRESETS), [on, reduced])\n}\n"],"mappings":"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"}
|
package/dist/widget-grid.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/*! Rendra Design System v2.
|
|
2
|
-
import { t as cn } from "./cn-
|
|
1
|
+
/*! Rendra Design System v2.6.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
|
|
2
|
+
import { t as cn } from "./cn-TBlI6-gS.js";
|
|
3
3
|
import { GripVertical } from "lucide-react";
|
|
4
4
|
import { useMemo, useState } from "react";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rendra-ui/web",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Rendra, design system e boilerplate React (Vite, TypeScript, Tailwind v4, Radix), com CLI de catálogo, auditoria e troca de variante.",
|
|
6
6
|
"author": {
|
|
@@ -64,6 +64,10 @@
|
|
|
64
64
|
"types": "./dist/types/chart.d.ts",
|
|
65
65
|
"import": "./dist/chart.js"
|
|
66
66
|
},
|
|
67
|
+
"./motion": {
|
|
68
|
+
"types": "./dist/types/motion.d.ts",
|
|
69
|
+
"import": "./dist/motion.js"
|
|
70
|
+
},
|
|
67
71
|
"./widget-grid": {
|
|
68
72
|
"types": "./dist/types/widget-grid.d.ts",
|
|
69
73
|
"import": "./dist/widget-grid.js"
|
|
@@ -94,6 +98,8 @@
|
|
|
94
98
|
"build": "tsc -b && vite build",
|
|
95
99
|
"build:lib": "vite build --config vite.lib.config.ts && tsc -p tsconfig.build.json && node scripts/fix-dts-aliases.mjs && node scripts/build-lib.mjs",
|
|
96
100
|
"verify:pack": "node scripts/verify-pack.mjs",
|
|
101
|
+
"verify:bundle:app": "node scripts/bundle-inicial.mjs --verificar --app dist",
|
|
102
|
+
"verify:bundle:lib": "node scripts/bundle-inicial.mjs --verificar --lib dist",
|
|
97
103
|
"preview": "vite preview",
|
|
98
104
|
"typecheck": "tsc -b",
|
|
99
105
|
"lint": "eslint .",
|
|
@@ -115,6 +121,7 @@
|
|
|
115
121
|
"test:visual": "playwright test --project=visual",
|
|
116
122
|
"test:visual:update": "playwright test --project=visual --update-snapshots",
|
|
117
123
|
"test:motion": "playwright test --project=motion --project=estados",
|
|
124
|
+
"test:lazy": "playwright test --project=lazy",
|
|
118
125
|
"test:css-layers": "playwright test --project=css-layers",
|
|
119
126
|
"test:site": "playwright test -c playwright.site.config.ts",
|
|
120
127
|
"registry:build": "node scripts/build-registry.mjs",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"button-BzJgR2gH.js","names":[],"sources":["../src/components/ui/spinner.tsx","../src/lib/motion/native-events.ts","../src/components/ui/button.tsx"],"sourcesContent":["import { Loader2 } from 'lucide-react'\nimport { usePrefersReducedMotion } from '@/hooks/use-reduced-motion'\nimport { cn } from '@/lib/cn'\n\n/*\n * Indicador de carregamento único do sistema (A17 do plano da v2). Substitui qualquer\n * `Loader2 animate-spin` solto em Button, Input e Select. Sem label é decorativo\n * (aria-hidden); com label, anuncia o carregamento a quem usa leitor de tela. Para de girar\n * quando o sistema pede menos movimento.\n */\n\nexport interface SpinnerProps {\n size?: 'sm' | 'md' | 'lg'\n /** Nome do que está carregando. Vazio (padrão): decorativo, sem anúncio de leitor de tela. */\n label?: string\n className?: string\n}\n\nconst sizeClass: Record<NonNullable<SpinnerProps['size']>, string> = {\n sm: 'size-icon-sm',\n md: 'size-icon-md',\n lg: 'size-icon-lg',\n}\n\nexport function Spinner({ size = 'md', label, className }: SpinnerProps) {\n const reduced = usePrefersReducedMotion()\n const icon = (\n <Loader2 aria-hidden className={cn(sizeClass[size], reduced ? '' : 'animate-spin')} />\n )\n\n if (!label) {\n return (\n <span data-rendra=\"SPIN-001\" aria-hidden className={cn('inline-flex', className)}>\n {icon}\n </span>\n )\n }\n\n return (\n <span\n data-rendra=\"SPIN-001\"\n role=\"status\"\n className={cn('inline-flex items-center gap-2', className)}\n >\n {icon}\n <span className=\"sr-only\">{label}</span>\n </span>\n )\n}\n","/*\n * O Motion toma `onDrag`, `onDragStart`, `onDragEnd` e `onAnimationStart` para os gestos e\n * animações dele: tira essas props do DOM e as tipa com outra assinatura. Em `m.button` e\n * `m.li`, o consumidor que passa o evento nativo (HTML5 drag, animationstart do CSS) o perderia.\n * Estes ajudantes separam essas chaves das props e as ligam como ouvintes nativos no elemento.\n */\n\nconst NATIVE_EVENTS = {\n onDrag: 'drag',\n onDragStart: 'dragstart',\n onDragEnd: 'dragend',\n onAnimationStart: 'animationstart',\n} as const\n\ntype NativeKey = keyof typeof NATIVE_EVENTS\ntype Handler = ((event: never) => void) | undefined\n\n/** Separa as quatro chaves em conflito; o resto segue para o elemento do Motion. */\nexport function splitNativeEvents<P extends object>(props: P) {\n const native: Partial<Record<NativeKey, Handler>> = {}\n const rest: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(props)) {\n if (key in NATIVE_EVENTS) native[key as NativeKey] = value as Handler\n else rest[key] = value\n }\n return { native, rest: rest as Omit<P, NativeKey> }\n}\n\n/** Liga os manipuladores como ouvintes nativos. Devolve a função que os remove. */\nexport function bindNativeEvents(el: HTMLElement, native: Partial<Record<NativeKey, Handler>>) {\n const bound: [string, EventListener][] = []\n for (const [key, type] of Object.entries(NATIVE_EVENTS)) {\n const handler = native[key as NativeKey]\n if (!handler) continue\n const listener = ((event: Event) => handler(event as never)) as EventListener\n el.addEventListener(type, listener)\n bound.push([type, listener])\n }\n return () => bound.forEach(([type, listener]) => el.removeEventListener(type, listener))\n}\n","import { cva, type VariantProps } from 'class-variance-authority'\nimport { m } from 'motion/react'\nimport { Slot } from 'radix-ui'\nimport { forwardRef, type ButtonHTMLAttributes, type ReactNode, type Ref } from 'react'\nimport { resolveCatalogCode } from '@/catalog/components'\nimport { Spinner } from '@/components/ui/spinner'\nimport { cn } from '@/lib/cn'\nimport { useMotionMode, useMotionPresets } from '@/lib/motion'\nimport { bindNativeEvents, splitNativeEvents } from '@/lib/motion/native-events'\n\n/**\n * Botão único do sistema. Variantes, tamanho, ícone, só ícone, carregamento e\n * largura total são props: nunca crie outro arquivo de botão.\n * Altura vem de h-control-*: 44px ou mais no mobile, compacta a partir de md.\n */\nexport const buttonVariants = cva(\n 'inline-flex shrink-0 cursor-pointer items-center justify-center gap-2 rounded-control font-medium whitespace-nowrap transition-[color,background-color,border-color,box-shadow,transform] duration-(--rendra-duration-press) ease-out select-none active:scale-97 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 motion-reduce:active:scale-100 [&_svg]:pointer-events-none [&_svg]:shrink-0',\n {\n variants: {\n variant: {\n // Hover troca para a cor de hover da marca e eleva um nível; pressionar comprime.\n primary:\n 'bg-primary text-primary-foreground shadow-sm hover:bg-primary-hover hover:text-primary-hover-foreground hover:shadow-md active:bg-primary-hover active:text-primary-hover-foreground active:shadow-sm',\n secondary:\n 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary-hover hover:text-secondary-hover-foreground hover:shadow-md active:bg-secondary-hover active:text-secondary-hover-foreground active:shadow-sm',\n outline:\n 'border border-input bg-card text-foreground hover:border-primary hover:bg-primary-soft hover:text-primary-soft-foreground active:bg-primary-soft',\n // Transparentes: no hover, assumem a cor primária do template.\n ghost:\n 'text-foreground hover:bg-primary-soft hover:text-primary-soft-foreground active:bg-primary-soft',\n destructive:\n 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive-hover hover:shadow-md active:bg-destructive-hover active:shadow-sm',\n link: 'min-h-touch min-w-touch text-primary-text underline-offset-4 hover:text-primary-hover hover:underline md:min-h-0 md:min-w-0',\n },\n size: {\n sm: 'h-control-sm px-3 text-sm [&_svg]:size-icon-sm',\n md: 'h-control-md px-4 text-sm [&_svg]:size-icon-sm',\n lg: 'h-control-lg px-6 text-base [&_svg]:size-icon-md',\n },\n iconOnly: { true: 'px-0', false: '' },\n fullWidth: { true: 'w-full', false: '' },\n },\n compoundVariants: [\n { iconOnly: true, size: 'sm', className: 'w-control-sm' },\n { iconOnly: true, size: 'md', className: 'w-control-md' },\n { iconOnly: true, size: 'lg', className: 'w-control-lg' },\n { variant: 'link', className: 'h-auto px-0' },\n ],\n defaultVariants: { variant: 'primary', size: 'md', iconOnly: false, fullWidth: false },\n },\n)\n\ntype Variants = VariantProps<typeof buttonVariants>\n\nexport interface ButtonProps\n extends ButtonHTMLAttributes<HTMLButtonElement>, Omit<Variants, 'iconOnly' | 'fullWidth'> {\n /** Ícone à esquerda do texto (ou o próprio conteúdo, com iconOnly). */\n icon?: ReactNode\n /** Ícone à direita do texto. */\n iconRight?: ReactNode\n /** Botão só com ícone: quadrado, e aria-label passa a ser obrigatório. */\n iconOnly?: boolean\n /** Mostra indicador, bloqueia cliques e marca aria-busy. */\n loading?: boolean\n /** Ocupa toda a largura do contêiner. */\n fullWidth?: boolean\n /** Renderiza o filho (ex.: <Link>) com a aparência de botão. */\n asChild?: boolean\n}\n\ntype MotionButtonProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'children'> & {\n children: ReactNode\n}\n\n/**\n * O botão de `on`: `m.button` com toque discreto (whileTap). Os eventos que o Motion toma\n * (`onDrag*` e `onAnimationStart`) saem das props dele e viram ouvintes nativos no elemento,\n * então o consumidor continua recebendo o evento. Só existe em `on`; por isso os hooks de motion\n * moram aqui e o `off` não paga nada.\n */\nconst MotionButton = forwardRef<HTMLButtonElement, MotionButtonProps>(\n function MotionButton(props, ref) {\n const presets = useMotionPresets()\n const { native, rest } = splitNativeEvents(props)\n const attach = (el: HTMLButtonElement | null) => {\n assignRef(ref, el)\n if (!el) return\n const unbind = bindNativeEvents(el, native)\n return () => {\n unbind()\n assignRef(ref, null)\n }\n }\n return (\n <m.button\n ref={attach}\n whileTap={presets.press.whileTap}\n transition={presets.press.transition}\n {...rest}\n />\n )\n },\n)\n\nfunction assignRef<T>(ref: Ref<T> | undefined, value: T | null) {\n if (typeof ref === 'function') ref(value)\n else if (ref) ref.current = value\n}\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(\n {\n className,\n variant,\n size,\n icon,\n iconRight,\n iconOnly = false,\n loading = false,\n fullWidth = false,\n asChild = false,\n disabled,\n type = 'button',\n children,\n ...props\n },\n ref,\n) {\n if (import.meta.env.DEV && iconOnly && !props['aria-label']) {\n console.warn('Button com iconOnly precisa de aria-label.')\n }\n const on = useMotionMode() === 'on'\n // Em `on` o toque é do whileTap: a classe `active:scale-97` sairia somando com ele, e o\n // `transform` sai da lista de transition (senão o CSS transiciona cada quadro que o Motion grava\n // e o toque chega atrasado). Com asChild nada disso: é só CSS, como em `off`.\n const classes = cn(\n buttonVariants({ variant, size, iconOnly, fullWidth }),\n on &&\n !asChild &&\n 'transition-[color,background-color,border-color,box-shadow] active:scale-100',\n className,\n )\n const code = resolveCatalogCode('Button', { variant: variant ?? 'primary' })\n\n if (asChild) {\n return (\n <Slot.Root ref={ref} data-rendra={code} className={classes} {...props}>\n {children}\n </Slot.Root>\n )\n }\n\n // Ícone dentro do botão segue o tamanho do próprio botão (sm/md -> sm, lg -> md, como o\n // [&_svg]:size-icon-* de buttonVariants já fazia com o Loader2 solto).\n const leading = loading ? <Spinner size={size === 'lg' ? 'md' : 'sm'} /> : icon\n if (on) {\n return (\n <MotionButton\n ref={ref}\n type={type}\n data-rendra={code}\n className={classes}\n disabled={disabled || loading}\n aria-busy={loading || undefined}\n {...props}\n >\n {leading}\n {iconOnly ? (loading ? null : children) : children}\n {!iconOnly && iconRight}\n </MotionButton>\n )\n }\n return (\n <button\n ref={ref}\n type={type}\n data-rendra={code}\n className={classes}\n disabled={disabled || loading}\n aria-busy={loading || undefined}\n {...props}\n >\n {leading}\n {iconOnly ? (loading ? null : children) : children}\n {!iconOnly && iconRight}\n </button>\n )\n})\n"],"mappings":"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"}
|
|
@@ -1,107 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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 +0,0 @@
|
|
|
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"}
|
|
@@ -1 +0,0 @@
|
|
|
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":";;;;;;;;;;AAaA,IAAM,kBAAkB,cAA8B,IAAI;AAC1D,IAAM,iBAAiB,cAA8B,IAAI;AAEzD,SAAS,aAAa,EAAE,MAAM,aAAa,cAAc,GAAG,QAAuC;CACjG,MAAM,CAAC,OAAO,YAAY,SAAS,eAAe,KAAK;CACvD,MAAM,UAAU,QAAQ;CACxB,OACE,oBAAC,gBAAgB,UAAjB;EAA0B,OAAO;EAC/B,UAAA,oBAAC,aAAE,MAAH;GACE,GAAI;GACJ,MAAM;GACN,eAAe,SAAS;IACtB,SAAS,IAAI;IACb,eAAe,IAAI;GACrB;EACD,CAAA;CACuB,CAAA;AAE9B;AAEA,SAAS,YAAY,EAAE,MAAM,aAAa,cAAc,GAAG,QAAsC;CAC/F,MAAM,CAAC,OAAO,YAAY,SAAS,eAAe,KAAK;CACvD,MAAM,UAAU,QAAQ;CACxB,OACE,oBAAC,eAAe,UAAhB;EAAyB,OAAO;EAC9B,UAAA,oBAAC,aAAE,KAAH;GACE,GAAI;GACJ,MAAM;GACN,eAAe,SAAS;IACtB,SAAS,IAAI;IACb,eAAe,IAAI;GACrB;EACD,CAAA;CACsB,CAAA;AAE7B;AAEA,SAAgB,eAAa,OAAsC;CACjE,OAAO,cAAc,MAAM,OAAO,oBAAC,cAAD,EAAc,GAAI,MAAQ,CAAA,IAAI,oBAAC,aAAE,MAAH,EAAQ,GAAI,MAAQ,CAAA;AACtF;AACA,IAAa,sBAAsB,aAAE;AACrC,IAAa,oBAAoB,aAAE;AACnC,SAAgB,gBAAgB,OAAqC;CACnE,OAAO,cAAc,MAAM,OAAO,oBAAC,aAAD,EAAa,GAAI,MAAQ,CAAA,IAAI,oBAAC,aAAE,KAAH,EAAO,GAAI,MAAQ,CAAA;AACpF;AACA,IAAa,yBAAyB,aAAE;AAGxC,IAAM,YACJ;AACF,IAAM,WAAW,GACf,WACA,sLACF;AAGA,IAAM,OACJ;AAEF,SAAgB,oBAAoB,EAClC,WACA,aAAa,GACb,UACA,SACA,GAAG,SACgC;CACnC,MAAM,OAAO,WAAW,eAAe;CACvC,MAAM,SAAS,cAAc;CAC7B,MAAM,UAAU,iBAAiB;CAEjC,IAAI,WAAW,QAAQ,SAAS,QAAQ,CAAC,SACvC,OACE,oBAAC,iBAAD,EAAA,UACG,QACC,oBAAC,aAAE,QAAH;EAAU,YAAA;EACR,UAAA,oBAAC,aAAE,SAAH;GACE,YAAA;GACA,SAAA;GACY;GACZ,kBAAkB;GAClB,eAAY;GACZ,WAAW,GAAG,WAAW,SAAS;GAClC,GAAI;GAEJ,UAAA,oBAAC,EAAE,KAAH;IAAO,GAAI,QAAQ,KAAK;IAAI;GAAgB,CAAA;EACnC,CAAA;CACH,GAZe,MAYf,EAEG,CAAA;CAIrB,OACE,oBAAC,aAAE,QAAH,EAAA,UACE,oBAAC,aAAE,SAAH;EACc;EACZ,kBAAkB;EAClB,eAAY;EACZ,WAAW,GAAG,UAAU,SAAS;EACxB;EACT,GAAI;EAEH;CACQ,CAAA,EACH,CAAA;AAEd;AAOA,SAAgB,iBAAiB,EAAE,WAAW,aAAa,GAAG,SAAoB;CAChF,OACE,oBAAC,aAAE,MAAH;EACE,WAAW,GACT,MACA,eACE,gIACF,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAgB,yBAAyB,EACvC,WACA,UACA,GAAG,SACqC;CACxC,OACE,qBAAC,aAAE,cAAH;EAAgB,WAAW,GAAG,MAAM,QAAQ,SAAS;EAAG,GAAI;EAA5D,UAAA,CACE,oBAAC,QAAD;GAAM,WAAU;GACd,UAAA,oBAAC,aAAE,eAAH,EAAA,UACE,oBAAC,OAAD,EAAO,WAAU,oBAAqB,CAAA,EACvB,CAAA;EACb,CAAA,GACL,QACa;;AAEpB;AAEA,SAAgB,sBAAsB,EACpC,WACA,UACA,GAAG,SACkC;CACrC,OACE,qBAAC,aAAE,WAAH;EAAa,WAAW,GAAG,MAAM,QAAQ,SAAS;EAAG,GAAI;EAAzD,UAAA,CACE,oBAAC,QAAD;GAAM,WAAU;GACd,UAAA,oBAAC,aAAE,eAAH,EAAA,UACE,oBAAC,OAAD,EAAO,WAAU,oBAAqB,CAAA,EACvB,CAAA;EACb,CAAA,GACL,QACU;;AAEjB;AAEA,SAAgB,kBAAkB,EAAE,WAAW,GAAG,SAAyC;CACzF,OACE,oBAAC,aAAE,OAAH;EACE,WAAW,GAAG,uDAAuD,SAAS;EAC9E,GAAI;CACL,CAAA;AAEL;AAEA,SAAgB,sBAAsB,EAAE,WAAW,GAAG,SAA6C;CACjG,OAAO,oBAAC,aAAE,WAAH;EAAa,WAAW,GAAG,6BAA6B,SAAS;EAAG,GAAI;CAAQ,CAAA;AACzF;AAEA,SAAgB,uBAAuB,EACrC,WACA,UACA,GAAG,SACmC;CACtC,OACE,qBAAC,aAAE,YAAH;EAAc,WAAW,GAAG,MAAM,+BAA+B,SAAS;EAAG,GAAI;EAAjF,UAAA,CACG,UACD,oBAAC,cAAD,EAAc,WAAU,UAAW,CAAA,CACvB;;AAElB;AAEA,SAAgB,uBAAuB,EACrC,WACA,UACA,SACA,GAAG,SACmC;CACtC,MAAM,OAAO,WAAW,cAAc;CACtC,MAAM,SAAS,cAAc;CAC7B,MAAM,UAAU,iBAAiB;CAEjC,IAAI,WAAW,QAAQ,SAAS,QAAQ,CAAC,SACvC,OACE,oBAAC,iBAAD,EAAA,UACG,QACC,oBAAC,aAAE,QAAH;EAAU,YAAA;EACR,UAAA,oBAAC,aAAE,YAAH;GACE,YAAA;GACA,SAAA;GACA,kBAAkB;GAClB,WAAW,GAAG,WAAW,SAAS;GAClC,GAAI;GAEJ,UAAA,oBAAC,EAAE,KAAH;IAAO,GAAI,QAAQ,KAAK;IAAI;GAAgB,CAAA;EAChC,CAAA;CACN,GAVe,SAUf,EAEG,CAAA;CAIrB,OACE,oBAAC,aAAE,QAAH,EAAA,UACE,oBAAC,aAAE,YAAH;EACE,kBAAkB;EAClB,WAAW,GAAG,UAAU,SAAS;EACxB;EACT,GAAI;EAEH;CACW,CAAA,EACN,CAAA;AAEd;;;;;;;ACxOA,SAAgB,gBAAgB,EAAE,YAAqC;CACrE,OACE,oBAAC,QAAE,UAAH;EAAY,eAAe;EAAK,mBAAmB;EAChD;CACS,CAAA;AAEhB;AAWA,IAAM,aACJ;;;;;;;AAQF,IAAM,cAAc,WAClB,SAAS,YAAY,OAAO,KAAK;CAC/B,MAAM,UAAU,iBAAiB;CACjC,MAAM,UAAW,MAAoC,kBAAkB;CACvE,OAAO,oBAAC,EAAE,KAAH;EAAY;EAAK,GAAI;EAAO,GAAI,QAAQ,QAAQ,OAAO;CAAI,CAAA;AACpE,CACF;AAEA,SAAgB,UAAQ,EAAE,SAAS,UAAU,OAAO,OAAO,YAA0B;CACnF,MAAM,SAAS,cAAc;CAG7B,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CACtC,IAAI,UAAU,OAAO,oBAAA,YAAA,EAAG,SAAW,CAAA;CACnC,IAAI,WAAW,MACb,OACE,qBAAC,QAAE,MAAH;EAAc;EAAM,cAAc;EAAlC,UAAA,CACE,oBAAC,QAAE,SAAH;GAAW,SAAA;GAAS;EAAoB,CAAA,GACxC,oBAAC,iBAAD,EAAA,UACG,QACC,oBAAC,QAAE,QAAH;GAAU,YAAA;GACR,UAAA,oBAAC,QAAE,SAAH;IACE,YAAA;IACA,SAAA;IACM;IACN,YAAY;IACZ,kBAAkB;IAClB,eAAY;IACZ,WAAW;IAEX,UAAA,oBAAC,aAAD,EAAA,UAAc,QAAqB,CAAA;GAC1B,CAAA;EACH,GAZe,SAYf,EAEG,CAAA,CACX;;CAGZ,OACE,qBAAC,QAAE,MAAH,EAAA,UAAA,CACE,oBAAC,QAAE,SAAH;EAAW,SAAA;EAAS;CAAoB,CAAA,GACxC,oBAAC,QAAE,QAAH,EAAA,UACE,oBAAC,QAAE,SAAH;EACQ;EACN,YAAY;EACZ,kBAAkB;EAClB,eAAY;EACZ,WAAW,GACT,YAEA,6LACF;EAEC,UAAA;CACQ,CAAA,EACH,CAAA,CACJ,EAAA,CAAA;AAEZ"}
|