@rendra-ui/web 2.1.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/LICENSE +21 -0
- package/README.md +433 -0
- package/bin/rendra.mjs +114 -0
- package/dist/base.css +246 -0
- package/dist/button-DIcpJwK9.js +143 -0
- package/dist/button-DIcpJwK9.js.map +1 -0
- package/dist/chart.js +520 -0
- package/dist/chart.js.map +1 -0
- package/dist/cli/auditar.js +125 -0
- package/dist/cli/auditar.js.map +1 -0
- package/dist/cli/codigos.js +15 -0
- package/dist/cli/codigos.js.map +1 -0
- package/dist/cli/help.js +17 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/trocar.js +242 -0
- package/dist/cli/trocar.js.map +1 -0
- package/dist/cli/typescript-loader.js +27 -0
- package/dist/cli/typescript-loader.js.map +1 -0
- package/dist/cn-DVPheE99.js +22 -0
- package/dist/cn-DVPheE99.js.map +1 -0
- package/dist/components-Cm2ezlPT.js +800 -0
- package/dist/components-Cm2ezlPT.js.map +1 -0
- package/dist/components.css +3365 -0
- package/dist/document-viewer.js +204 -0
- package/dist/document-viewer.js.map +1 -0
- package/dist/empty-state-DtyZAfYb.js +168 -0
- package/dist/empty-state-DtyZAfYb.js.map +1 -0
- package/dist/index.js +10530 -0
- package/dist/index.js.map +1 -0
- package/dist/rendra-provider-cCnquOZy.js +88 -0
- package/dist/rendra-provider-cCnquOZy.js.map +1 -0
- package/dist/rich-text-editor.js +439 -0
- package/dist/rich-text-editor.js.map +1 -0
- package/dist/router-bridge.js +51 -0
- package/dist/router-bridge.js.map +1 -0
- package/dist/tokens.css +732 -0
- package/dist/tooltip-DyeuGPCc.js +105 -0
- package/dist/tooltip-DyeuGPCc.js.map +1 -0
- package/dist/types/brand/apply-theme.d.ts +9 -0
- package/dist/types/brand/brand-context.d.ts +21 -0
- package/dist/types/brand/brand-provider.d.ts +49 -0
- package/dist/types/brand/palette.d.ts +63 -0
- package/dist/types/brand/public.d.ts +6 -0
- package/dist/types/brand/theme.d.ts +80 -0
- package/dist/types/brand/types.d.ts +54 -0
- package/dist/types/brand/use-brand.d.ts +1 -0
- package/dist/types/catalog/components.d.ts +81 -0
- package/dist/types/chart.d.ts +1 -0
- package/dist/types/components/app-shell/app-shell.d.ts +36 -0
- package/dist/types/components/app-shell/command-search.d.ts +1 -0
- package/dist/types/components/app-shell/header.d.ts +1 -0
- package/dist/types/components/app-shell/layout.d.ts +53 -0
- package/dist/types/components/app-shell/mega-menu.d.ts +1 -0
- package/dist/types/components/app-shell/navigation-utils.d.ts +18 -0
- package/dist/types/components/app-shell/notifications.d.ts +6 -0
- package/dist/types/components/app-shell/shell-context.d.ts +48 -0
- package/dist/types/components/app-shell/sidebar.d.ts +1 -0
- package/dist/types/components/app-shell/types.d.ts +53 -0
- package/dist/types/components/layout/index.d.ts +4 -0
- package/dist/types/components/layout/page-header.d.ts +38 -0
- package/dist/types/components/layout/primitives.d.ts +71 -0
- package/dist/types/components/layout/tokens.d.ts +43 -0
- package/dist/types/components/rendra-provider.d.ts +48 -0
- package/dist/types/components/rendra-router-bridge.d.ts +18 -0
- package/dist/types/components/ui/accordion.d.ts +16 -0
- package/dist/types/components/ui/action-bar.d.ts +35 -0
- package/dist/types/components/ui/alert.d.ts +26 -0
- package/dist/types/components/ui/avatar.d.ts +23 -0
- package/dist/types/components/ui/badge.d.ts +15 -0
- package/dist/types/components/ui/brand-feedback-icon.d.ts +26 -0
- package/dist/types/components/ui/brand-logo.d.ts +8 -0
- package/dist/types/components/ui/breadcrumb.d.ts +19 -0
- package/dist/types/components/ui/button-group.d.ts +27 -0
- package/dist/types/components/ui/button.d.ts +30 -0
- package/dist/types/components/ui/calendar.d.ts +34 -0
- package/dist/types/components/ui/card.d.ts +32 -0
- package/dist/types/components/ui/chart.d.ts +57 -0
- package/dist/types/components/ui/chat.d.ts +137 -0
- package/dist/types/components/ui/checkbox.d.ts +37 -0
- package/dist/types/components/ui/checklist.d.ts +16 -0
- package/dist/types/components/ui/color-picker.d.ts +13 -0
- package/dist/types/components/ui/data-toolbar.d.ts +37 -0
- package/dist/types/components/ui/date-picker.d.ts +41 -0
- package/dist/types/components/ui/document-viewer.d.ts +19 -0
- package/dist/types/components/ui/drawer.d.ts +30 -0
- package/dist/types/components/ui/dropdown-menu.d.ts +20 -0
- package/dist/types/components/ui/empty-state.d.ts +15 -0
- package/dist/types/components/ui/error-page.d.ts +13 -0
- package/dist/types/components/ui/field.d.ts +42 -0
- package/dist/types/components/ui/form.d.ts +42 -0
- package/dist/types/components/ui/image-cropper.d.ts +55 -0
- package/dist/types/components/ui/image-viewer.d.ts +14 -0
- package/dist/types/components/ui/info-hint.d.ts +9 -0
- package/dist/types/components/ui/input.d.ts +91 -0
- package/dist/types/components/ui/kanban.d.ts +98 -0
- package/dist/types/components/ui/list.d.ts +31 -0
- package/dist/types/components/ui/modal.d.ts +27 -0
- package/dist/types/components/ui/otp-input.d.ts +17 -0
- package/dist/types/components/ui/overlay-shell.d.ts +14 -0
- package/dist/types/components/ui/pagination.d.ts +18 -0
- package/dist/types/components/ui/picker-panel.d.ts +24 -0
- package/dist/types/components/ui/popover.d.ts +12 -0
- package/dist/types/components/ui/progress.d.ts +16 -0
- package/dist/types/components/ui/qr-code.d.ts +13 -0
- package/dist/types/components/ui/radio-group.d.ts +27 -0
- package/dist/types/components/ui/rating.d.ts +19 -0
- package/dist/types/components/ui/rendra-credit.d.ts +12 -0
- package/dist/types/components/ui/repeatable-field.d.ts +22 -0
- package/dist/types/components/ui/rich-text-editor.d.ts +21 -0
- package/dist/types/components/ui/select.d.ts +65 -0
- package/dist/types/components/ui/separator.d.ts +7 -0
- package/dist/types/components/ui/skeleton.d.ts +3 -0
- package/dist/types/components/ui/slider.d.ts +18 -0
- package/dist/types/components/ui/sortable-handle.d.ts +16 -0
- package/dist/types/components/ui/spinner.d.ts +7 -0
- package/dist/types/components/ui/stat-card.d.ts +20 -0
- package/dist/types/components/ui/switch.d.ts +15 -0
- package/dist/types/components/ui/table.d.ts +134 -0
- package/dist/types/components/ui/tabs.d.ts +25 -0
- package/dist/types/components/ui/textarea.d.ts +10 -0
- package/dist/types/components/ui/timeline.d.ts +18 -0
- package/dist/types/components/ui/toast.d.ts +18 -0
- package/dist/types/components/ui/tooltip.d.ts +17 -0
- package/dist/types/components/ui/upload.d.ts +50 -0
- package/dist/types/components/ui/widget-grid.d.ts +22 -0
- package/dist/types/components/ui/wizard.d.ts +38 -0
- package/dist/types/document-viewer.d.ts +1 -0
- package/dist/types/hooks/use-breakpoint.d.ts +21 -0
- package/dist/types/hooks/use-debounced-value.d.ts +5 -0
- package/dist/types/hooks/use-fill-height.d.ts +6 -0
- package/dist/types/hooks/use-lookup.d.ts +30 -0
- package/dist/types/hooks/use-reduced-motion.d.ts +1 -0
- package/dist/types/index.d.ts +76 -0
- package/dist/types/lib/cn.d.ts +2 -0
- package/dist/types/lib/contrast.d.ts +2 -0
- package/dist/types/lib/control.d.ts +20 -0
- package/dist/types/lib/lookup.d.ts +22 -0
- package/dist/types/lib/masks.d.ts +46 -0
- package/dist/types/lib/qr-encode.d.ts +48 -0
- package/dist/types/lib/shape.d.ts +8 -0
- package/dist/types/lib/sortable.d.ts +72 -0
- package/dist/types/lib/validators.d.ts +14 -0
- package/dist/types/rendra-router-bridge.d.ts +1 -0
- package/dist/types/rich-text-editor.d.ts +1 -0
- package/dist/types/widget-grid.d.ts +1 -0
- package/dist/use-breakpoint-BmXOZtF9.js +49 -0
- package/dist/use-breakpoint-BmXOZtF9.js.map +1 -0
- package/dist/widget-grid.js +118 -0
- package/dist/widget-grid.js.map +1 -0
- package/package.json +182 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/*! Rendra Design System v2.1.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
|
|
2
|
+
import { t as cn } from "./cn-DVPheE99.js";
|
|
3
|
+
import { Check, ChevronRight } from "lucide-react";
|
|
4
|
+
import { DropdownMenu, Tooltip } from "radix-ui";
|
|
5
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
//#region src/components/ui/dropdown-menu.tsx
|
|
7
|
+
var DropdownMenu$1 = DropdownMenu.Root;
|
|
8
|
+
var DropdownMenuTrigger = DropdownMenu.Trigger;
|
|
9
|
+
var DropdownMenuGroup = DropdownMenu.Group;
|
|
10
|
+
var DropdownMenuSub = DropdownMenu.Sub;
|
|
11
|
+
var DropdownMenuRadioGroup = DropdownMenu.RadioGroup;
|
|
12
|
+
var panel = "z-50 w-max min-w-3xs max-w-popover overflow-hidden rounded-surface border bg-popover p-1 text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95";
|
|
13
|
+
var item = "relative flex min-h-touch cursor-pointer items-center gap-2 rounded-item px-3 text-sm outline-none select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-highlighted:bg-accent data-highlighted:text-accent-foreground md:min-h-0 md:py-2 [&_svg]:size-icon-sm [&_svg]:shrink-0 [&_svg]:text-muted-foreground";
|
|
14
|
+
function DropdownMenuContent({ className, sideOffset = 8, ...props }) {
|
|
15
|
+
return /* @__PURE__ */ jsx(DropdownMenu.Portal, { children: /* @__PURE__ */ jsx(DropdownMenu.Content, {
|
|
16
|
+
sideOffset,
|
|
17
|
+
collisionPadding: 16,
|
|
18
|
+
"data-rendra": "DDM-001",
|
|
19
|
+
className: cn(panel, className),
|
|
20
|
+
...props
|
|
21
|
+
}) });
|
|
22
|
+
}
|
|
23
|
+
function DropdownMenuItem({ className, destructive, ...props }) {
|
|
24
|
+
return /* @__PURE__ */ jsx(DropdownMenu.Item, {
|
|
25
|
+
className: cn(item, destructive && "text-destructive data-highlighted:bg-destructive-soft data-highlighted:text-destructive-soft-foreground [&_svg]:text-current", className),
|
|
26
|
+
...props
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function DropdownMenuCheckboxItem({ className, children, ...props }) {
|
|
30
|
+
return /* @__PURE__ */ jsxs(DropdownMenu.CheckboxItem, {
|
|
31
|
+
className: cn(item, "pl-8", className),
|
|
32
|
+
...props,
|
|
33
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
34
|
+
className: "absolute left-2 flex size-icon-sm items-center justify-center",
|
|
35
|
+
children: /* @__PURE__ */ jsx(DropdownMenu.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, { className: "text-primary-text" }) })
|
|
36
|
+
}), children]
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function DropdownMenuRadioItem({ className, children, ...props }) {
|
|
40
|
+
return /* @__PURE__ */ jsxs(DropdownMenu.RadioItem, {
|
|
41
|
+
className: cn(item, "pl-8", className),
|
|
42
|
+
...props,
|
|
43
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
44
|
+
className: "absolute left-2 flex size-icon-sm items-center justify-center",
|
|
45
|
+
children: /* @__PURE__ */ jsx(DropdownMenu.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, { className: "text-primary-text" }) })
|
|
46
|
+
}), children]
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function DropdownMenuLabel({ className, ...props }) {
|
|
50
|
+
return /* @__PURE__ */ jsx(DropdownMenu.Label, {
|
|
51
|
+
className: cn("px-2 py-2 text-xs font-medium text-muted-foreground", className),
|
|
52
|
+
...props
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function DropdownMenuSeparator({ className, ...props }) {
|
|
56
|
+
return /* @__PURE__ */ jsx(DropdownMenu.Separator, {
|
|
57
|
+
className: cn("-mx-1 my-1 h-px bg-border", className),
|
|
58
|
+
...props
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function DropdownMenuSubTrigger({ className, children, ...props }) {
|
|
62
|
+
return /* @__PURE__ */ jsxs(DropdownMenu.SubTrigger, {
|
|
63
|
+
className: cn(item, "data-[state=open]:bg-accent", className),
|
|
64
|
+
...props,
|
|
65
|
+
children: [children, /* @__PURE__ */ jsx(ChevronRight, { className: "ml-auto" })]
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function DropdownMenuSubContent({ className, ...props }) {
|
|
69
|
+
return /* @__PURE__ */ jsx(DropdownMenu.Portal, { children: /* @__PURE__ */ jsx(DropdownMenu.SubContent, {
|
|
70
|
+
collisionPadding: 16,
|
|
71
|
+
className: cn(panel, className),
|
|
72
|
+
...props
|
|
73
|
+
}) });
|
|
74
|
+
}
|
|
75
|
+
//#endregion
|
|
76
|
+
//#region src/components/ui/tooltip.tsx
|
|
77
|
+
/**
|
|
78
|
+
* Tooltip: só para informação complementar, nunca essencial (não existe hover no toque).
|
|
79
|
+
* Informação essencial vai em texto de ajuda visível ou em Popover acionado por toque.
|
|
80
|
+
*/
|
|
81
|
+
function TooltipProvider({ children }) {
|
|
82
|
+
return /* @__PURE__ */ jsx(Tooltip.Provider, {
|
|
83
|
+
delayDuration: 300,
|
|
84
|
+
skipDelayDuration: 150,
|
|
85
|
+
children
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
function Tooltip$1({ content, children, side = "top", disabled }) {
|
|
89
|
+
if (disabled) return /* @__PURE__ */ jsx(Fragment, { children });
|
|
90
|
+
return /* @__PURE__ */ jsxs(Tooltip.Root, { children: [/* @__PURE__ */ jsx(Tooltip.Trigger, {
|
|
91
|
+
asChild: true,
|
|
92
|
+
children
|
|
93
|
+
}), /* @__PURE__ */ jsx(Tooltip.Portal, { children: /* @__PURE__ */ jsx(Tooltip.Content, {
|
|
94
|
+
side,
|
|
95
|
+
sideOffset: 8,
|
|
96
|
+
collisionPadding: 16,
|
|
97
|
+
"data-rendra": "TIP-001",
|
|
98
|
+
className: cn("z-50 max-w-xs rounded-control bg-foreground px-3 py-2 text-xs font-medium text-background", "animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0"),
|
|
99
|
+
children: content
|
|
100
|
+
}) })] });
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
export { DropdownMenuContent as a, DropdownMenuLabel as c, DropdownMenuSeparator as d, DropdownMenuSub as f, DropdownMenuTrigger as h, DropdownMenuCheckboxItem as i, DropdownMenuRadioGroup as l, DropdownMenuSubTrigger as m, TooltipProvider as n, DropdownMenuGroup as o, DropdownMenuSubContent as p, DropdownMenu$1 as r, DropdownMenuItem as s, Tooltip$1 as t, DropdownMenuRadioItem as u };
|
|
104
|
+
|
|
105
|
+
//# sourceMappingURL=tooltip-DyeuGPCc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tooltip-DyeuGPCc.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 type { ComponentProps } from 'react'\nimport { cn } from '@/lib/cn'\n\nexport const DropdownMenu = D.Root\nexport const DropdownMenuTrigger = D.Trigger\nexport const DropdownMenuGroup = D.Group\nexport const DropdownMenuSub = D.Sub\nexport const DropdownMenuRadioGroup = D.RadioGroup\n\nconst panel =\n 'z-50 w-max min-w-3xs max-w-popover overflow-hidden rounded-surface border bg-popover p-1 text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95'\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 ...props\n}: ComponentProps<typeof D.Content>) {\n return (\n <D.Portal>\n <D.Content\n sideOffset={sideOffset}\n collisionPadding={16}\n data-rendra=\"DDM-001\"\n className={cn(panel, className)}\n {...props}\n />\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 ...props\n}: ComponentProps<typeof D.SubContent>) {\n return (\n <D.Portal>\n <D.SubContent collisionPadding={16} className={cn(panel, className)} {...props} />\n </D.Portal>\n )\n}\n","import { Tooltip as T } from 'radix-ui'\nimport type { ReactNode } from 'react'\nimport { cn } from '@/lib/cn'\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\nexport function Tooltip({ content, children, side = 'top', disabled }: TooltipProps) {\n if (disabled) return <>{children}</>\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 'z-50 max-w-xs rounded-control bg-foreground px-3 py-2 text-xs font-medium text-background',\n 'animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0',\n )}\n >\n {content}\n </T.Content>\n </T.Portal>\n </T.Root>\n )\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ThemeResult } from './theme';
|
|
2
|
+
export interface ApplyThemeOptions {
|
|
3
|
+
/** Default: document.documentElement (o próprio <html>, como applyPalette hoje). */
|
|
4
|
+
target?: HTMLElement;
|
|
5
|
+
/** Seletor do claro; o escuro é `${selector}.dark`. Default: deriva de target/id. */
|
|
6
|
+
selector?: string;
|
|
7
|
+
}
|
|
8
|
+
/** Aplica no DOM o resultado de createTheme. Sem opções, reproduz applyPalette(seed) de hoje. */
|
|
9
|
+
export declare function applyTheme(theme: ThemeResult, options?: ApplyThemeOptions, doc?: Document): void;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Shape } from '../lib/shape';
|
|
2
|
+
import type { BrandConfig, PaletteConfig } from './types';
|
|
3
|
+
export type ColorMode = 'light' | 'dark' | 'system';
|
|
4
|
+
export interface BrandContextValue {
|
|
5
|
+
brand: BrandConfig;
|
|
6
|
+
brands: BrandConfig[];
|
|
7
|
+
setBrandId: (id: string) => void;
|
|
8
|
+
mode: ColorMode;
|
|
9
|
+
resolvedMode: 'light' | 'dark';
|
|
10
|
+
setMode: (mode: ColorMode) => void;
|
|
11
|
+
/** Formato do template ativo (fixo por template). */
|
|
12
|
+
shape: Shape;
|
|
13
|
+
/** Paleta de cores em uso (por padrão, a do próprio modelo). */
|
|
14
|
+
palette: PaletteConfig;
|
|
15
|
+
palettes: PaletteConfig[];
|
|
16
|
+
/** Usa a paleta de outro template; null volta às cores do próprio modelo. */
|
|
17
|
+
setPaletteId: (id: string | null) => void;
|
|
18
|
+
/** Logotipo adequado para a sidebar com a paleta atual. */
|
|
19
|
+
sidebarLogoVariant: 'light' | 'dark';
|
|
20
|
+
}
|
|
21
|
+
export declare const BrandContext: import("react").Context<BrandContextValue | null>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type ColorMode } from './brand-context';
|
|
3
|
+
import type { ThemeResult } from './theme';
|
|
4
|
+
import type { BrandConfig, PaletteConfig } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* Armazenamento plugável: get/set simples, para trocar o localStorage padrão por outra fonte
|
|
7
|
+
* (cookie, backend...), ou desligar com `false`.
|
|
8
|
+
* `remove` é opcional: quando ausente (armazenamento customizado antigo, sem essa peça),
|
|
9
|
+
* `clearKey` cai de volta em `set(key, '')`, para não quebrar quem já implementou só get/set.
|
|
10
|
+
*/
|
|
11
|
+
export interface BrandStorage {
|
|
12
|
+
get(key: string): string | null;
|
|
13
|
+
set(key: string, value: string): void;
|
|
14
|
+
remove?(key: string): void;
|
|
15
|
+
}
|
|
16
|
+
interface BrandProviderProps {
|
|
17
|
+
brands: BrandConfig[];
|
|
18
|
+
/** Paletas disponíveis. Padrão: uma por modelo. */
|
|
19
|
+
palettes?: PaletteConfig[];
|
|
20
|
+
defaultBrand: BrandConfig;
|
|
21
|
+
children: ReactNode;
|
|
22
|
+
/**
|
|
23
|
+
* Tema aplicado em tempo de execução (resultado de createTheme, C5). Aplica sem exigir um id
|
|
24
|
+
* cadastrado em palettes.ts: o data-palette (ou data-rendra-root, com `target`) recebe o id
|
|
25
|
+
* do próprio tema.
|
|
26
|
+
*/
|
|
27
|
+
theme?: ThemeResult;
|
|
28
|
+
/** Força um modo (útil no Storybook e nos testes). */
|
|
29
|
+
forcedMode?: 'light' | 'dark';
|
|
30
|
+
/** Força uma marca pelo id (útil no Storybook e nos testes). */
|
|
31
|
+
forcedBrandId?: string;
|
|
32
|
+
/** Força uma paleta pelo id (útil no Storybook). */
|
|
33
|
+
forcedPaletteId?: string;
|
|
34
|
+
/** Modo controlado; sem esta prop, o provider guarda o próprio estado (comportamento de hoje). */
|
|
35
|
+
mode?: ColorMode;
|
|
36
|
+
onModeChange?(mode: ColorMode): void;
|
|
37
|
+
/** Marca controlada; sem esta prop, o provider guarda o próprio estado. */
|
|
38
|
+
brandId?: string;
|
|
39
|
+
onBrandIdChange?(id: string): void;
|
|
40
|
+
/** Paleta controlada (null volta às cores do próprio modelo); sem esta prop, estado próprio. */
|
|
41
|
+
paletteId?: string | null;
|
|
42
|
+
onPaletteIdChange?(id: string | null): void;
|
|
43
|
+
/** Armazenamento da preferência; false desliga a persistência. Padrão: localStorage. */
|
|
44
|
+
storage?: BrandStorage | false;
|
|
45
|
+
/** Contêiner onde a marca é aplicada (data-*, tema). Padrão: document.documentElement. */
|
|
46
|
+
target?: HTMLElement;
|
|
47
|
+
}
|
|
48
|
+
export declare function BrandProvider({ brands, palettes: palettesProp, defaultBrand, children, theme, forcedMode, forcedBrandId, forcedPaletteId, mode: modeProp, onModeChange, brandId: brandIdProp, onBrandIdChange, paletteId: paletteIdProp, onPaletteIdChange, storage: storageProp, target, }: BrandProviderProps): import("react").JSX.Element;
|
|
49
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export interface PaletteSeeds {
|
|
2
|
+
/** Identificador usado em data-palette no <html> (ex.: "safira", "cliente-42"). */
|
|
3
|
+
id: string;
|
|
4
|
+
/** Nome curto exibido nos seletores. */
|
|
5
|
+
name: string;
|
|
6
|
+
primary: string;
|
|
7
|
+
primaryHover: string;
|
|
8
|
+
secondary: string;
|
|
9
|
+
secondaryHover: string;
|
|
10
|
+
/** Degradê da marca (sidebar, painel do login, destaque): luz, meio e fundo. */
|
|
11
|
+
gradient: [string, string, string];
|
|
12
|
+
/**
|
|
13
|
+
* Texto sobre a primária e a secundária. 'auto' (padrão) escolhe o que passa AA (branco
|
|
14
|
+
* ou escuro); 'light' força texto branco e escurece a cor até passar; 'dark', o contrário.
|
|
15
|
+
*/
|
|
16
|
+
onPrimary?: TextOn;
|
|
17
|
+
onSecondary?: TextOn;
|
|
18
|
+
}
|
|
19
|
+
export type TextOn = 'auto' | 'light' | 'dark';
|
|
20
|
+
export type PaletteVars = Record<string, string>;
|
|
21
|
+
export interface Palette {
|
|
22
|
+
seeds: PaletteSeeds;
|
|
23
|
+
light: PaletteVars;
|
|
24
|
+
dark: PaletteVars;
|
|
25
|
+
/** Logotipo adequado sobre a sidebar desta paleta. */
|
|
26
|
+
sidebarLogo: 'light' | 'dark';
|
|
27
|
+
/** Ajustes feitos para passar AA (ex.: "secundária escurecida de #EA600D para #C94F0A"). */
|
|
28
|
+
adjustments: string[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Branco e tinta escura de referência. Exportados para o ColorPicker (A1) escolher, por
|
|
32
|
+
* contraste, a cor do check sobre uma amostra livre do usuário (que não é do tema, então
|
|
33
|
+
* não tem um par claro/escuro pronto): nenhum componente de fora de src/brand pode ter um
|
|
34
|
+
* hexadecimal literal, então a comparação usa estas constantes em vez de repetir a cor.
|
|
35
|
+
* O mesmo par vive em CSS como --rendra-swatch-check-light e --rendra-swatch-check-dark
|
|
36
|
+
* (src/styles/globals.css); mude os dois lados juntos.
|
|
37
|
+
*/
|
|
38
|
+
export declare const WHITE = "#ffffff";
|
|
39
|
+
/** Texto escuro padrão (o mesmo --foreground do theme.css). */
|
|
40
|
+
export declare const INK = "#0b1d37";
|
|
41
|
+
/** Mistura em sRGB, como color-mix(in srgb): t = quanto de b entra (0 a 1). */
|
|
42
|
+
export declare function mix(a: string, b: string, t: number): string;
|
|
43
|
+
/**
|
|
44
|
+
* Amostras padrão do ColorPicker (A1): um ponto de partida variado, sem relação com a
|
|
45
|
+
* paleta da marca. Hexadecimal fixo só pode existir aqui dentro (src/brand); o componente
|
|
46
|
+
* (fora daqui) sempre recebe a lista por import, nunca com a cor escrita nele.
|
|
47
|
+
*/
|
|
48
|
+
export declare const COLOR_PICKER_SWATCHES: string[];
|
|
49
|
+
/** Contraste WCAG entre duas cores #RRGGBB. */
|
|
50
|
+
export declare function contrast(a: string, b: string): number;
|
|
51
|
+
/** Gera as duas versões (claro e escuro) da paleta a partir das sementes. */
|
|
52
|
+
export declare function createPalette(seeds: PaletteSeeds): Palette;
|
|
53
|
+
/**
|
|
54
|
+
* CSS da paleta. `isDefault` também aplica a paleta quando o <html> ainda não tem
|
|
55
|
+
* data-palette (primeira pintura).
|
|
56
|
+
*/
|
|
57
|
+
export declare function paletteCss(palette: Palette, isDefault?: boolean): string;
|
|
58
|
+
/**
|
|
59
|
+
* White label em tempo de execução: gera a paleta de um cliente e a injeta na página
|
|
60
|
+
* (um <style> por paleta), sem build. Depois é só usar data-palette com o id dela.
|
|
61
|
+
* Devolve a paleta gerada, com os ajustes de contraste feitos.
|
|
62
|
+
*/
|
|
63
|
+
export declare function applyPalette(seeds: PaletteSeeds, doc?: Document): Palette;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type { BrandConfig, FeedbackType, PaletteConfig, SvgComponent } from './types';
|
|
2
|
+
export { applyPalette, contrast, createPalette, type PaletteSeeds } from './palette';
|
|
3
|
+
export { BrandProvider, type BrandStorage } from './brand-provider';
|
|
4
|
+
export { useBrand } from './use-brand';
|
|
5
|
+
export { createTheme, TOKEN_KEYS, type ThemeMode, type ThemeSeedInput, type ThemeSemanticTokens, type ThemeExplicitInput, type ThemeInput, type ThemeContrastCheck, type ThemeAdjustment, type ThemeResult, } from './theme';
|
|
6
|
+
export { applyTheme, type ApplyThemeOptions } from './apply-theme';
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
export type ThemeMode = 'gerado' | 'explicito' | 'misto';
|
|
2
|
+
export interface ThemeSeedInput {
|
|
3
|
+
/** Hex, rgb(), hsl() ou tripleta HSL solta ("210 95% 34%"). */
|
|
4
|
+
primary: string;
|
|
5
|
+
primaryHover?: string;
|
|
6
|
+
secondary: string;
|
|
7
|
+
secondaryHover?: string;
|
|
8
|
+
/** Degradê da marca (sidebar, painel do login, destaque): luz, meio e fundo. */
|
|
9
|
+
gradient: [string, string, string];
|
|
10
|
+
onPrimary?: 'auto' | 'light' | 'dark';
|
|
11
|
+
onSecondary?: 'auto' | 'light' | 'dark';
|
|
12
|
+
}
|
|
13
|
+
/** Tokens semânticos por nome, sem o prefixo --rendra- (ex.: "primary", "primaryForeground"). */
|
|
14
|
+
export type ThemeSemanticTokens = Partial<Record<(typeof TOKEN_KEYS)[number], string>>;
|
|
15
|
+
export interface ThemeExplicitInput {
|
|
16
|
+
light: ThemeSemanticTokens;
|
|
17
|
+
/** Ausente = derivado do claro; presente = respeitado como está. */
|
|
18
|
+
dark?: ThemeSemanticTokens;
|
|
19
|
+
/** Default false: só relata o contraste. true: ajusta os pares que falham AA. */
|
|
20
|
+
enforceContrast?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface ThemeInput {
|
|
23
|
+
/** Usado em data-palette (ou data-rendra-root) e no BrandProvider. */
|
|
24
|
+
id: string;
|
|
25
|
+
/** Nome curto exibido nos seletores. */
|
|
26
|
+
name: string;
|
|
27
|
+
mode: ThemeMode;
|
|
28
|
+
/** Obrigatório em 'gerado' e 'misto'. */
|
|
29
|
+
seed?: ThemeSeedInput;
|
|
30
|
+
/** Obrigatório em 'explicito' e 'misto' (ao menos `light`). */
|
|
31
|
+
explicit?: Partial<ThemeExplicitInput>;
|
|
32
|
+
}
|
|
33
|
+
export interface ThemeContrastCheck {
|
|
34
|
+
/** Nome da variável --rendra-* verificada (o papel de preenchimento do par). */
|
|
35
|
+
token: string;
|
|
36
|
+
background: string;
|
|
37
|
+
foreground: string;
|
|
38
|
+
ratio: number;
|
|
39
|
+
passesAA: boolean;
|
|
40
|
+
mode: 'light' | 'dark';
|
|
41
|
+
}
|
|
42
|
+
export interface ThemeAdjustment {
|
|
43
|
+
token: string;
|
|
44
|
+
mode: 'light' | 'dark';
|
|
45
|
+
requested: string;
|
|
46
|
+
applied: string;
|
|
47
|
+
ratio: number;
|
|
48
|
+
}
|
|
49
|
+
export interface ThemeResult {
|
|
50
|
+
id: string;
|
|
51
|
+
name: string;
|
|
52
|
+
/** Logotipo adequado sobre a sidebar deste tema. */
|
|
53
|
+
sidebarLogo: 'light' | 'dark';
|
|
54
|
+
vars: {
|
|
55
|
+
light: Record<string, string>;
|
|
56
|
+
dark: Record<string, string>;
|
|
57
|
+
};
|
|
58
|
+
/** Um item por par de contraste conferido. */
|
|
59
|
+
report: ThemeContrastCheck[];
|
|
60
|
+
/** Ajustes aplicados (enforceContrast, ou os já feitos por createPalette no modo gerado). */
|
|
61
|
+
adjustments: ThemeAdjustment[];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Todo nome de token que createPalette emite (light ∪ dark), sem prefixo, em camelCase.
|
|
65
|
+
* É a lista que o modo explícito aceita; qualquer chave fora daqui é ignorada (não é
|
|
66
|
+
* vocabulário de createPalette, não faz parte deste contrato).
|
|
67
|
+
*/
|
|
68
|
+
export declare const TOKEN_KEYS: readonly ["primary", "primaryForeground", "primaryHover", "primaryHoverForeground", "secondary", "secondaryForeground", "secondaryHover", "secondaryHoverForeground", "primarySoft", "primarySoftForeground", "primaryText", "ring", "accent", "accentForeground", "sidebar", "sidebarImage", "sidebarForeground", "sidebarMutedForeground", "sidebarBorder", "sidebarAccent", "sidebarActive", "sidebarActiveForeground", "sidebarIndicator", "gradientBrand", "gradientBrandForeground", "gradientAccent", "gradientSoft", "chart1", "chart2", "chart3", "chart4", "chart5", "shadowColor", "background", "backgroundImage", "foreground", "card", "cardForeground", "popover", "popoverForeground", "muted", "mutedForeground", "border", "input", "field", "overlay"];
|
|
69
|
+
/**
|
|
70
|
+
* Tenta reconhecer `value` como cor (hex, rgb(), hsl() ou tripleta HSL solta, "210 95% 34%") e
|
|
71
|
+
* devolve o hex normalizado em minúsculas. Devolve null quando não é um formato de cor
|
|
72
|
+
* reconhecido (gradiente, palavra-chave, "none"...), para o chamador decidir o que fazer.
|
|
73
|
+
*/
|
|
74
|
+
export declare function tryParseColorToHex(value: string): string | null;
|
|
75
|
+
/**
|
|
76
|
+
* Função pura, sem DOM, compatível com SSR. As chaves de vars.light/vars.dark já nascem
|
|
77
|
+
* prefixadas (--rendra-primary, --rendra-shadow-color...), no mesmo formato que
|
|
78
|
+
* applyTheme/BrandProvider esperam para injetar no DOM sem reprocessar nada.
|
|
79
|
+
*/
|
|
80
|
+
export declare function createTheme(input: ThemeInput): ThemeResult;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { ComponentType, SVGProps } from 'react';
|
|
2
|
+
import type { Shape } from '../lib/shape';
|
|
3
|
+
export type SvgComponent = ComponentType<SVGProps<SVGSVGElement>>;
|
|
4
|
+
export type FeedbackType = 'success' | 'error' | 'warning' | 'info';
|
|
5
|
+
/** Estilo do rótulo dos campos. */
|
|
6
|
+
export type LabelStyle = 'discreto' | 'normal';
|
|
7
|
+
/** Paleta de cores combinável com qualquer modelo (atributo data-palette no <html>). */
|
|
8
|
+
export interface PaletteConfig {
|
|
9
|
+
id: string;
|
|
10
|
+
/** Nome curto exibido nos seletores (ex.: "Safira", "Ardósia"). */
|
|
11
|
+
name: string;
|
|
12
|
+
/** Logotipo adequado sobre a sidebar desta paleta. */
|
|
13
|
+
sidebarLogo: 'light' | 'dark' | 'auto';
|
|
14
|
+
}
|
|
15
|
+
export interface BrandConfig {
|
|
16
|
+
/** Identificador usado no atributo data-brand do <html>. */
|
|
17
|
+
id: string;
|
|
18
|
+
/** Nome do produto exibido na interface e no título da aba. */
|
|
19
|
+
productName: string;
|
|
20
|
+
/** Nome da empresa, usado em rodapés e textos legais. */
|
|
21
|
+
companyName: string;
|
|
22
|
+
/** Frase curta usada na tela de login. */
|
|
23
|
+
tagline: string;
|
|
24
|
+
logo: {
|
|
25
|
+
/** Logotipo para fundos claros. */
|
|
26
|
+
light: SvgComponent;
|
|
27
|
+
/** Logotipo para fundos escuros (sidebar navy, modo escuro). */
|
|
28
|
+
dark: SvgComponent;
|
|
29
|
+
};
|
|
30
|
+
/** Símbolo da marca. Precisa usar fill="currentColor" para ser tingido. */
|
|
31
|
+
symbol: SvgComponent;
|
|
32
|
+
/** URL do favicon. */
|
|
33
|
+
favicon: string;
|
|
34
|
+
/**
|
|
35
|
+
* Ícones de feedback. Por padrão o BrandFeedbackIcon usa o símbolo com um selo de status.
|
|
36
|
+
* Informe um SVG (em currentColor) para substituir o ícone de um tipo específico.
|
|
37
|
+
*/
|
|
38
|
+
feedbackIcons?: Partial<Record<FeedbackType, SvgComponent>>;
|
|
39
|
+
/** Formato padrão de todos os componentes: square, rounded ou pill. */
|
|
40
|
+
shape: Shape;
|
|
41
|
+
/**
|
|
42
|
+
* Estilo do rótulo dos campos (atributo data-label no <html>): discreto (padrão; 11px,
|
|
43
|
+
* maiúsculo, cinza delicado) ou normal (14px, cor do texto).
|
|
44
|
+
*/
|
|
45
|
+
labelStyle?: LabelStyle;
|
|
46
|
+
/**
|
|
47
|
+
* themed (padrão): o logotipo é montado com o símbolo e as cores da paleta ativa,
|
|
48
|
+
* e acompanha o tema. image: usa os SVGs de logo como estão (arte oficial que não
|
|
49
|
+
* pode ser recolorida).
|
|
50
|
+
*/
|
|
51
|
+
logoMode?: 'themed' | 'image';
|
|
52
|
+
/** Qual logotipo usar sobre a sidebar. Sidebar escura pede o logo 'dark'. */
|
|
53
|
+
sidebarLogo: 'light' | 'dark' | 'auto';
|
|
54
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useBrand(): import("./brand-context").BrandContextValue;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Catálogo de códigos de componente (etapa 1.2.0-alpha.1 do plano da v2).
|
|
3
|
+
*
|
|
4
|
+
* Cada componente de `src/components/ui` (menos os internos `overlay-shell` e
|
|
5
|
+
* `picker-panel`, e menos os arquivos de teste) tem ao menos um código aqui. Uma variante
|
|
6
|
+
* visual relevante (a prop que muda o formato do componente, não tom nem tamanho) ganha o
|
|
7
|
+
* seu próprio código, numerado 001, 002... na ordem em que aparece neste arquivo.
|
|
8
|
+
*
|
|
9
|
+
* O código é o que o cliente escolhe no `docs/BRIEFING_MODELO.md` ("Componentes e
|
|
10
|
+
* variantes") e o que aparece na vitrine (`/componentes`), no `data-rendra` do elemento
|
|
11
|
+
* raiz de cada componente e no `registry.json` (`meta.codes`).
|
|
12
|
+
*
|
|
13
|
+
* Formato: `^[A-Z]{3,4}-\d{3}$` (ex.: "ABA-001", "BTN-006"). Nunca editar um código depois
|
|
14
|
+
* de publicado: ele é o identificador estável de uma variante.
|
|
15
|
+
*/
|
|
16
|
+
export interface ComponentCatalogEntry {
|
|
17
|
+
/** Formato ^[A-Z]{3,4}-\d{3}$, ex.: "ABA-001". Único no catálogo inteiro. */
|
|
18
|
+
code: string;
|
|
19
|
+
/** Nome em português do Brasil, ex.: "Abas em linha". */
|
|
20
|
+
name: string;
|
|
21
|
+
/** Nome do componente React, ex.: "Tabs". */
|
|
22
|
+
component: string;
|
|
23
|
+
/** Caminho relativo a partir de src/, ex.: "components/ui/tabs.tsx". */
|
|
24
|
+
file: string;
|
|
25
|
+
/** Props (nome: valor) que definem esta variante especificamente. */
|
|
26
|
+
variantProps: Record<string, string | number | boolean>;
|
|
27
|
+
/** Frase curta de quando usar esta variante, para o BRIEFING_MODELO. */
|
|
28
|
+
whenToUse: string;
|
|
29
|
+
/**
|
|
30
|
+
* Esta é a variante que o componente usa quando a prop não é passada (o valor padrão de
|
|
31
|
+
* `variantProps` no próprio componente React, ex.: `variant = 'line'` em `tabs.tsx`)? No
|
|
32
|
+
* máximo uma por componente (nenhuma, para o componente sem variante ou sem um padrão real,
|
|
33
|
+
* como `Chart`, cuja prop `type` é obrigatória); um componente com mais de uma variante tem
|
|
34
|
+
* exatamente uma marcada `true` (teste de integridade, `assertCatalogIntegrity`). Usada por
|
|
35
|
+
* `rendra trocar`: um elemento sem a prop conta como esta variante, e trocar para uma
|
|
36
|
+
* variante `isDefault` remove a prop em vez de escrever o valor por extenso.
|
|
37
|
+
*/
|
|
38
|
+
isDefault?: true;
|
|
39
|
+
}
|
|
40
|
+
/** Formato do código: de 3 a 4 letras maiúsculas, hífen, três dígitos. */
|
|
41
|
+
export declare const COMPONENT_CODE_PATTERN: RegExp;
|
|
42
|
+
/**
|
|
43
|
+
* Arquivos de `src/components/ui` que não entram no catálogo: são peças internas, sem uso
|
|
44
|
+
* direto em tela (nunca aparecem sozinhos numa tela, só dentro de outro componente).
|
|
45
|
+
*/
|
|
46
|
+
export declare const CATALOG_EXCLUDED_FILES: string[];
|
|
47
|
+
export declare const CATALOG: ComponentCatalogEntry[];
|
|
48
|
+
/** Um código específico do catálogo (ex.: para montar a vitrine ou o registry). */
|
|
49
|
+
export declare function getCatalogEntry(code: string): ComponentCatalogEntry | undefined;
|
|
50
|
+
/** Todos os códigos de um componente (ex.: as duas variantes do Tabs), na ordem cadastrada. */
|
|
51
|
+
export declare function catalogByComponent(component: string): ComponentCatalogEntry[];
|
|
52
|
+
/**
|
|
53
|
+
* Resolve o código de catálogo de um componente a partir das props que definem a variante.
|
|
54
|
+
* Sem variante (um código só, ou nenhuma prop bate), devolve o primeiro código cadastrado
|
|
55
|
+
* para o componente. Usado pelos próprios componentes para calcular o `data-rendra`, sem
|
|
56
|
+
* duplicar a tabela de variantes.
|
|
57
|
+
*/
|
|
58
|
+
export declare function resolveCatalogCode(component: string, props?: Record<string, unknown>): string;
|
|
59
|
+
/** Código que aparece mais de uma vez na lista. */
|
|
60
|
+
export declare function findDuplicateCodes(entries: ComponentCatalogEntry[]): string[];
|
|
61
|
+
/** Código fora do formato ^[A-Z]{3,4}-\d{3}$. */
|
|
62
|
+
export declare function findInvalidFormatCodes(entries: ComponentCatalogEntry[]): string[];
|
|
63
|
+
/**
|
|
64
|
+
* Código que colidiria com um código de modelo (T1, C4, M5...) de src/config/presets.ts,
|
|
65
|
+
* cujo padrão é /[TCM]\d+/ (uma letra T, C ou M seguida direto de dígitos, sem hífen).
|
|
66
|
+
*/
|
|
67
|
+
export declare function findPresetCollisions(entries: ComponentCatalogEntry[]): string[];
|
|
68
|
+
/** Arquivo (caminho relativo a src/) que não tem nenhuma entrada no catálogo. */
|
|
69
|
+
export declare function filesMissingCatalogEntry(files: string[], entries: ComponentCatalogEntry[]): string[];
|
|
70
|
+
/**
|
|
71
|
+
* Componente com mais de uma variante que não tem nenhuma marcada `isDefault` (fase 3, Lote
|
|
72
|
+
* B: `rendra trocar` precisa saber qual variante um elemento sem a prop representa).
|
|
73
|
+
*/
|
|
74
|
+
export declare function findComponentsWithoutDefault(entries: ComponentCatalogEntry[]): string[];
|
|
75
|
+
/** Componente com mais de uma variante marcada `isDefault` ao mesmo tempo (só pode uma). */
|
|
76
|
+
export declare function findComponentsWithMultipleDefaults(entries: ComponentCatalogEntry[]): string[];
|
|
77
|
+
/**
|
|
78
|
+
* Lança se houver código duplicado, fora do formato, colidindo com um código de modelo, ou
|
|
79
|
+
* componente com mais de uma variante sem exatamente uma marcada `isDefault`.
|
|
80
|
+
*/
|
|
81
|
+
export declare function assertCatalogIntegrity(): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './components/ui/chart';
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type ShellLayout } from './layout';
|
|
3
|
+
import type { NavGroup, ShellMenuItem, ShellNotificationsConfig, ShellUser } from './types';
|
|
4
|
+
export interface AppShellProps {
|
|
5
|
+
/** Menu do sistema: sidebar, barra inferior e busca global. Único obrigatório. */
|
|
6
|
+
navigation: NavGroup[];
|
|
7
|
+
/** Sobrescreve o padrão interno (defaultShellLayout), chave a chave. */
|
|
8
|
+
layout?: Partial<ShellLayout>;
|
|
9
|
+
/** Usuário exibido no menu do avatar e no rodapé da sidebar. */
|
|
10
|
+
user?: ShellUser;
|
|
11
|
+
/** Itens do menu do avatar (ex.: "Meu perfil", "Configurações"). Padrão: nenhum. */
|
|
12
|
+
userMenuItems?: ShellMenuItem[];
|
|
13
|
+
/** Chamado ao selecionar "Sair", na sidebar e no menu do avatar. */
|
|
14
|
+
onLogout?: () => void;
|
|
15
|
+
/** Rótulo do destino inicial na trilha do header. */
|
|
16
|
+
homeLabel?: string;
|
|
17
|
+
/** Ações rápidas da busca global (Ctrl+K), além do atalho de tema. Padrão: nenhuma. */
|
|
18
|
+
quickActions?: ShellMenuItem[];
|
|
19
|
+
/** Notificações do sino do header. Sem esta prop, o sino não aparece. */
|
|
20
|
+
notifications?: ShellNotificationsConfig;
|
|
21
|
+
/**
|
|
22
|
+
* Permite que o usuário troque o layout pelo menu do avatar (guardado no navegador).
|
|
23
|
+
* Desligue em produção se o layout do projeto for fixo.
|
|
24
|
+
*/
|
|
25
|
+
userConfigurable?: boolean;
|
|
26
|
+
/** Tela atual. O boilerplate passa o <Outlet /> do react-router. */
|
|
27
|
+
children?: ReactNode;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Estrutura da aplicação. Uma única área de rolagem: o <main>.
|
|
31
|
+
* Nunca importa @/config nem um roteador: recebe o menu, o layout, o usuário e as
|
|
32
|
+
* notificações por prop; quem navega é o RendraProvider (useCurrentPath/useRendraLink).
|
|
33
|
+
* Título da aba e meta description (SEO) não são responsabilidade do AppShell: o
|
|
34
|
+
* boilerplate (src/app/app-layout.tsx) aplica isso com useRouteMeta, que lê @/config/seo.
|
|
35
|
+
*/
|
|
36
|
+
export declare function AppShell({ navigation, layout: layoutProp, user, userMenuItems, onLogout, homeLabel, quickActions, notifications, userConfigurable, children, }: AppShellProps): import("react").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function CommandSearch(): import("react").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function Header(): import("react").JSX.Element;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export interface ShellLayout {
|
|
2
|
+
/** Menu lateral (sidebar) ou superior (topbar, no header). */
|
|
3
|
+
navigation: 'sidebar' | 'topbar';
|
|
4
|
+
/** Sidebar recolhida (só ícones) ou expandida (ícones e rótulos). */
|
|
5
|
+
sidebar: 'collapsed' | 'expanded';
|
|
6
|
+
/** Com a sidebar recolhida, abre por cima do conteúdo ao passar o mouse ou focar pelo teclado. */
|
|
7
|
+
expandOnHover: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Como abrir itens com submenu:
|
|
10
|
+
* panel abre uma segunda barra lateral com os subitens
|
|
11
|
+
* inline expande os subitens dentro da própria sidebar
|
|
12
|
+
*/
|
|
13
|
+
submenu: 'panel' | 'inline';
|
|
14
|
+
/**
|
|
15
|
+
* Submenu do menu superior:
|
|
16
|
+
* dropdown lista suspensa navegável por item
|
|
17
|
+
* mega mega menu com seções (grupos do navigation.ts) e menus com descrição
|
|
18
|
+
*/
|
|
19
|
+
topbarSubmenu: 'dropdown' | 'mega';
|
|
20
|
+
/** Barra de navegação inferior no mobile (até 4 itens marcados em navigation.ts). */
|
|
21
|
+
bottomNav: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare const defaultShellLayout: ShellLayout;
|
|
24
|
+
export declare const layoutOptions: {
|
|
25
|
+
readonly navigation: readonly [{
|
|
26
|
+
readonly value: "sidebar";
|
|
27
|
+
readonly label: "Menu lateral";
|
|
28
|
+
}, {
|
|
29
|
+
readonly value: "topbar";
|
|
30
|
+
readonly label: "Menu superior";
|
|
31
|
+
}];
|
|
32
|
+
readonly sidebar: readonly [{
|
|
33
|
+
readonly value: "collapsed";
|
|
34
|
+
readonly label: "Recolhida (só ícones)";
|
|
35
|
+
}, {
|
|
36
|
+
readonly value: "expanded";
|
|
37
|
+
readonly label: "Expandida";
|
|
38
|
+
}];
|
|
39
|
+
readonly submenu: readonly [{
|
|
40
|
+
readonly value: "panel";
|
|
41
|
+
readonly label: "Submenu em segunda barra";
|
|
42
|
+
}, {
|
|
43
|
+
readonly value: "inline";
|
|
44
|
+
readonly label: "Submenu dentro da sidebar";
|
|
45
|
+
}];
|
|
46
|
+
readonly topbarSubmenu: readonly [{
|
|
47
|
+
readonly value: "dropdown";
|
|
48
|
+
readonly label: "Submenu navegável";
|
|
49
|
+
}, {
|
|
50
|
+
readonly value: "mega";
|
|
51
|
+
readonly label: "Mega menu";
|
|
52
|
+
}];
|
|
53
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function MegaMenu(): import("react").JSX.Element;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { LucideIcon } from 'lucide-react';
|
|
2
|
+
import type { NavGroup, NavItem } from './types';
|
|
3
|
+
/** Destino plano da busca global e do cálculo do item ativo. */
|
|
4
|
+
export interface NavigationTarget {
|
|
5
|
+
title: string;
|
|
6
|
+
to: string;
|
|
7
|
+
group: string;
|
|
8
|
+
icon: LucideIcon;
|
|
9
|
+
}
|
|
10
|
+
/** Itens marcados `bottomNav`, na ordem do menu. Limite de 4. */
|
|
11
|
+
export declare function getBottomNavItems(navigation: NavGroup[]): NavItem[];
|
|
12
|
+
/** Lista plana de destinos (itens de primeiro nível com rota e filhos de itens com submenu). */
|
|
13
|
+
export declare function getNavigationTargets(navigation: NavGroup[]): NavigationTarget[];
|
|
14
|
+
/**
|
|
15
|
+
* Destino ativo: o mais específico que combina com o endereço.
|
|
16
|
+
* Ex.: em /clientes/novo fica ativo "Novo cliente" (e o grupo Cadastros), não "Clientes".
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveActiveTo(targets: NavigationTarget[], pathname: string): string | null;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sino de notificações. Renderizado só quando o AppShell recebe a prop `notifications`;
|
|
3
|
+
* os itens e os dois retornos de chamada (marcar todas como lidas, marcar uma como lida)
|
|
4
|
+
* vêm dessa prop, nunca de um mock interno.
|
|
5
|
+
*/
|
|
6
|
+
export declare function Notifications(): import("react").JSX.Element | null;
|