@mui/x-tree-view
Version:
The community edition of the MUI X Tree View components.
158 lines (148 loc) • 7.85 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.MinimalTreeViewStore = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _store = require("@mui/x-internals/store");
var _warning = require("@mui/x-internals/warning");
var _EventManager = require("@mui/x-internals/EventManager");
var _disposable = require("@mui/x-internals/disposable");
var _MinimalTreeViewStore = require("./MinimalTreeViewStore.utils");
var _TimeoutManager = require("./TimeoutManager");
var _keyboardNavigation = require("../plugins/keyboardNavigation");
var _TreeViewFocusPlugin = require("../plugins/focus/TreeViewFocusPlugin");
var _TreeViewItemsPlugin = require("../plugins/items/TreeViewItemsPlugin");
var _TreeViewSelectionPlugin = require("../plugins/selection/TreeViewSelectionPlugin");
var _expansion = require("../plugins/expansion");
var _TreeViewItemPluginManager = require("./TreeViewItemPluginManager");
class MinimalTreeViewStore extends _store.Store {
initialParameters = null;
// Owns the store's teardown. Declared first so the resources below register
// against it during field initialization; disposed by `useDisposable` on
// unmount (see `[disposeSymbol]`). `public` so plugins can register their own
// subscriptions against it (hidden from the context store type).
disposables = new _disposable.DisposableStack();
eventManager = this.disposables.adopt(new _EventManager.EventManager(), manager => manager.removeAllListeners());
timeoutManager = this.disposables.adopt(new _TimeoutManager.TimeoutManager(), manager => manager.clearAll());
itemPluginManager = new _TreeViewItemPluginManager.TreeViewItemPluginManager();
constructor(parameters, instanceName, mapper) {
const minimalInitialState = (0, _MinimalTreeViewStore.createMinimalInitialState)(parameters);
const initialState = mapper.getInitialState(minimalInitialState, parameters);
super(initialState);
this.parameters = parameters;
this.instanceName = instanceName;
this.mapper = mapper;
// We mount the plugins in the constructor to make sure all the methods of the store are available to the plugins during their construction.
this.items = new _TreeViewItemsPlugin.TreeViewItemsPlugin(this);
this.focus = new _TreeViewFocusPlugin.TreeViewFocusPlugin(this);
this.expansion = new _expansion.TreeViewExpansionPlugin(this);
this.selection = new _TreeViewSelectionPlugin.TreeViewSelectionPlugin(this);
this.keyboardNavigation = new _keyboardNavigation.TreeViewKeyboardNavigationPlugin(this);
if (process.env.NODE_ENV !== 'production') {
this.initialParameters = parameters;
}
}
/**
* Builds an object containing the method that should be exposed publicly by the Tree View components.
*/
buildPublicAPI() {
return (0, _extends2.default)({}, this.items.buildPublicAPI(), this.focus.buildPublicAPI(), this.expansion.buildPublicAPI(), this.selection.buildPublicAPI());
}
/**
* Updates the state of the Tree View based on the new parameters provided to the root component.
*/
updateStateFromParameters(parameters) {
const updateModel = (mutableNewState, controlledProp, defaultProp) => {
if (parameters[controlledProp] !== undefined) {
mutableNewState[controlledProp] = parameters[controlledProp];
}
if (process.env.NODE_ENV !== 'production') {
const defaultValue = parameters[defaultProp];
const isControlled = parameters[controlledProp] !== undefined;
const initialDefaultValue = this.initialParameters?.[defaultProp];
const initialIsControlled = this.initialParameters?.[controlledProp] !== undefined;
if (initialIsControlled !== isControlled) {
(0, _warning.warnOnce)([`MUI X Tree View: A component is changing the ${initialIsControlled ? '' : 'un'}controlled ${controlledProp} state of ${this.instanceName} to be ${initialIsControlled ? 'un' : ''}controlled.`, 'Elements should not switch from uncontrolled to controlled (or vice versa).', `Decide between using a controlled or uncontrolled ${controlledProp} element for the lifetime of the component.`, "The nature of the state is determined during the first render. It's considered controlled if the value is not `undefined`.", 'More info: https://fb.me/react-controlled-components'], 'error');
} else if (JSON.stringify(initialDefaultValue) !== JSON.stringify(defaultValue)) {
(0, _warning.warnOnce)([`MUI X Tree View: A component is changing the default ${controlledProp} state of an uncontrolled ${this.instanceName} after being initialized. `, `To suppress this warning opt to use a controlled ${this.instanceName}.`], 'error');
}
}
};
const newMinimalState = (0, _MinimalTreeViewStore.deriveStateFromParameters)(parameters);
updateModel(newMinimalState, 'expandedItems', 'defaultExpandedItems');
updateModel(newMinimalState, 'selectedItems', 'defaultSelectedItems');
if (this.state.providedTreeId !== parameters.id || this.state.treeId === undefined) {
newMinimalState.treeId = (0, _MinimalTreeViewStore.createTreeViewDefaultId)();
}
if (!this.mapper.shouldIgnoreItemsStateUpdate(parameters) && _TreeViewItemsPlugin.TreeViewItemsPlugin.shouldRebuildItemsState(parameters, this.parameters)) {
Object.assign(newMinimalState, _TreeViewItemsPlugin.TreeViewItemsPlugin.buildItemsStateIfNeeded(parameters));
}
const newState = this.mapper.updateStateFromParameters(newMinimalState, parameters, updateModel);
this.update(newState);
this.parameters = parameters;
}
/**
* Runs mount-time side effects that must not happen during render (the store
* is created during render by `useDisposable`). No-op by default; overridden
* by stores that kick off work on mount (e.g. lazy-loading fetches). Safe to
* call more than once (StrictMode replays mount effects).
*/
mountEffect = () => {};
/**
* Disposes the store synchronously when the component unmounts. `useDisposable`
* handles React StrictMode's simulated unmount, so this runs once on real unmount.
*/
[_disposable.disposeSymbol]() {
if (this.disposables.disposed) {
return;
}
try {
this.disposables.dispose();
} catch (error) {
if (process.env.NODE_ENV !== 'production') {
console.error('MUI X Tree View: error while disposing the store.', ...(0, _disposable.unwrapSuppressedErrors)(error));
}
}
}
/**
* Whether updates based on `props.items` change should be ignored.
*/
shouldIgnoreItemsStateUpdate = () => {
return this.mapper.shouldIgnoreItemsStateUpdate(this.parameters);
};
/**
* Registers an effect to be run when the value returned by the selector changes.
*/
registerStoreEffect = (selector, effect) => {
let previousValue = selector(this.state);
this.disposables.defer(this.subscribe(state => {
const nextValue = selector(state);
if (nextValue !== previousValue) {
effect(previousValue, nextValue);
previousValue = nextValue;
}
}));
};
/**
* Publishes an event to all its subscribers.
*/
publishEvent = (name, params, event) => {
if (isSyntheticEvent(event) && event.isPropagationStopped()) {
return;
}
this.eventManager.emit(name, params, event);
};
/**
* Subscribe to an event emitted by the store.
* For now, the subscription is only removed when the store is destroyed.
*/
subscribeEvent = (eventName, handler) => {
this.eventManager.on(eventName, handler);
};
}
exports.MinimalTreeViewStore = MinimalTreeViewStore;
function isSyntheticEvent(event) {
return event?.isPropagationStopped !== undefined;
}