@motor-hero/ui-kit 0.18.0 → 0.19.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 +41 -0
- package/dist/components/theme-provider.d.ts +3 -1
- package/dist/components/theme-provider.d.ts.map +1 -1
- package/dist/index.cjs +36 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +35 -6
- package/dist/index.js.map +1 -1
- package/dist/lib/tenant-theme.d.ts +15 -0
- package/dist/lib/tenant-theme.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/components/theme-provider.tsx +18 -8
- package/src/index.ts +2 -0
- package/src/lib/tenant-theme.ts +42 -0
package/README.md
CHANGED
|
@@ -43,6 +43,47 @@ function App() {
|
|
|
43
43
|
}
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
+
## Temas e Multi-tenant
|
|
47
|
+
|
|
48
|
+
Por padrão o kit usa o tema **zinc** (claro/escuro), alternado pelo `ThemeProvider`.
|
|
49
|
+
Para servir várias marcas (tenants) no mesmo app, passe a prop opcional `tenantTheme`.
|
|
50
|
+
**Sem ela, nada muda** — apps existentes seguem com o tema padrão.
|
|
51
|
+
|
|
52
|
+
Pense em dois eixos independentes: a **marca** (qual tenant) e o **modo** (claro/escuro).
|
|
53
|
+
Só o grupo de cores da **marca** é por tenant; neutros (`background`, `card`, `border`…) e
|
|
54
|
+
status (`destructive`, `success`) são compartilhados e respondem só ao modo.
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
import { ThemeProvider } from "@motor-hero/ui-kit"
|
|
58
|
+
import type { TenantTheme } from "@motor-hero/ui-kit"
|
|
59
|
+
|
|
60
|
+
const tenantTheme: TenantTheme = {
|
|
61
|
+
light: {
|
|
62
|
+
primary: "hsl(145 63% 32%)",
|
|
63
|
+
primaryForeground: "hsl(0 0% 100%)",
|
|
64
|
+
secondary: "hsl(0 0% 96%)",
|
|
65
|
+
secondaryForeground: "hsl(0 0% 12%)",
|
|
66
|
+
accent: "hsl(45 95% 55%)",
|
|
67
|
+
accentForeground: "hsl(0 0% 8%)",
|
|
68
|
+
},
|
|
69
|
+
dark: { primary: "hsl(145 50% 55%)" }, // opcional e parcial: só o que muda no escuro
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
<ThemeProvider defaultTheme="dark" tenantTheme={tenantTheme}>
|
|
73
|
+
<App />
|
|
74
|
+
</ThemeProvider>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Regras:**
|
|
78
|
+
|
|
79
|
+
- Mínimo por tenant: `primary` + `primaryForeground` (2 cores). A marca completa tem três cores — `primary`, `secondary` e `accent` — cada uma com seu foreground.
|
|
80
|
+
- `dark` é opcional e parcial — informe apenas os tokens que mudam; o resto herda do `light`.
|
|
81
|
+
- Valores são qualquer cor CSS válida (`hsl(...)`, `#hex`, `oklch(...)`); prefira `hsl(...)`.
|
|
82
|
+
- Os `*Foreground` são responsabilidade sua — garanta contraste AA, o kit não deriva.
|
|
83
|
+
- As cores entram como estilo inline no `<html>`, vencendo o `.dark` e qualquer `@theme` do app (sem conflito de cascata). Memoize o objeto `tenantTheme`.
|
|
84
|
+
|
|
85
|
+
Guia completo em [ui.motorhero.com.br](https://ui.motorhero.com.br) → **Temas Multi-tenant**.
|
|
86
|
+
|
|
46
87
|
## Desenvolvimento
|
|
47
88
|
|
|
48
89
|
```bash
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
+
import { type TenantTheme } from "../lib/tenant-theme";
|
|
1
2
|
type Theme = "dark" | "light" | "system";
|
|
2
3
|
type ThemeProviderProps = {
|
|
3
4
|
children: React.ReactNode;
|
|
4
5
|
defaultTheme?: Theme;
|
|
5
6
|
storageKey?: string;
|
|
7
|
+
tenantTheme?: TenantTheme;
|
|
6
8
|
};
|
|
7
9
|
type ThemeProviderState = {
|
|
8
10
|
theme: Theme;
|
|
9
11
|
setTheme: (theme: Theme) => void;
|
|
10
12
|
};
|
|
11
|
-
export declare function ThemeProvider({ children, defaultTheme, storageKey, ...props }: ThemeProviderProps): import("react").JSX.Element;
|
|
13
|
+
export declare function ThemeProvider({ children, defaultTheme, storageKey, tenantTheme, ...props }: ThemeProviderProps): import("react").JSX.Element;
|
|
12
14
|
export declare function useTheme(): ThemeProviderState;
|
|
13
15
|
export type { Theme, ThemeProviderProps, ThemeProviderState };
|
|
14
16
|
//# sourceMappingURL=theme-provider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme-provider.d.ts","sourceRoot":"","sources":["../../src/components/theme-provider.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"theme-provider.d.ts","sourceRoot":"","sources":["../../src/components/theme-provider.tsx"],"names":[],"mappings":"AACA,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAExE,KAAK,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAA;AAExC,KAAK,kBAAkB,GAAG;IACxB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,YAAY,CAAC,EAAE,KAAK,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B,CAAA;AAED,KAAK,kBAAkB,GAAG;IACxB,KAAK,EAAE,KAAK,CAAA;IACZ,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CACjC,CAAA;AASD,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,YAAuB,EACvB,UAAuB,EACvB,WAAW,EACX,GAAG,KAAK,EACT,EAAE,kBAAkB,+BAsCpB;AAED,wBAAgB,QAAQ,uBAMvB;AAED,YAAY,EAAE,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,CAAA"}
|
package/dist/index.cjs
CHANGED
|
@@ -56,6 +56,7 @@ __export(index_exports, {
|
|
|
56
56
|
ThemeProvider: () => ThemeProvider,
|
|
57
57
|
Toaster: () => Toaster,
|
|
58
58
|
UserMenu: () => UserMenu,
|
|
59
|
+
applyTenantTheme: () => applyTenantTheme,
|
|
59
60
|
cn: () => cn,
|
|
60
61
|
defaultRenderLink: () => defaultRenderLink,
|
|
61
62
|
extractApiError: () => extractApiError,
|
|
@@ -69,6 +70,27 @@ module.exports = __toCommonJS(index_exports);
|
|
|
69
70
|
|
|
70
71
|
// src/components/theme-provider.tsx
|
|
71
72
|
var import_react = require("react");
|
|
73
|
+
|
|
74
|
+
// src/lib/tenant-theme.ts
|
|
75
|
+
var VAR_MAP = {
|
|
76
|
+
primary: "--color-primary",
|
|
77
|
+
primaryForeground: "--color-primary-foreground",
|
|
78
|
+
secondary: "--color-secondary",
|
|
79
|
+
secondaryForeground: "--color-secondary-foreground",
|
|
80
|
+
accent: "--color-accent",
|
|
81
|
+
accentForeground: "--color-accent-foreground",
|
|
82
|
+
ring: "--color-ring"
|
|
83
|
+
};
|
|
84
|
+
function applyTenantTheme(root, tenantTheme, mode) {
|
|
85
|
+
const tokens = tenantTheme ? mode === "dark" ? { ...tenantTheme.light, ...tenantTheme.dark } : tenantTheme.light : {};
|
|
86
|
+
for (const key of Object.keys(VAR_MAP)) {
|
|
87
|
+
const value = tokens[key];
|
|
88
|
+
if (value) root.style.setProperty(VAR_MAP[key], value);
|
|
89
|
+
else root.style.removeProperty(VAR_MAP[key]);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/components/theme-provider.tsx
|
|
72
94
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
73
95
|
var initialState = {
|
|
74
96
|
theme: "system",
|
|
@@ -79,6 +101,7 @@ function ThemeProvider({
|
|
|
79
101
|
children,
|
|
80
102
|
defaultTheme = "system",
|
|
81
103
|
storageKey = "ui-theme",
|
|
104
|
+
tenantTheme,
|
|
82
105
|
...props
|
|
83
106
|
}) {
|
|
84
107
|
const [theme, setTheme] = (0, import_react.useState)(
|
|
@@ -86,14 +109,20 @@ function ThemeProvider({
|
|
|
86
109
|
);
|
|
87
110
|
(0, import_react.useEffect)(() => {
|
|
88
111
|
const root = window.document.documentElement;
|
|
89
|
-
|
|
112
|
+
const applyResolved = (resolved) => {
|
|
113
|
+
root.classList.remove("light", "dark");
|
|
114
|
+
root.classList.add(resolved);
|
|
115
|
+
applyTenantTheme(root, tenantTheme, resolved);
|
|
116
|
+
};
|
|
90
117
|
if (theme === "system") {
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
118
|
+
const mql = window.matchMedia("(prefers-color-scheme: dark)");
|
|
119
|
+
applyResolved(mql.matches ? "dark" : "light");
|
|
120
|
+
const onChange = (e) => applyResolved(e.matches ? "dark" : "light");
|
|
121
|
+
mql.addEventListener("change", onChange);
|
|
122
|
+
return () => mql.removeEventListener("change", onChange);
|
|
94
123
|
}
|
|
95
|
-
|
|
96
|
-
}, [theme]);
|
|
124
|
+
applyResolved(theme);
|
|
125
|
+
}, [theme, tenantTheme]);
|
|
97
126
|
const value = {
|
|
98
127
|
theme,
|
|
99
128
|
setTheme: (theme2) => {
|
|
@@ -1447,6 +1476,7 @@ function useCustomToast() {
|
|
|
1447
1476
|
ThemeProvider,
|
|
1448
1477
|
Toaster,
|
|
1449
1478
|
UserMenu,
|
|
1479
|
+
applyTenantTheme,
|
|
1450
1480
|
cn,
|
|
1451
1481
|
defaultRenderLink,
|
|
1452
1482
|
extractApiError,
|