Skip to content

Commit

Permalink
Added PanelStack
Browse files Browse the repository at this point in the history
  • Loading branch information
viktor-podzigun committed Dec 6, 2024
1 parent 203093f commit c92161c
Show file tree
Hide file tree
Showing 7 changed files with 502 additions and 21 deletions.
127 changes: 127 additions & 0 deletions src/stack/PanelStack.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/**
* @typedef {import("./PanelStackItem.mjs").ReactComponent} ReactComponent
*/
import PanelStackItem from "./PanelStackItem.mjs";

class PanelStack {
/**
* @param {boolean} isActive
* @param {PanelStackItem<any>[]} data
* @param {(f: (data: PanelStackItem<any>[]) => PanelStackItem<any>[]) => void} updater
*/
constructor(isActive, data, updater) {
/** @readonly @type {boolean} */
this.isActive = isActive;

/** @private @readonly @type {PanelStackItem<any>[]} */
this._data = data;

/** @private @readonly @type {(f: (data: PanelStackItem<any>[]) => PanelStackItem<any>[]) => void} */
this._updater = updater;
}

/**
* @param {PanelStackItem<any>} item
* @returns {void}
*/
push(item) {
this._updater((data) => [item, ...data]);
}

/**
* @template T
* @param {(data: PanelStackItem<T>) => PanelStackItem<T>} f
* @returns {void}
*/
update(f) {
this._updater((data) => {
if (data.length === 0) {
return data;
}

const [head, ...tail] = data;
return [f(head), ...tail];
});
}

/**
* @template T
* @param {ReactComponent} component
* @param {(data: PanelStackItem<T>) => PanelStackItem<T>} f
* @returns {void}
*/
updateFor(component, f) {
this._updater((data) => {
return data.map((item) => {
return item.component === component ? f(item) : item;
});
});
}

/**
* @returns {void}
*/
pop() {
this._updater((data) => {
if (data.length > 1) {
const [_, ...tail] = data;
return tail;
}

return data;
});
}

/**
* @returns {void}
*/
clear() {
this._updater((data) => {
if (data.length > 1) {
const last = data[data.length - 1];
return [last];
}

return data;
});
}

/**
* @template T
* @returns {PanelStackItem<T>}
*/
peek() {
ensureNonEmpty(this._data);

return this._data[0];
}

/**
* @template T
* @returns {PanelStackItem<T>}
*/
peekLast() {
ensureNonEmpty(this._data);

return this._data[this._data.length - 1];
}

/**
* @template T
* @returns {T}
*/
params() {
return this.peek().state;
}
}

/**
* @param {PanelStackItem<any>[]} data
*/
function ensureNonEmpty(data) {
if (data.length === 0) {
throw Error("PanelStack is empty!");
}
}

export default PanelStack;
8 changes: 6 additions & 2 deletions src/stack/PanelStackItem.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,22 @@ import FileListData from "../FileListData.mjs";
import FileListState from "../FileListState.mjs";
import FileListActions from "../FileListActions.mjs";

/**
* @typedef {React.FunctionComponent<any> | React.ComponentClass<any>} ReactComponent
*/

/**
* @template T
*/
class PanelStackItem {
/**
* @param {React.FunctionComponent<any> | React.ComponentClass<any>} component
* @param {ReactComponent} component
* @param {Dispatch} [dispatch]
* @param {FileListActions} [actions]
* @param {T} [state]
*/
constructor(component, dispatch, actions, state) {
/** @readonly @type {React.FunctionComponent<any> | React.ComponentClass<any>} */
/** @readonly @type {ReactComponent} */
this.component = component;

/** @readonly @type {Dispatch | undefined} */
Expand Down
1 change: 1 addition & 0 deletions test/all.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ await import("./history/HistoryProvider.test.mjs");

await import("./sort/FileListSort.test.mjs");

await import("./stack/PanelStack.test.mjs");
await import("./stack/PanelStackItem.test.mjs");

await import("./theme/FileListTheme.test.mjs");
Loading

0 comments on commit c92161c

Please sign in to comment.