@xenide-io/the-old-ui-theme 0.6.11 → 0.6.13
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/dist/{ai-message-blocknote-DIUICX3G.mjs → ai-message-blocknote-WABTHFY7.mjs} +1 -1
- package/dist/{chunk-VIWW7AW2.mjs → chunk-NOI42JNZ.mjs} +47 -3
- package/dist/suite.d.mts +9 -2
- package/dist/suite.d.ts +9 -2
- package/dist/suite.js +267 -90
- package/dist/suite.mjs +149 -27
- package/package.json +1 -1
- package/src/styles/suite-skin.css +8 -0
- package/src/suite/components/suite-notification-bell.tsx +9 -7
- package/src/suite/components/suite-sidebar.tsx +4 -1
- package/src/suite/components/theme-provider.test.tsx +15 -0
- package/src/suite/components/theme-provider.tsx +3 -0
- package/src/suite/index.ts +5 -0
- package/src/suite/lib/use-lock-mobile-page-zoom.test.tsx +65 -0
- package/src/suite/lib/use-lock-mobile-page-zoom.ts +51 -0
- package/src/suite/lib/use-sidebar-width-hook.test.tsx +73 -0
- package/src/suite/lib/use-sidebar-width.test.ts +77 -0
- package/src/suite/lib/use-sidebar-width.ts +152 -20
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
useCallback,
|
|
5
|
-
|
|
5
|
+
useLayoutEffect,
|
|
6
6
|
useState,
|
|
7
7
|
type PointerEvent as ReactPointerEvent,
|
|
8
8
|
} from "react";
|
|
@@ -13,6 +13,27 @@ export const SIDEBAR_MIN_EXPANDED_WIDTH = 180;
|
|
|
13
13
|
export const SIDEBAR_MAX_WIDTH = 640;
|
|
14
14
|
export const SIDEBAR_DEFAULT_WIDTH = 320;
|
|
15
15
|
|
|
16
|
+
/** Shared across Tides / TurtleTime / Kraken / ShellStack / Nakama. */
|
|
17
|
+
export const SUITE_SIDEBAR_WIDTH_KEY = "shellstack:sidebar-width";
|
|
18
|
+
export const SUITE_SIDEBAR_WIDTH_COOKIE = "shellstack_sidebar_width";
|
|
19
|
+
|
|
20
|
+
const LEGACY_SIDEBAR_WIDTH_KEYS = [
|
|
21
|
+
"tides-sidebar-width",
|
|
22
|
+
"tt-sidebar-width",
|
|
23
|
+
"kraken-sidebar-width",
|
|
24
|
+
"shellstack-sidebar-width",
|
|
25
|
+
"nakama-sidebar-width",
|
|
26
|
+
] as const;
|
|
27
|
+
|
|
28
|
+
function isSuiteSidebarKey(storageKey: string): boolean {
|
|
29
|
+
return (
|
|
30
|
+
storageKey === SUITE_SIDEBAR_WIDTH_KEY ||
|
|
31
|
+
LEGACY_SIDEBAR_WIDTH_KEYS.includes(
|
|
32
|
+
storageKey as (typeof LEGACY_SIDEBAR_WIDTH_KEYS)[number],
|
|
33
|
+
)
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
16
37
|
/** Desktop column width: icon rail when collapsed, otherwise the persisted width. */
|
|
17
38
|
export function sidebarColumnWidth(
|
|
18
39
|
width: number,
|
|
@@ -33,34 +54,149 @@ function snapWidth(width: number): number {
|
|
|
33
54
|
return Math.min(SIDEBAR_MAX_WIDTH, width);
|
|
34
55
|
}
|
|
35
56
|
|
|
57
|
+
function parseWidth(raw: string | null | undefined): number | null {
|
|
58
|
+
if (!raw) return null;
|
|
59
|
+
const parsed = Number.parseInt(raw, 10);
|
|
60
|
+
return Number.isNaN(parsed) ? null : parsed;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function suiteCookieDomainAttr(): string {
|
|
64
|
+
const host = window.location.hostname;
|
|
65
|
+
if (host === "localhost" || /^\d{1,3}(?:\.\d{1,3}){3}$/.test(host)) {
|
|
66
|
+
return "";
|
|
67
|
+
}
|
|
68
|
+
// tides.localhost / turtletime.localhost must share one cookie.
|
|
69
|
+
if (host.endsWith(".localhost")) {
|
|
70
|
+
return "; Domain=.localhost";
|
|
71
|
+
}
|
|
72
|
+
const known = new Set([
|
|
73
|
+
"tides",
|
|
74
|
+
"kraken",
|
|
75
|
+
"turtletime",
|
|
76
|
+
"time",
|
|
77
|
+
"nakama",
|
|
78
|
+
"app",
|
|
79
|
+
"shellstack",
|
|
80
|
+
"portal",
|
|
81
|
+
]);
|
|
82
|
+
const parts = host.split(".");
|
|
83
|
+
if (parts.length >= 3 && known.has(parts[0] ?? "")) {
|
|
84
|
+
return `; Domain=.${parts.slice(1).join(".")}`;
|
|
85
|
+
}
|
|
86
|
+
if (parts.length >= 2) return `; Domain=.${parts.slice(1).join(".")}`;
|
|
87
|
+
return "";
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function readCookie(name: string): string | null {
|
|
91
|
+
const prefix = `${name}=`;
|
|
92
|
+
for (const part of document.cookie.split(";")) {
|
|
93
|
+
const trimmed = part.trim();
|
|
94
|
+
if (trimmed.startsWith(prefix)) {
|
|
95
|
+
return decodeURIComponent(trimmed.slice(prefix.length));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function writeCookie(name: string, value: string): void {
|
|
102
|
+
const secure = window.location.protocol === "https:" ? "; Secure" : "";
|
|
103
|
+
document.cookie = `${name}=${encodeURIComponent(value)}; Path=/; Max-Age=31536000; SameSite=Lax${suiteCookieDomainAttr()}${secure}`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function clearCookie(name: string): void {
|
|
107
|
+
const secure = window.location.protocol === "https:" ? "; Secure" : "";
|
|
108
|
+
document.cookie = `${name}=; Path=/; Max-Age=0; SameSite=Lax${suiteCookieDomainAttr()}${secure}`;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function readSidebarWidth(storageKey: string): number | null {
|
|
112
|
+
try {
|
|
113
|
+
if (isSuiteSidebarKey(storageKey)) {
|
|
114
|
+
const fromCookie = parseWidth(readCookie(SUITE_SIDEBAR_WIDTH_COOKIE));
|
|
115
|
+
if (fromCookie != null) return fromCookie;
|
|
116
|
+
const shared = parseWidth(localStorage.getItem(SUITE_SIDEBAR_WIDTH_KEY));
|
|
117
|
+
if (shared != null) return shared;
|
|
118
|
+
for (const key of LEGACY_SIDEBAR_WIDTH_KEYS) {
|
|
119
|
+
const legacy = parseWidth(localStorage.getItem(key));
|
|
120
|
+
if (legacy != null) return legacy;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return parseWidth(localStorage.getItem(storageKey));
|
|
124
|
+
} catch {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function persistSidebarWidth(storageKey: string, value: number): void {
|
|
130
|
+
try {
|
|
131
|
+
localStorage.setItem(storageKey, String(value));
|
|
132
|
+
if (isSuiteSidebarKey(storageKey)) {
|
|
133
|
+
localStorage.setItem(SUITE_SIDEBAR_WIDTH_KEY, String(value));
|
|
134
|
+
}
|
|
135
|
+
} catch {
|
|
136
|
+
// localStorage can be unavailable; the cookie still crosses apps.
|
|
137
|
+
}
|
|
138
|
+
if (isSuiteSidebarKey(storageKey)) {
|
|
139
|
+
try {
|
|
140
|
+
writeCookie(SUITE_SIDEBAR_WIDTH_COOKIE, String(value));
|
|
141
|
+
} catch {
|
|
142
|
+
// Cookie write can fail in restricted browser contexts.
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function resetSuiteSidebarWidth(): void {
|
|
148
|
+
try {
|
|
149
|
+
localStorage.removeItem(SUITE_SIDEBAR_WIDTH_KEY);
|
|
150
|
+
for (const key of LEGACY_SIDEBAR_WIDTH_KEYS) {
|
|
151
|
+
localStorage.removeItem(key);
|
|
152
|
+
}
|
|
153
|
+
localStorage.removeItem("kraken-sidebar-collapsed");
|
|
154
|
+
} catch {
|
|
155
|
+
// Ignore storage failures.
|
|
156
|
+
}
|
|
157
|
+
try {
|
|
158
|
+
clearCookie(SUITE_SIDEBAR_WIDTH_COOKIE);
|
|
159
|
+
} catch {
|
|
160
|
+
// Ignore cookie failures.
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
36
164
|
/**
|
|
37
165
|
* Shared suite sidebar resizing: drag below the threshold to collapse,
|
|
38
166
|
* drag the rail edge out to expand, and double-click to reset.
|
|
167
|
+
* Suite app keys share one width via cookie so app-switch keeps it.
|
|
39
168
|
*/
|
|
40
169
|
export function useSidebarWidth(
|
|
41
|
-
storageKey
|
|
170
|
+
storageKey = SUITE_SIDEBAR_WIDTH_KEY,
|
|
42
171
|
defaultWidth = SIDEBAR_DEFAULT_WIDTH,
|
|
43
172
|
) {
|
|
44
173
|
const fallbackWidth = snapWidth(clampWidth(defaultWidth));
|
|
174
|
+
// ponytail: always start at the default so SSR and the first client render
|
|
175
|
+
// match. Reading the cookie in useState() hydrates 320 vs 412 and React
|
|
176
|
+
// keeps the server width — TurtleTime / ShellStack / Nakama stay stuck.
|
|
45
177
|
const [width, setWidth] = useState(fallbackWidth);
|
|
46
178
|
const [narrowViewport, setNarrowViewport] = useState(false);
|
|
47
179
|
const collapsed = narrowViewport || width <= SIDEBAR_COLLAPSE_THRESHOLD;
|
|
48
180
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
stored
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
181
|
+
useLayoutEffect(() => {
|
|
182
|
+
const sync = () => {
|
|
183
|
+
const stored = readSidebarWidth(storageKey);
|
|
184
|
+
if (stored == null) return;
|
|
185
|
+
setWidth(snapWidth(clampWidth(stored)));
|
|
186
|
+
};
|
|
187
|
+
sync();
|
|
188
|
+
// App switch can restore a bf-cached page. Re-read the shared cookie.
|
|
189
|
+
window.addEventListener("pageshow", sync);
|
|
190
|
+
window.addEventListener("focus", sync);
|
|
191
|
+
document.addEventListener("visibilitychange", sync);
|
|
192
|
+
return () => {
|
|
193
|
+
window.removeEventListener("pageshow", sync);
|
|
194
|
+
window.removeEventListener("focus", sync);
|
|
195
|
+
document.removeEventListener("visibilitychange", sync);
|
|
196
|
+
};
|
|
61
197
|
}, [storageKey]);
|
|
62
198
|
|
|
63
|
-
|
|
199
|
+
useLayoutEffect(() => {
|
|
64
200
|
const media = window.matchMedia("(max-width: 639px)");
|
|
65
201
|
const sync = () => setNarrowViewport(media.matches);
|
|
66
202
|
sync();
|
|
@@ -70,11 +206,7 @@ export function useSidebarWidth(
|
|
|
70
206
|
|
|
71
207
|
const persist = useCallback(
|
|
72
208
|
(value: number) => {
|
|
73
|
-
|
|
74
|
-
localStorage.setItem(storageKey, String(value));
|
|
75
|
-
} catch {
|
|
76
|
-
// A persisted preference is optional; resizing should still work.
|
|
77
|
-
}
|
|
209
|
+
persistSidebarWidth(storageKey, value);
|
|
78
210
|
},
|
|
79
211
|
[storageKey],
|
|
80
212
|
);
|