mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
80f31bffc2
Summary: Tweak PagePanels to let the left pane automatically expand on mouse over. This is to make pages more accessible when the panel is collapsed. In this context, when expanding, the left panel overlap the main content, reducing visual clutter. Test Plan: updated Reviewers: jarek Reviewed By: jarek Subscribers: anaisconce, jarek Differential Revision: https://phab.getgrist.com/D3516
65 lines
2.5 KiB
TypeScript
65 lines
2.5 KiB
TypeScript
/**
|
|
* createSessionObs() creates an observable tied to window.sessionStorage, i.e. preserved for the
|
|
* lifetime of a browser tab for the current origin.
|
|
*/
|
|
import {safeJsonParse} from 'app/common/gutil';
|
|
import {IDisposableOwner, Observable} from 'grainjs';
|
|
|
|
export interface SessionObs<T> extends Observable<T> {
|
|
pauseSaving(yesNo: boolean): void;
|
|
}
|
|
|
|
/**
|
|
* Creates and returns an Observable tied to sessionStorage, to make its value stick across
|
|
* reloads and navigation, but differ across browser tabs. E.g. whether a side pane is open.
|
|
*
|
|
* The `key` isn't visible to the user, so pick any unique string name. You may include the
|
|
* docId into the key, to remember a separate value for each doc.
|
|
*
|
|
* To use it, you must specify a default, and a validation function: this module exposes a few
|
|
* helpful ones. Some examples:
|
|
*
|
|
* panelWidth = createSessionObs(owner, "panelWidth", 240, isNumber); // Has type Observable<number>
|
|
*
|
|
* import {StringUnion} from 'app/common/StringUnion';
|
|
* const SomeTab = StringUnion("foo", "bar", "baz");
|
|
* tab = createSessionObs(owner, "tab", "baz", SomeTab.guard); // Type Observable<"foo"|"bar"|"baz">
|
|
*
|
|
* You can disable saving to sessionStorage:
|
|
* panelWidth.pauseSaving(true);
|
|
* doStuff();
|
|
* panelWidth.pauseSaving(false);
|
|
*
|
|
*/
|
|
export function createSessionObs<T>(
|
|
owner: IDisposableOwner|null,
|
|
key: string,
|
|
_default: T,
|
|
isValid: (val: any) => val is T,
|
|
): SessionObs<T> {
|
|
function fromString(value: string|null): T {
|
|
const parsed = value == null ? null : safeJsonParse(value, null);
|
|
return isValid(parsed) ? parsed : _default;
|
|
}
|
|
function toString(value: T): string|null {
|
|
return value === _default || !isValid(value) ? null : JSON.stringify(value);
|
|
}
|
|
let _pauseSaving = false;
|
|
const obs = Observable.create<T>(owner, fromString(window.sessionStorage.getItem(key)));
|
|
obs.addListener((value: T) => {
|
|
if (_pauseSaving) { return; }
|
|
const stored = toString(value);
|
|
if (stored == null) {
|
|
window.sessionStorage.removeItem(key);
|
|
} else {
|
|
window.sessionStorage.setItem(key, stored);
|
|
}
|
|
});
|
|
return Object.assign(obs, {pauseSaving(yesNo: boolean) { _pauseSaving = yesNo; }});
|
|
}
|
|
|
|
/** Helper functions to check simple types, useful for the `isValid` argument to createSessionObs. */
|
|
export function isNumber(t: any): t is number { return typeof t === 'number'; }
|
|
export function isBoolean(t: any): t is boolean { return typeof t === 'boolean'; }
|
|
export function isString(t: any): t is string { return typeof t === 'string'; }
|