@cosxai/ui 0.10.3 → 0.10.4
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/package.json +1 -1
- package/src/actionbar/ActionBar.tsx +34 -28
package/package.json
CHANGED
|
@@ -78,24 +78,13 @@ function loadCollapsed(storageKey: string): boolean {
|
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function persistAdminMode(storageKey: string, on: boolean) {
|
|
91
|
-
if (typeof window === "undefined") return;
|
|
92
|
-
try {
|
|
93
|
-
if (on) window.localStorage.setItem(`${storageKey}:admin`, "1");
|
|
94
|
-
else window.localStorage.removeItem(`${storageKey}:admin`);
|
|
95
|
-
} catch {
|
|
96
|
-
/* ignore */
|
|
97
|
-
}
|
|
98
|
-
}
|
|
81
|
+
// Admin mode is session-only — deliberately NOT persisted. Two
|
|
82
|
+
// reasons: (1) cross-page reload persistence would surface an
|
|
83
|
+
// elevated-privileges state on a fresh session without explicit
|
|
84
|
+
// user opt-in every time — a small surprise factor with real
|
|
85
|
+
// consequences on admin surfaces. (2) The reset-on-context-change
|
|
86
|
+
// effect below relies on the state living in React memory alone,
|
|
87
|
+
// so we can watch for admin-item-set changes and clear cleanly.
|
|
99
88
|
|
|
100
89
|
interface BuildEntry {
|
|
101
90
|
kind: "flat" | "group";
|
|
@@ -197,17 +186,34 @@ export function ActionBar({
|
|
|
197
186
|
// ----- Admin mode toggle (any registered item with adminOnly=true) -----
|
|
198
187
|
// Admin items stay hidden by default; a small toggle button (rendered
|
|
199
188
|
// between the grip and the first item) flips this to reveal them.
|
|
200
|
-
//
|
|
201
|
-
//
|
|
202
|
-
//
|
|
203
|
-
|
|
189
|
+
// Session-only: never persisted (see comment on loadAdminMode's
|
|
190
|
+
// removal above). Additionally auto-resets when the set of
|
|
191
|
+
// adminOnly item keys changes so a user who turned admin on for
|
|
192
|
+
// Doc A doesn't accidentally land in admin mode on Doc B.
|
|
193
|
+
const [adminMode, setAdminMode] = useState<boolean>(false);
|
|
204
194
|
const toggleAdminMode = useCallback(() => {
|
|
205
|
-
setAdminMode((prev) =>
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
195
|
+
setAdminMode((prev) => !prev);
|
|
196
|
+
}, []);
|
|
197
|
+
const adminItemKeys = useMemo(
|
|
198
|
+
() =>
|
|
199
|
+
items
|
|
200
|
+
.filter((it) => it.adminOnly === true)
|
|
201
|
+
.map((it) => it.key)
|
|
202
|
+
.sort()
|
|
203
|
+
.join(","),
|
|
204
|
+
[items],
|
|
205
|
+
);
|
|
206
|
+
const prevAdminKeysRef = useRef(adminItemKeys);
|
|
207
|
+
useEffect(() => {
|
|
208
|
+
if (prevAdminKeysRef.current !== adminItemKeys) {
|
|
209
|
+
prevAdminKeysRef.current = adminItemKeys;
|
|
210
|
+
// Context changed (typically: user navigated to a different
|
|
211
|
+
// page whose useActionBarItems registered a different set of
|
|
212
|
+
// admin actions). Reset admin mode so the elevated state is
|
|
213
|
+
// never carried across viewer sessions implicitly.
|
|
214
|
+
setAdminMode(false);
|
|
215
|
+
}
|
|
216
|
+
}, [adminItemKeys]);
|
|
211
217
|
const hasAdminItems = useMemo(() => items.some((it) => it.adminOnly === true), [items]);
|
|
212
218
|
// Filter semantics:
|
|
213
219
|
// admin OFF → hide items marked adminOnly (the toggle would reveal them)
|