@rendra-ui/web 2.6.0 → 2.8.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 +15 -14
- package/dist/base.css +1 -1
- package/dist/{empty-state-DrQjqxvp.js → brand-feedback-icon-CVux4pNh.js} +4 -64
- package/dist/brand-feedback-icon-CVux4pNh.js.map +1 -0
- package/dist/{button-B6-644xP.js → button-CrSlVIsY.js} +6 -6
- package/dist/{button-B6-644xP.js.map → button-CrSlVIsY.js.map} +1 -1
- package/dist/chart.js +7 -7
- 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-TBlI6-gS.js → cn-BlJHpkDs.js} +2 -2
- package/dist/{cn-TBlI6-gS.js.map → cn-BlJHpkDs.js.map} +1 -1
- package/dist/{components-Btk1cUg2.js → components-6RpoJ2Od.js} +20 -4
- package/dist/{components-Btk1cUg2.js.map → components-6RpoJ2Od.js.map} +1 -1
- package/dist/components.css +108 -1
- package/dist/document-viewer.js +4 -4
- package/dist/{tooltip-kgsorOg6.js → dropdown-menu-BUGKtR6k.js} +9 -75
- package/dist/dropdown-menu-BUGKtR6k.js.map +1 -0
- package/dist/empty-state-i4e-LacG.js +67 -0
- package/dist/empty-state-i4e-LacG.js.map +1 -0
- package/dist/{features-max-CC6CorTg.js → features-max-BCIy1Ic-.js} +1 -1
- package/dist/flow.js +1485 -0
- package/dist/flow.js.map +1 -0
- package/dist/index.js +816 -2019
- package/dist/index.js.map +1 -1
- package/dist/{motion-context-BL545cb6.js → motion-context-PJPj6X4g.js} +4 -4
- package/dist/{motion-context-BL545cb6.js.map → motion-context-PJPj6X4g.js.map} +1 -1
- package/dist/{motion-on-DMoTsWrG.js → motion-on-Bocf4Smc.js} +2 -2
- package/dist/{motion-on-DMoTsWrG.js.map → motion-on-Bocf4Smc.js.map} +1 -1
- package/dist/motion.js +2 -2
- package/dist/{rendra-provider-CeCkPafT.js → rendra-provider-Do_qWjJC.js} +3 -3
- package/dist/{rendra-provider-CeCkPafT.js.map → rendra-provider-Do_qWjJC.js.map} +1 -1
- package/dist/rich-text-editor.js +4 -3
- package/dist/rich-text-editor.js.map +1 -1
- package/dist/router-bridge.js +2 -2
- package/dist/timeline-xrMHeV92.js +1803 -0
- package/dist/timeline-xrMHeV92.js.map +1 -0
- package/dist/tokens.css +9 -1
- package/dist/tooltip-to0h6aPe.js +76 -0
- package/dist/tooltip-to0h6aPe.js.map +1 -0
- package/dist/types/components/ui/data-toolbar.d.ts +6 -1
- package/dist/types/components/ui/flow-editor.d.ts +11 -0
- package/dist/types/components/ui/flow-viewer.d.ts +58 -0
- package/dist/types/components/ui/kanban.d.ts +75 -6
- package/dist/types/flow.d.ts +3 -0
- package/dist/types/lib/flow.d.ts +121 -0
- package/dist/{use-breakpoint-CNxDwEpc.js → use-breakpoint-CM-yeDHJ.js} +2 -2
- package/dist/{use-breakpoint-CNxDwEpc.js.map → use-breakpoint-CM-yeDHJ.js.map} +1 -1
- package/dist/{use-motion-presets-DCJPBfNJ.js → use-motion-presets-I4StrsCi.js} +3 -3
- package/dist/{use-motion-presets-DCJPBfNJ.js.map → use-motion-presets-I4StrsCi.js.map} +1 -1
- package/dist/widget-grid.js +2 -2
- package/package.json +8 -1
- package/dist/empty-state-DrQjqxvp.js.map +0 -1
- package/dist/tooltip-kgsorOg6.js.map +0 -1
|
@@ -7,6 +7,20 @@ export interface KanbanColumn {
|
|
|
7
7
|
tone?: BadgeProps['tone'];
|
|
8
8
|
/** Limite de cards (WIP). Passando dele, o contador fica em alerta. */
|
|
9
9
|
limit?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Dias máximos de um card nesta etapa. Passando disso (pela `enteredColumnAt` do card), a
|
|
12
|
+
* cadência está vencida. Sem ela, a etapa nunca vence. Aparece no cabeçalho da coluna.
|
|
13
|
+
*/
|
|
14
|
+
cadenceDays?: number;
|
|
15
|
+
}
|
|
16
|
+
/** Próxima atividade agendada do card: tipo, data com hora e com quem. */
|
|
17
|
+
export interface KanbanActivity {
|
|
18
|
+
/** Ex.: "Reunião", "Ligação". Só aparece no hint do calendário. */
|
|
19
|
+
type: string;
|
|
20
|
+
/** Data e hora da atividade. */
|
|
21
|
+
at: Date;
|
|
22
|
+
/** Com quem (pessoa de contato). */
|
|
23
|
+
with?: string;
|
|
10
24
|
}
|
|
11
25
|
export interface KanbanCard {
|
|
12
26
|
id: string;
|
|
@@ -33,12 +47,36 @@ export interface KanbanCard {
|
|
|
33
47
|
meta?: string;
|
|
34
48
|
/** Valores numéricos do card, pelas chaves de valueFields (ex.: { ps: 4800, mrr: 590 }). */
|
|
35
49
|
values?: Record<string, number>;
|
|
50
|
+
/**
|
|
51
|
+
* Próxima atividade. Com ela (ou com `cadenceDays` em alguma etapa) o quadro passa a
|
|
52
|
+
* colorir o card pela situação e a mostrar o calendário no lugar do `dueDate`.
|
|
53
|
+
*/
|
|
54
|
+
activity?: KanbanActivity;
|
|
55
|
+
/**
|
|
56
|
+
* Quando o card entrou na etapa atual. Quem usa o componente atualiza esta data ao mover
|
|
57
|
+
* o card, para a contagem da cadência recomeçar.
|
|
58
|
+
*/
|
|
59
|
+
enteredColumnAt?: Date;
|
|
36
60
|
}
|
|
37
61
|
/** Valor somado no cabeçalho da coluna e mostrado no card (ex.: P&S e MRR). */
|
|
38
62
|
export interface KanbanValueField {
|
|
39
63
|
key: string;
|
|
40
64
|
label: string;
|
|
41
65
|
}
|
|
66
|
+
/** Confirmação opcional de um destino de arraste: abre um modal antes de agir. */
|
|
67
|
+
export interface KanbanDropConfirm {
|
|
68
|
+
title: string;
|
|
69
|
+
description: string;
|
|
70
|
+
/** Texto do botão. Padrão: o `label` do destino. */
|
|
71
|
+
confirmLabel?: string;
|
|
72
|
+
/** Botão destrutivo (ex.: Perder). */
|
|
73
|
+
destructive?: boolean;
|
|
74
|
+
/** Motivos a escolher; o escolhido chega como terceiro argumento de `onDropTarget`. */
|
|
75
|
+
reasons?: {
|
|
76
|
+
value: string;
|
|
77
|
+
label: string;
|
|
78
|
+
}[];
|
|
79
|
+
}
|
|
42
80
|
/**
|
|
43
81
|
* Destino de arraste (etapa A14): uma ação para onde o card vai, diferente de "outra
|
|
44
82
|
* coluna" (ex.: "Marcar como ganho", "Arquivar"). Aparece numa barra durante o arraste e
|
|
@@ -54,6 +92,8 @@ export interface KanbanDropTarget {
|
|
|
54
92
|
disabled?: boolean;
|
|
55
93
|
/** Motivo mostrado quando desabilitado; o destino recusa o solto. */
|
|
56
94
|
disabledReason?: string;
|
|
95
|
+
/** Sem ela, o destino age na hora. Com ela, abre a confirmação (mouse, toque e menu). */
|
|
96
|
+
confirm?: KanbanDropConfirm;
|
|
57
97
|
}
|
|
58
98
|
export interface KanbanProps {
|
|
59
99
|
columns: KanbanColumn[];
|
|
@@ -74,11 +114,11 @@ export interface KanbanProps {
|
|
|
74
114
|
hasMore?: (columnId: string) => boolean;
|
|
75
115
|
/** Etapas visíveis por vez no desktop; as demais pela rolagem lateral. Padrão: 5. */
|
|
76
116
|
visibleColumns?: number;
|
|
77
|
-
/** Conteúdo próprio do card, no lugar do padrão. */
|
|
117
|
+
/** Conteúdo próprio do card, no lugar do padrão (substitui também calendário e valores). */
|
|
78
118
|
renderCard?: (card: KanbanCard) => ReactNode;
|
|
79
119
|
/**
|
|
80
|
-
* Valores do card (até 2,
|
|
81
|
-
* Ex.: [{ key: 'ps', label: 'P&S' }, { key: 'mrr', label: 'MRR' }].
|
|
120
|
+
* Valores do card (até 2, empilhados no rodapé) e o total de cada um na coluna, com o
|
|
121
|
+
* percentual sobre o total do quadro. Ex.: [{ key: 'ps', label: 'P&S' }, { key: 'mrr', label: 'MRR' }].
|
|
82
122
|
*/
|
|
83
123
|
valueFields?: KanbanValueField[];
|
|
84
124
|
/** Formato dos valores. Padrão: moeda (R$ 1.250,00). */
|
|
@@ -88,11 +128,40 @@ export interface KanbanProps {
|
|
|
88
128
|
* barra durante o arraste e o menu "Mover para" passa a listar estes destinos.
|
|
89
129
|
*/
|
|
90
130
|
dropTargets?: KanbanDropTarget[];
|
|
91
|
-
/**
|
|
92
|
-
|
|
131
|
+
/**
|
|
132
|
+
* Card solto num destino da barra (ou escolhido no menu "Mover para"). `reason` é o motivo
|
|
133
|
+
* escolhido na confirmação (destinos com `confirm.reasons`).
|
|
134
|
+
*/
|
|
135
|
+
onDropTarget?: (cardId: string, targetId: string, reason?: string) => void;
|
|
136
|
+
/** Data de hoje, para o status e a cadência (injetável em teste). Padrão: agora. */
|
|
137
|
+
referenceDate?: Date;
|
|
138
|
+
/** Liga a barra do quadro: busca, filtros, totais, Customizar e Novo card. */
|
|
139
|
+
toolbar?: boolean;
|
|
140
|
+
/** "Novo card" da barra do quadro (sem coluna; o (+) da coluna segue com `onAddCard`). */
|
|
141
|
+
onNewCard?: () => void;
|
|
142
|
+
/**
|
|
143
|
+
* Chave do `localStorage` em que o Customizar guarda os campos escondidos (por navegador).
|
|
144
|
+
* Sem ela, a escolha vale só enquanto o quadro está montado.
|
|
145
|
+
*/
|
|
146
|
+
storageKey?: string;
|
|
93
147
|
'aria-label'?: string;
|
|
94
148
|
className?: string;
|
|
95
149
|
}
|
|
96
|
-
export
|
|
150
|
+
export interface KanbanCardStatus {
|
|
151
|
+
/** Fundo do card: crítico, cadência vencida, sem atividade ou normal. */
|
|
152
|
+
background: 'critical' | 'cadenceOverdue' | 'noActivity' | 'normal';
|
|
153
|
+
/** Situação do calendário: em dia, vence hoje, atrasada ou sem atividade. */
|
|
154
|
+
activity: 'onTime' | 'today' | 'late' | 'none';
|
|
155
|
+
/** Dias de calendário na etapa; `null` sem `enteredColumnAt`. */
|
|
156
|
+
daysInColumn: number | null;
|
|
157
|
+
/** Dias de atraso da atividade (0 fora de `late`). */
|
|
158
|
+
daysLate: number;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Situação do card a partir da próxima atividade e da cadência da etapa. Compara por dia de
|
|
162
|
+
* calendário; `referenceDate` é o "hoje" (injetável para teste).
|
|
163
|
+
*/
|
|
164
|
+
export declare function getKanbanCardStatus(card: KanbanCard, column: KanbanColumn | undefined, referenceDate: Date): KanbanCardStatus;
|
|
165
|
+
export declare function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard, valueFields, formatValue, pageSize, visibleColumns, onLoadMore, hasMore, dropTargets, onDropTarget, referenceDate, toolbar, onNewCard, storageKey, className, ...aria }: KanbanProps): import("react").JSX.Element;
|
|
97
166
|
/** Move um card na lista (para usar no onCardMove): devolve a lista nova. */
|
|
98
167
|
export declare function moveKanbanCard(cards: KanbanCard[], cardId: string, toColumnId: string, toIndex: number): KanbanCard[];
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { FlowEditor, type FlowEditorProps } from './components/ui/flow-editor';
|
|
2
|
+
export { FlowViewer, type FlowViewerProps } from './components/ui/flow-viewer';
|
|
3
|
+
export { parseFlow, serializeFlow, validateFlow, type Flow, type FlowBranch, type FlowEdge, type FlowIssue, type FlowNode, type FlowNodeType, type ParseResult, } from './lib/flow';
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
export type FlowNodeType = 'gatilho' | 'acao' | 'condicao' | 'espera' | 'fim';
|
|
2
|
+
export type FlowBranch = 'sim' | 'nao';
|
|
3
|
+
export type FlowWaitUnit = 'segundos' | 'minutos' | 'horas' | 'dias';
|
|
4
|
+
export interface FlowNode {
|
|
5
|
+
id: string;
|
|
6
|
+
type: FlowNodeType;
|
|
7
|
+
position: {
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
};
|
|
11
|
+
data: {
|
|
12
|
+
label: string;
|
|
13
|
+
config?: Record<string, unknown>;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export interface FlowEdge {
|
|
17
|
+
id: string;
|
|
18
|
+
source: string;
|
|
19
|
+
target: string;
|
|
20
|
+
/** Só a saída de uma condição usa o ramo. */
|
|
21
|
+
branch?: FlowBranch;
|
|
22
|
+
}
|
|
23
|
+
export interface Flow {
|
|
24
|
+
nodes: FlowNode[];
|
|
25
|
+
edges: FlowEdge[];
|
|
26
|
+
}
|
|
27
|
+
export interface FlowIssue {
|
|
28
|
+
code: string;
|
|
29
|
+
message: string;
|
|
30
|
+
nodeId?: string;
|
|
31
|
+
edgeId?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface SimulationStep {
|
|
34
|
+
nodeId: string;
|
|
35
|
+
type: FlowNodeType;
|
|
36
|
+
label: string;
|
|
37
|
+
status: 'succeeded' | 'failed' | 'skipped';
|
|
38
|
+
detail?: string;
|
|
39
|
+
}
|
|
40
|
+
export interface SimulationState {
|
|
41
|
+
status: 'idle' | 'running' | 'waiting-choice' | 'finished' | 'error';
|
|
42
|
+
steps: SimulationStep[];
|
|
43
|
+
/** Bloco que o próximo avanço executa (o bloco ativo); `null` fora da simulação. */
|
|
44
|
+
currentId: string | null;
|
|
45
|
+
issues: FlowIssue[];
|
|
46
|
+
}
|
|
47
|
+
export declare const FLOW_NODE_TYPES: readonly FlowNodeType[];
|
|
48
|
+
export declare const FLOW_WAIT_UNITS: readonly FlowWaitUnit[];
|
|
49
|
+
/** Nome do tipo de bloco, como aparece na interface. */
|
|
50
|
+
export declare const FLOW_TYPE_NAME: Record<FlowNodeType, string>;
|
|
51
|
+
/** A duração do bloco de espera ("5 minutos"), ou `null` se o config não a define. */
|
|
52
|
+
export declare function formatWait(config: Record<string, unknown> | undefined): string | null;
|
|
53
|
+
/** Texto da espera simulada: nunca espera de verdade. */
|
|
54
|
+
export declare function describeWait(config: Record<string, unknown> | undefined): string;
|
|
55
|
+
/** Nome do bloco para mensagens e rótulos: o rótulo, ou o tipo quando ele está vazio. */
|
|
56
|
+
export declare const nodeName: (n: Pick<FlowNode, "type" | "data">) => string;
|
|
57
|
+
/** Problemas do fluxo, em ordem estável: a mesma entrada dá sempre a mesma lista. */
|
|
58
|
+
export declare function validateFlow(flow: Flow): FlowIssue[];
|
|
59
|
+
/** JSON do fluxo, com a ordem das chaves fixa: o mesmo fluxo dá sempre o mesmo texto. */
|
|
60
|
+
export declare function serializeFlow(flow: Flow): string;
|
|
61
|
+
export type ParseResult = {
|
|
62
|
+
ok: true;
|
|
63
|
+
flow: Flow;
|
|
64
|
+
} | {
|
|
65
|
+
ok: false;
|
|
66
|
+
errors: string[];
|
|
67
|
+
};
|
|
68
|
+
/** Lê o JSON de um fluxo. Nunca lança; campos que o contrato não conhece são ignorados. */
|
|
69
|
+
export declare function parseFlow(text: string): ParseResult;
|
|
70
|
+
export interface AddNodeOptions {
|
|
71
|
+
label?: string;
|
|
72
|
+
/** Ids que já existiram neste fluxo (mesmo apagados): não voltam a ser usados. */
|
|
73
|
+
reservedIds?: Iterable<string>;
|
|
74
|
+
}
|
|
75
|
+
/** Acrescenta um bloco com id único e determinístico (`tipo-N`). */
|
|
76
|
+
export declare function addNode(flow: Flow, type: FlowNodeType, position: {
|
|
77
|
+
x: number;
|
|
78
|
+
y: number;
|
|
79
|
+
}, options?: AddNodeOptions): {
|
|
80
|
+
flow: Flow;
|
|
81
|
+
id: string;
|
|
82
|
+
};
|
|
83
|
+
/** Apaga o bloco e as ligações que chegam ou saem dele. */
|
|
84
|
+
export declare function removeNode(flow: Flow, id: string): Flow;
|
|
85
|
+
export declare function removeEdge(flow: Flow, id: string): Flow;
|
|
86
|
+
export declare function moveNode(flow: Flow, id: string, position: {
|
|
87
|
+
x: number;
|
|
88
|
+
y: number;
|
|
89
|
+
}): Flow;
|
|
90
|
+
/** Troca o rótulo e/ou o config do bloco (o config informado substitui o anterior). */
|
|
91
|
+
export declare function updateNodeData(flow: Flow, id: string, patch: {
|
|
92
|
+
label?: string;
|
|
93
|
+
config?: Record<string, unknown>;
|
|
94
|
+
}): Flow;
|
|
95
|
+
export type ConnectResult = {
|
|
96
|
+
ok: true;
|
|
97
|
+
flow: Flow;
|
|
98
|
+
} | {
|
|
99
|
+
ok: false;
|
|
100
|
+
reason: string;
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Liga dois blocos. A segunda saída de um bloco comum (ou do mesmo ramo da condição) substitui
|
|
104
|
+
* a primeira. Recusa, com o motivo, o que o fluxo nunca aceita.
|
|
105
|
+
*/
|
|
106
|
+
export declare function connectNodes(flow: Flow, source: string, target: string, branch?: FlowBranch): ConnectResult;
|
|
107
|
+
/**
|
|
108
|
+
* Define (ou, com `target` nulo, tira) o próximo bloco de `id`; na condição, o do ramo dado.
|
|
109
|
+
* Uma ligação recusada devolve o próprio fluxo, sem mudança.
|
|
110
|
+
*/
|
|
111
|
+
export declare function setNext(flow: Flow, id: string, target: string | null, branch?: FlowBranch): Flow;
|
|
112
|
+
/** Blocos que `id` pode ter como próximo: nunca ele mesmo nem o gatilho. */
|
|
113
|
+
export declare function nextCandidates(flow: Flow, id: string): FlowNode[];
|
|
114
|
+
export declare function resetSimulation(): SimulationState;
|
|
115
|
+
/** Começa no gatilho. Fluxo inválido não inicia: devolve `error` com os problemas. */
|
|
116
|
+
export declare function startSimulation(flow: Flow): SimulationState;
|
|
117
|
+
/**
|
|
118
|
+
* Executa o bloco ativo (um passo) e passa ao próximo. Na condição é preciso escolher o ramo:
|
|
119
|
+
* sem escolha válida nada anda. A espera é instantânea; só o texto diz quanto aguardaria.
|
|
120
|
+
*/
|
|
121
|
+
export declare function advanceSimulation(flow: Flow, state: SimulationState, choice?: FlowBranch): SimulationState;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! Rendra Design System v2.
|
|
1
|
+
/*! Rendra Design System v2.8.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-CM-yeDHJ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-breakpoint-
|
|
1
|
+
{"version":3,"file":"use-breakpoint-CM-yeDHJ.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 useMotionMode, c as getReducedMotion, l as subscribeReducedMotion } from "./motion-context-
|
|
1
|
+
/*! Rendra Design System v2.8.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
|
|
2
|
+
import { a as useMotionMode, c as getReducedMotion, l as subscribeReducedMotion } from "./motion-context-PJPj6X4g.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-I4StrsCi.js.map
|
|
@@ -1 +1 @@
|
|
|
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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"}
|
|
1
|
+
{"version":3,"file":"use-motion-presets-I4StrsCi.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.8.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
|
|
2
|
+
import { t as cn } from "./cn-BlJHpkDs.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.8.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": {
|
|
@@ -68,6 +68,10 @@
|
|
|
68
68
|
"types": "./dist/types/motion.d.ts",
|
|
69
69
|
"import": "./dist/motion.js"
|
|
70
70
|
},
|
|
71
|
+
"./flow": {
|
|
72
|
+
"types": "./dist/types/flow.d.ts",
|
|
73
|
+
"import": "./dist/flow.js"
|
|
74
|
+
},
|
|
71
75
|
"./widget-grid": {
|
|
72
76
|
"types": "./dist/types/widget-grid.d.ts",
|
|
73
77
|
"import": "./dist/widget-grid.js"
|
|
@@ -122,6 +126,8 @@
|
|
|
122
126
|
"test:visual:update": "playwright test --project=visual --update-snapshots",
|
|
123
127
|
"test:motion": "playwright test --project=motion --project=estados",
|
|
124
128
|
"test:lazy": "playwright test --project=lazy",
|
|
129
|
+
"test:flow": "playwright test --project=flow",
|
|
130
|
+
"test:kanban": "playwright test --project=kanban",
|
|
125
131
|
"test:css-layers": "playwright test --project=css-layers",
|
|
126
132
|
"test:site": "playwright test -c playwright.site.config.ts",
|
|
127
133
|
"registry:build": "node scripts/build-registry.mjs",
|
|
@@ -138,6 +144,7 @@
|
|
|
138
144
|
"@tiptap/pm": "^3.31.3",
|
|
139
145
|
"@tiptap/react": "^3.31.3",
|
|
140
146
|
"@tiptap/starter-kit": "^3.31.3",
|
|
147
|
+
"@xyflow/react": "^12.12.0",
|
|
141
148
|
"class-variance-authority": "^0.7.1",
|
|
142
149
|
"clsx": "^2.1.1",
|
|
143
150
|
"cmdk": "^1.1.1",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"empty-state-DrQjqxvp.js","names":[],"sources":["../src/brand/brand-context.ts","../src/brand/use-brand.ts","../src/components/ui/brand-feedback-icon.tsx","../src/components/ui/empty-state.tsx"],"sourcesContent":["import { createContext } from 'react'\nimport type { Shape } from '@/lib/shape'\nimport type { BrandConfig, PaletteConfig } from './types'\n\nexport type ColorMode = 'light' | 'dark' | 'system'\n\nexport interface BrandContextValue {\n brand: BrandConfig\n brands: BrandConfig[]\n setBrandId: (id: string) => void\n mode: ColorMode\n resolvedMode: 'light' | 'dark'\n setMode: (mode: ColorMode) => void\n /** Formato do template ativo (fixo por template). */\n shape: Shape\n /** Paleta de cores em uso (por padrão, a do próprio modelo). */\n palette: PaletteConfig\n palettes: PaletteConfig[]\n /** Usa a paleta de outro template; null volta às cores do próprio modelo. */\n setPaletteId: (id: string | null) => void\n /** Logotipo adequado para a sidebar com a paleta atual. */\n sidebarLogoVariant: 'light' | 'dark'\n}\n\nexport const BrandContext = createContext<BrandContextValue | null>(null)\n","import { useContext } from 'react'\nimport { BrandContext } from './brand-context'\n\nexport function useBrand() {\n const ctx = useContext(BrandContext)\n if (!ctx) throw new Error('useBrand precisa estar dentro de <BrandProvider>.')\n return ctx\n}\n","import { cva, type VariantProps } from 'class-variance-authority'\nimport { CircleCheck, CircleX, Info, TriangleAlert, type LucideIcon } from 'lucide-react'\nimport type { SVGProps } from 'react'\nimport { useBrand } from '@/brand/use-brand'\nimport type { FeedbackType } from '@/brand/types'\nimport { cn } from '@/lib/cn'\n\nconst sizes = {\n sm: 'size-icon-sm',\n md: 'size-icon-md',\n lg: 'size-icon-lg',\n xl: 'size-12',\n '2xl': 'size-16',\n} as const\n\nconst iconVariants = cva('relative inline-flex shrink-0', {\n variants: { size: sizes },\n defaultVariants: { size: 'md' },\n})\n\n/** Cor do estado (tinge o símbolo e, em statusBadge, o ícone ao lado). */\nconst stateText: Record<FeedbackType, string> = {\n success: 'text-success',\n error: 'text-destructive',\n warning: 'text-warning',\n info: 'text-info',\n}\n\n/** Ícone Lucide do selo ao lado do símbolo (statusBadge). */\nconst badgeIcons: Record<FeedbackType, LucideIcon> = {\n success: CircleCheck,\n error: CircleX,\n warning: TriangleAlert,\n info: Info,\n}\n\n/** Tamanho do ícone ao lado, proporcional ao do símbolo. */\nconst badgeIconSize: Record<keyof typeof sizes, string> = {\n sm: 'size-3',\n md: 'size-icon-sm',\n lg: 'size-icon-md',\n xl: 'size-icon-lg',\n '2xl': 'size-icon-lg',\n}\n\nconst badgeTone: Record<FeedbackType, string> = {\n success: 'bg-success text-success-foreground',\n error: 'bg-destructive text-destructive-foreground',\n warning: 'bg-warning text-warning-foreground',\n info: 'bg-info text-info-foreground',\n}\n\nexport const feedbackLabels: Record<FeedbackType, string> = {\n success: 'Sucesso',\n error: 'Erro',\n warning: 'Atenção',\n info: 'Informação',\n}\n\n/** Glifos universais de status desenhados em traço, herdando currentColor. */\nfunction StatusGlyph({\n type,\n animated,\n ...props\n}: { type: FeedbackType; animated?: boolean } & SVGProps<SVGSVGElement>) {\n // pathLength=1 normaliza o traço: o desenho anima de 1 a 0 em qualquer glifo.\n const draw = animated\n ? ({ pathLength: 1, strokeDasharray: 1, className: 'animate-draw' } as const)\n : {}\n const common = {\n viewBox: '0 0 12 12',\n fill: 'none',\n stroke: 'currentColor',\n strokeWidth: 2,\n strokeLinecap: 'round' as const,\n strokeLinejoin: 'round' as const,\n 'aria-hidden': true,\n ...props,\n }\n switch (type) {\n case 'success':\n return (\n <svg {...common}>\n <path d=\"M3 6.2 5.1 8.2 9 4\" {...draw} />\n </svg>\n )\n case 'error':\n return (\n <svg {...common}>\n <path d=\"M4 4l4 4M8 4 4 8\" {...draw} />\n </svg>\n )\n case 'warning':\n return (\n <svg {...common}>\n <path d=\"M6 3.2v3.3M6 8.8v0\" {...draw} />\n </svg>\n )\n case 'info':\n return (\n <svg {...common}>\n <path d=\"M6 3.2v0M6 5.5v3.3\" {...draw} />\n </svg>\n )\n }\n}\n\nexport interface BrandFeedbackIconProps extends VariantProps<typeof iconVariants> {\n type: FeedbackType\n /** Texto para leitores de tela. Sem ele o ícone é decorativo (o texto ao lado informa). */\n label?: string\n /**\n * Anima a entrada: o símbolo entra com mola e o glifo se desenha (check se formando,\n * X se riscando). O erro treme ao final. Respeita reduzir movimento.\n * Troque a key do componente para repetir a animação.\n */\n animated?: boolean\n /**\n * Cor do símbolo. `state` (padrão): a cor do estado (verde, vermelho, amarelo, azul).\n * `brand`: a cor primária da marca (`text-primary-text`); o selo de estado mantém a cor do\n * estado, para o significado não depender só da cor.\n */\n symbolTone?: 'state' | 'brand'\n /**\n * `false` (padrão): selo de estado sobreposto ao símbolo. `true`: o ícone do estado\n * (Lucide, na cor do estado) fica ao lado do símbolo, no lugar do selo sobreposto. Com um\n * SVG próprio em `brand.feedbackIcons[type]`, o SVG vence e nenhum selo é desenhado.\n */\n statusBadge?: boolean\n /**\n * Só vale com `animated`. `pop` (padrão): entra com mola, o glifo se desenha e o erro\n * treme. `encaixe`: entra em 240 ms, curva de saída suave, sem quique, sem desenho e sem\n * tremor. Com \"reduzir movimento\" do sistema, nenhuma animação roda.\n */\n animation?: 'pop' | 'encaixe'\n className?: string\n}\n\n/**\n * Ícone de feedback da marca: o símbolo da marca em currentColor, tingido pela cor\n * semântica, com um selo de status para que o significado não dependa só da cor.\n * Cada tipo pode ser substituído por um SVG próprio em brand.config.ts (feedbackIcons).\n */\nexport function BrandFeedbackIcon({\n type,\n size,\n label,\n animated = false,\n symbolTone = 'state',\n statusBadge = false,\n animation = 'pop',\n className,\n}: BrandFeedbackIconProps) {\n const { brand } = useBrand()\n const Custom = brand.feedbackIcons?.[type]\n const Symbol = brand.symbol\n const a11y = label\n ? ({ role: 'img', 'aria-label': label } as const)\n : ({ 'aria-hidden': true } as const)\n const encaixe = animation === 'encaixe'\n // Com `symbolTone=\"state\"` o texto do estado fica na raiz (como sempre); com `brand` sai da raiz.\n const rootTone = symbolTone === 'state' ? stateText[type] : undefined\n const symbolTonal = symbolTone === 'brand' && 'text-primary-text'\n const symbolAnim = animated && (encaixe ? 'animate-encaixe' : 'animate-pop')\n const badgeAnim = animated && (encaixe ? 'animate-encaixe' : 'animate-pop anim-delay-1')\n const BadgeIcon = badgeIcons[type]\n const sideBadge = statusBadge && !Custom\n\n return (\n <span\n data-slot=\"feedback-icon\"\n data-rendra=\"BFI-001\"\n className={cn(\n sideBadge ? 'relative inline-flex shrink-0 items-center gap-1' : iconVariants({ size }),\n rootTone,\n animated && !encaixe && type === 'error' && 'animate-shake',\n className,\n )}\n {...a11y}\n >\n {Custom ? (\n <Custom className={cn('size-full', symbolTonal, symbolAnim)} />\n ) : sideBadge ? (\n <>\n <Symbol className={cn(sizes[size ?? 'md'], symbolTonal, symbolAnim)} />\n <BadgeIcon\n aria-hidden\n className={cn('shrink-0', badgeIconSize[size ?? 'md'], stateText[type], badgeAnim)}\n />\n </>\n ) : (\n <>\n <Symbol className={cn('size-full mask-status-cutout', symbolTonal, symbolAnim)} />\n <span\n className={cn(\n 'absolute right-0 bottom-0 flex size-1/2 items-center justify-center rounded-full',\n badgeTone[type],\n badgeAnim,\n )}\n >\n <StatusGlyph type={type} animated={animated && !encaixe} className=\"size-full\" />\n </span>\n </>\n )}\n </span>\n )\n}\n","import type { ElementType, ReactNode } from 'react'\nimport type { FeedbackType } from '@/brand/types'\nimport { BrandFeedbackIcon } from '@/components/ui/brand-feedback-icon'\nimport { cn } from '@/lib/cn'\nimport { useMotionLib, useMotionPresets } from '@/lib/motion'\n\nexport interface EmptyStateProps {\n title: string\n description?: ReactNode\n /** Tipo do ícone de feedback da marca. info para \"sem dados\", error para falha. */\n type?: FeedbackType\n /** Ações: no máximo uma principal e uma secundária. */\n actions?: ReactNode\n /** compact: dentro de tabela ou card pequeno. */\n size?: 'default' | 'compact'\n /**\n * Classes extras, que vencem as do componente. Para zerar o respiro vertical (por exemplo,\n * dentro de um card que já tem o seu) use `className=\"py-0 md:py-0\"`.\n */\n className?: string\n}\n\n/** Estado vazio (e de erro) com o ícone de feedback da marca. */\nexport function EmptyState({\n title,\n description,\n type = 'info',\n actions,\n size = 'default',\n className,\n}: EmptyStateProps) {\n const lib = useMotionLib()\n const on = lib !== null\n const presets = useMotionPresets()\n // Em `on` as quatro partes (ícone, título, descrição e ações) sobem em cascata de 60 ms, cada\n // uma com o deslize curto; a raiz em si não anima. Estado vazio é cota de encanto: ocasional,\n // sem teclado no caminho. Em `off` o HTML é o de sempre.\n const Icon: ElementType = on ? lib.m.span : 'span'\n const Title: ElementType = on ? lib.m.p : 'p'\n const Description: ElementType = on ? lib.m.p : 'p'\n const Actions: ElementType = on ? lib.m.div : 'div'\n const part = (index: number) => {\n if (!on) return {}\n const enter = presets.slide('bottom', 'short')\n return { ...enter, transition: { ...enter.transition, ...presets.stagger(index) } }\n }\n return (\n <div\n data-rendra=\"VAZ-001\"\n className={cn(\n 'flex flex-col items-center justify-center gap-4 text-center',\n size === 'compact' ? 'px-4 py-8' : 'px-4 py-12 md:py-16',\n className,\n )}\n >\n <Icon className=\"relative flex items-center justify-center\" {...part(0)}>\n <span aria-hidden className=\"absolute size-16 rounded-full bg-gradient-soft\" />\n <BrandFeedbackIcon\n type={type}\n size={size === 'compact' ? 'xl' : '2xl'}\n className=\"relative\"\n />\n </Icon>\n <div className=\"flex w-full flex-col gap-1\">\n <Title className=\"text-base font-semibold wrap-break-word\" {...part(1)}>\n {title}\n </Title>\n {description && (\n <Description className=\"text-sm wrap-break-word text-muted-foreground\" {...part(2)}>\n {description}\n </Description>\n )}\n </div>\n {actions && (\n <Actions className=\"flex flex-wrap justify-center gap-3\" {...part(3)}>\n {actions}\n </Actions>\n )}\n </div>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tooltip-kgsorOg6.js","names":[],"sources":["../src/components/ui/dropdown-menu.tsx","../src/components/ui/tooltip.tsx"],"sourcesContent":["import { Check, ChevronRight } from 'lucide-react'\nimport { DropdownMenu as D } from 'radix-ui'\nimport { createContext, useContext, useState, type ComponentProps } from 'react'\nimport { cn } from '@/lib/cn'\nimport { useMotionLib, 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 lib = useMotionLib()\n const presets = useMotionPresets()\n\n if (lib && open !== null && !asChild) {\n return (\n <lib.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 <lib.m.div {...presets.open()}>{children}</lib.m.div>\n </D.Content>\n </D.Portal>\n )}\n </lib.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 lib = useMotionLib()\n const presets = useMotionPresets()\n\n if (lib && open !== null && !asChild) {\n return (\n <lib.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 <lib.m.div {...presets.open()}>{children}</lib.m.div>\n </D.SubContent>\n </D.Portal>\n )}\n </lib.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 { Tooltip as T } from 'radix-ui'\nimport { forwardRef, useState, type ComponentPropsWithoutRef, type ReactNode } from 'react'\nimport { cn } from '@/lib/cn'\nimport { useMotionLib, useMotionOn, useMotionPresets } from '@/lib/motion'\nimport type { RendraMotion } from '@/lib/motion/motion-on'\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<RendraMotion['m']['div']>>(\n function TooltipBody(props, ref) {\n const { m } = useMotionOn()\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 lib = useMotionLib()\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 (lib) {\n return (\n <T.Root open={open} onOpenChange={setOpen}>\n <T.Trigger asChild>{children}</T.Trigger>\n <lib.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 </lib.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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"}
|