@goplusvn/core 0.1.17 → 0.1.19
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/CHANGELOG.md +18 -0
- package/package.json +3 -2
- package/src/providers/brand-theme.ts +55 -0
- package/src/providers/index.tsx +14 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.19 — applyBrandThemeTokens (gom logic áp theme, subtle dark-aware)
|
|
4
|
+
|
|
5
|
+
Mỗi app copy y hệt logic áp bảng màu thương hiệu vào CSS token trong theme-provider
|
|
6
|
+
→ cùng 1 bug (`--accent-primary-subtle` luôn sáng → mất chữ dark mode) phải sửa 3
|
|
7
|
+
lần. Đưa vào core: `@goerp/core/providers/brand-theme` — `applyBrandThemeTokens(root,
|
|
8
|
+
theme, isDark)` + `shiftLightness` + type `BrandThemeColor`. Subtle DARK-AWARE sẵn
|
|
9
|
+
(dark hue 32% 18%, light 60% 96%). App chỉ giữ BẢNG màu riêng + gọi helper.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
## 0.1.18 — SettingsProvider nhận `defaults` (đổi màu/theme mặc định theo app)
|
|
13
|
+
|
|
14
|
+
Customizer khóa cứng `defaultSettings.theme = "blue"` trong core → app không đặt
|
|
15
|
+
được màu mặc định riêng (vd wu-vpbank muốn "green"). Thêm prop tùy chọn `defaults?:
|
|
16
|
+
Partial<SettingsType>` cho `SettingsProvider` — merge lên core defaults (áp cho state
|
|
17
|
+
đầu, khi không có cookie, và resetSettings). Additive/backward-compatible. App dùng:
|
|
18
|
+
`<SettingsProvider locale={locale} defaults={{ theme: "green" }}>`.
|
|
19
|
+
|
|
20
|
+
|
|
3
21
|
## 0.1.17 — Fix: khôi phục nền màu tab (page-tabs) theo golden vinhhoa
|
|
4
22
|
|
|
5
23
|
Bản "neutral single-style" trước đó bỏ gradient nền tab NHƯNG vẫn để icon/chữ
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goplusvn/core",
|
|
3
3
|
"description": "GoPlusVN Platform Kit - ERP kernel: layout, RBAC, CRUD, multi-tenant, system pages",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.19",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"registry": "https://registry.npmjs.org",
|
|
@@ -53,7 +53,8 @@
|
|
|
53
53
|
"./utils/cccd-parser": "./src/utils/cccd-parser.ts",
|
|
54
54
|
"./configs/status": "./src/configs/status.ts",
|
|
55
55
|
"./configs/entities": "./src/configs/entities/index.ts",
|
|
56
|
-
"./package.json": "./package.json"
|
|
56
|
+
"./package.json": "./package.json",
|
|
57
|
+
"./providers/brand-theme": "./src/providers/brand-theme.ts"
|
|
57
58
|
},
|
|
58
59
|
"peerDependencies": {
|
|
59
60
|
"next": ">=14.0.0",
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Áp bảng màu thương hiệu (theme) đã calibrate vào các CSS token — logic DÙNG
|
|
2
|
+
// CHUNG cho theme-provider của mọi app (trước đây bị copy y hệt ở wu/vinhhoa/
|
|
3
|
+
// thingtodo → cùng 1 bug phải sửa 3 lần). App chỉ giữ BẢNG màu riêng (THEMES) +
|
|
4
|
+
// gọi hàm này; token dark-aware xử lý ở đây.
|
|
5
|
+
//
|
|
6
|
+
// Usage (app theme-provider):
|
|
7
|
+
// import { applyBrandThemeTokens } from "@goerp/core/providers/brand-theme";
|
|
8
|
+
// applyBrandThemeTokens(document.documentElement, THEMES[theme], isDark);
|
|
9
|
+
|
|
10
|
+
export interface BrandThemeColor {
|
|
11
|
+
/** "H S% L%" cho light mode. */
|
|
12
|
+
primary: string;
|
|
13
|
+
/** "H S% L%" cho dark mode (thường sáng hơn). */
|
|
14
|
+
primaryDark: string;
|
|
15
|
+
/** primary-foreground "H S% L%". */
|
|
16
|
+
fg: string;
|
|
17
|
+
/** nền sidebar light. */
|
|
18
|
+
sidebar: string;
|
|
19
|
+
/** nền sidebar dark. */
|
|
20
|
+
sidebarDark: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Dịch lightness của "H S% L%" (cho hover/active). */
|
|
24
|
+
export function shiftLightness(triple: string, delta: number): string {
|
|
25
|
+
const parts = triple.trim().split(/\s+/);
|
|
26
|
+
if (parts.length < 3) return triple;
|
|
27
|
+
const l = parseFloat(parts[2]);
|
|
28
|
+
const next = Math.max(0, Math.min(100, l + delta));
|
|
29
|
+
return `${parts[0]} ${parts[1]} ${next}%`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function applyBrandThemeTokens(
|
|
33
|
+
root: HTMLElement,
|
|
34
|
+
theme: BrandThemeColor,
|
|
35
|
+
isDark: boolean,
|
|
36
|
+
): void {
|
|
37
|
+
const primary = isDark ? theme.primaryDark : theme.primary;
|
|
38
|
+
const sidebar = isDark ? theme.sidebarDark : theme.sidebar;
|
|
39
|
+
const hue = primary.trim().split(/\s+/)[0];
|
|
40
|
+
|
|
41
|
+
root.style.setProperty("--primary", primary);
|
|
42
|
+
root.style.setProperty("--accent-primary", primary);
|
|
43
|
+
root.style.setProperty("--ring", primary);
|
|
44
|
+
root.style.setProperty("--primary-foreground", theme.fg);
|
|
45
|
+
root.style.setProperty("--accent-primary-hover", shiftLightness(primary, -6));
|
|
46
|
+
root.style.setProperty("--accent-primary-active", shiftLightness(primary, -12));
|
|
47
|
+
// Subtle DARK-AWARE: sáng (96% L) ở light, TỐI (18% L) ở dark — nếu luôn sáng
|
|
48
|
+
// thì UI dùng bg-accent-primary-subtle + chữ sáng sẽ mất chữ ở dark mode.
|
|
49
|
+
if (hue)
|
|
50
|
+
root.style.setProperty(
|
|
51
|
+
"--accent-primary-subtle",
|
|
52
|
+
isDark ? `${hue} 32% 18%` : `${hue} 60% 96%`,
|
|
53
|
+
);
|
|
54
|
+
root.style.setProperty("--sidebar-background", sidebar);
|
|
55
|
+
}
|
package/src/providers/index.tsx
CHANGED
|
@@ -39,14 +39,20 @@ export const SettingsContext = createContext<
|
|
|
39
39
|
export function SettingsProvider({
|
|
40
40
|
locale,
|
|
41
41
|
children,
|
|
42
|
+
defaults,
|
|
42
43
|
}: {
|
|
43
44
|
locale: LocaleType;
|
|
44
45
|
children: ReactNode;
|
|
46
|
+
/** App-level overrides của defaultSettings (vd theme, radius). Truyền object
|
|
47
|
+
* ỔN ĐỊNH (module-level const) để tránh re-render. Mặc định = defaultSettings core. */
|
|
48
|
+
defaults?: Partial<SettingsType>;
|
|
45
49
|
}) {
|
|
50
|
+
// Mặc định của app = core defaults + override từ app (vd theme:"green").
|
|
51
|
+
const base = { ...defaultSettings, ...defaults };
|
|
46
52
|
const [storedSettings, setStoredSettings, deleteStoredSettings] =
|
|
47
53
|
useCookie("settings");
|
|
48
54
|
const [settings, setSettings] = useState<SettingsType>(() => ({
|
|
49
|
-
...
|
|
55
|
+
...base,
|
|
50
56
|
locale,
|
|
51
57
|
}));
|
|
52
58
|
|
|
@@ -54,14 +60,15 @@ export function SettingsProvider({
|
|
|
54
60
|
if (storedSettings) {
|
|
55
61
|
try {
|
|
56
62
|
const parsedSettings = JSON.parse(storedSettings);
|
|
57
|
-
setSettings({ ...
|
|
63
|
+
setSettings({ ...base, ...parsedSettings });
|
|
58
64
|
} catch {
|
|
59
|
-
setSettings({ ...
|
|
65
|
+
setSettings({ ...base, locale });
|
|
60
66
|
}
|
|
61
67
|
} else {
|
|
62
|
-
setSettings({ ...
|
|
68
|
+
setSettings({ ...base, locale });
|
|
63
69
|
}
|
|
64
|
-
|
|
70
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
71
|
+
}, [storedSettings, locale, defaults]);
|
|
65
72
|
|
|
66
73
|
const updateSettings = useCallback(
|
|
67
74
|
(newSettings: SettingsType) => {
|
|
@@ -73,8 +80,8 @@ export function SettingsProvider({
|
|
|
73
80
|
|
|
74
81
|
const resetSettings = useCallback(() => {
|
|
75
82
|
deleteStoredSettings();
|
|
76
|
-
setSettings(defaultSettings);
|
|
77
|
-
}, [deleteStoredSettings]);
|
|
83
|
+
setSettings({ ...defaultSettings, ...defaults });
|
|
84
|
+
}, [deleteStoredSettings, defaults]);
|
|
78
85
|
|
|
79
86
|
// Apply the appearance choices the Customizer exposes but that nothing else
|
|
80
87
|
// wires up. Without this, the "Radius" and "Density" controls store a value
|