UNPKG

@wix/design-system

Version:

@wix/design-system

571 lines (570 loc) 21.8 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.default = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireDefault(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _NestableListThemeSt = require("./NestableListTheme.st.css.js"); var _NestableListSt = require("./NestableList.st.css.js"); var _NestableListBase = _interopRequireDefault(require("../NestableListBase")); var _TableListItem = _interopRequireDefault(require("../TableListItem")); var _Box = _interopRequireDefault(require("../Box")); var _Arrow = require("./Arrow"); var _TextButton = _interopRequireDefault(require("../TextButton")); var _wixUiIconsCommon = require("@wix/wix-ui-icons-common"); var _utils = require("../NestableListBase/utils"); var _constants = require("./constants"); var _utils2 = require("./utils"); var _excluded = ["id", "children", "isCollapsed", "draggable", "dragDisabled", "hideDragHandle"]; var _jsxFileName = "/home/builduser/work/57e038ea7326c1ec/packages/wix-design-system/dist/cjs/NestableList/NestableList.js"; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } /** A styled list with drag and drop and nesting capabilities. */ class NestableList extends _react.default.PureComponent { constructor() { var _this; super(...arguments); _this = this; this.state = { movedItem: null, backup: null, isDragging: false, isInternalStateUpdate: false, items: this.props.items, normalizedIndentSize: _constants.DEFAULT_INDENT_SIZE }; // according to make possible use setState along with getDerivedStateFromProps // https://stackoverflow.com/questions/51019936/why-getderivedstatefromprops-is-called-after-setstate this._setStateDecorator = state => { this.setState(_objectSpread(_objectSpread({}, state), {}, { isInternalStateUpdate: true })); }; this._renderArrow = function () { var { isLastChild = false, isPreview = false, isPlaceholder } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return /*#__PURE__*/_react.default.createElement(_Box.default, { className: (0, _NestableListSt.st)(_NestableListSt.classes.arrowContainer, { indent: _this.state.normalizedIndentSize }), backgroundColor: isPlaceholder ? 'D60' : undefined, direction: "vertical", __self: _this, __source: { fileName: _jsxFileName, lineNumber: 65, columnNumber: 7 } }, /*#__PURE__*/_react.default.createElement("div", { className: (0, _NestableListSt.st)(_NestableListSt.classes.arrow, { lastChild: isLastChild, preview: isPreview, placeholder: isPlaceholder, offset: _this.state.normalizedIndentSize }), __self: _this, __source: { fileName: _jsxFileName, lineNumber: 72, columnNumber: 9 } }, /*#__PURE__*/_react.default.createElement(_Arrow.Arrow, { className: _NestableListSt.classes.horizontalArrow, __self: _this, __source: { fileName: _jsxFileName, lineNumber: 80, columnNumber: 11 } }))); }; this._renderActions = data => { var { isRootAction, veryLastItem, item } = data; var actions = isRootAction ? this.props.actions : item.actions; if (!actions) { return null; } var dataHook = isRootAction ? 'nestable-list-root-actions' : item.actionsDataHook; return /*#__PURE__*/_react.default.createElement("div", { "data-hook": dataHook, className: (0, _NestableListSt.st)(_NestableListSt.classes.item, { rootAction: isRootAction, last: veryLastItem, dragging: this.state.isDragging, withoutDividers: this.props.dividers === false, withoutBottomBorder: !this.props.withBottomBorder && (veryLastItem || isRootAction), indent: this.state.normalizedIndentSize }, _NestableListSt.classes.actionItem), __self: this, __source: { fileName: _jsxFileName, lineNumber: 97, columnNumber: 7 } }, /*#__PURE__*/_react.default.createElement(_TableListItem.default, { onClick: e => { if (actions.length === 1) { actions[0].onClick(e, item); } }, options: actions.map((action, index, arr) => { return { width: "fit-content(".concat(100 / arr.length, "%)"), value: /*#__PURE__*/_react.default.createElement(_TextButton.default, { dataHook: "nestable-list-action", ellipsis: true, size: "small", onClick: e => { // if one element event handler is fired on table list item if (arr.length !== 1) { action.onClick(e, item); } }, prefixIcon: action.prefixIcon, __self: this, __source: { fileName: _jsxFileName, lineNumber: 123, columnNumber: 17 } }, action.label) }; }), __self: this, __source: { fileName: _jsxFileName, lineNumber: 113, columnNumber: 9 } })); }; this._renderAction = data => { var label = data.isRootAction ? this.props.addItemLabel : data.item.addItemLabel; if (!label || this.props.maxDepth <= data.depth) { return; } return /*#__PURE__*/_react.default.createElement(_Box.default, { direction: "vertical", className: (0, _NestableListSt.st)(_NestableListSt.classes.item, { rootAction: data.isRootAction, last: data.veryLastItem, dragging: this.state.isDragging, withoutDividers: this.props.dividers === false, withoutBottomBorder: !this.props.withBottomBorder && (data.veryLastItem && !data.addItemLabel || data.isRootAction), indent: this.state.normalizedIndentSize }, _NestableListSt.classes.actionItem), __self: this, __source: { fileName: _jsxFileName, lineNumber: 154, columnNumber: 7 } }, /*#__PURE__*/_react.default.createElement(_TableListItem.default, { onClick: () => this.props.onAddItem(data.item), options: [{ value: /*#__PURE__*/_react.default.createElement(_Box.default, { __self: this, __source: { fileName: _jsxFileName, lineNumber: 176, columnNumber: 17 } }, /*#__PURE__*/_react.default.createElement(_TextButton.default, { size: "small", prefixIcon: /*#__PURE__*/_react.default.createElement(_wixUiIconsCommon.Add, { __self: this, __source: { fileName: _jsxFileName, lineNumber: 177, columnNumber: 56 } }), __self: this, __source: { fileName: _jsxFileName, lineNumber: 177, columnNumber: 19 } }, label)) }], __self: this, __source: { fileName: _jsxFileName, lineNumber: 171, columnNumber: 9 } })); }; this._renderPrefix = data => { if (data.isPreview || (0, _utils.isLastItem)(data.siblings, data.item) || (0, _utils.isRootItem)(data.depth)) { return null; } return /*#__PURE__*/_react.default.createElement("div", { className: (0, _NestableListSt.st)(_NestableListSt.classes.childArrow, { offset: this.state.normalizedIndentSize }), __self: this, __source: { fileName: _jsxFileName, lineNumber: 198, columnNumber: 7 } }); }; this._renderItem = options => { var { isPlaceholder, depth, isPreview, isVeryLastItem, siblings, item } = options; var { id, children, isCollapsed, draggable = true, dragDisabled, hideDragHandle } = item, rest = (0, _objectWithoutProperties2.default)(item, _excluded); var isLastChild = (0, _utils.isLastItem)(siblings, item); var focused = this.state.movedItem && id === this.state.movedItem.id; var hasExpandableSiblings = siblings == null ? void 0 : siblings.some(sibling => sibling.expandable); var hasDraggableSiblings = (siblings == null ? void 0 : siblings.some(sibling => !sibling.hideDragHandle)) && !this.props.readOnly; var isStatic = draggable === false && hideDragHandle === true || this.props.readOnly; var isDraggableWithDisabledHandle = !isStatic && (draggable === false || dragDisabled === true); var isDraggableWithoutHandle = !isStatic && hideDragHandle === true; return /*#__PURE__*/_react.default.createElement("div", { className: (0, _NestableListSt.st)(_NestableListSt.classes.itemWrapper, { dragEnabled: draggable && !this.props.readOnly }), "data-hook": item.dataHook ? "".concat(item.dataHook, "-item") : "styled-nestable-list-item-".concat(item.id), __self: this, __source: { fileName: _jsxFileName, lineNumber: 233, columnNumber: 7 } }, this.props.hierarchyIndicator && !(0, _utils.isRootItem)(depth) && this._renderArrow({ isLastChild, isPreview, isPlaceholder }), /*#__PURE__*/_react.default.createElement("div", { className: (0, _NestableListSt.st)(_NestableListSt.classes.item, { root: (0, _utils.isRootItem)(depth), firstSibling: (0, _utils.isFistItem)(siblings, item), last: isVeryLastItem, placeholder: isPlaceholder, preview: isPreview, focused, dragging: this.state.isDragging || focused, withoutDividers: this.props.dividers === false && !focused && !isPreview, withoutBottomBorder: isVeryLastItem && !this.props.withBottomBorder && !this.props.addItemLabel }), __self: this, __source: { fileName: _jsxFileName, lineNumber: 250, columnNumber: 9 } }, /*#__PURE__*/_react.default.createElement(_TableListItem.default, (0, _extends2.default)({}, rest, { className: (0, _NestableListSt.st)(rest.className, {}, _NestableListSt.classes.tableListItem), reserveExpandHandleSpace: hasExpandableSiblings, reserveDragHandleSpace: hasDraggableSiblings, focused: focused, onBlur: this._onBlur, onKeyUp: e => this._moveItemViaKeyboard(e, options), showDivider: false, dragging: isPreview || focused, draggable: !isStatic, dragDisabled: isDraggableWithDisabledHandle, hideDragHandle: isDraggableWithoutHandle, options: rest.options ? rest.options : [], dragHandleSize: this.props.dragHandleSize, showDragHandleOnHover: this.props.showDragHandleOnHover, __self: this, __source: { fileName: _jsxFileName, lineNumber: 267, columnNumber: 11 } })))); }; this._onBlur = () => { this._releaseItems(); }; this._moveItemViaKeyboard = (e, itemOptions) => { var left = 'ArrowLeft'; var top = 'ArrowUp'; var right = 'ArrowRight'; var bottom = 'ArrowDown'; var enter = 'Enter'; var esc = 'Escape'; // start dragend-drop if (e.key === enter && !this.state.movedItem) { this._setStateDecorator({ backup: this.state.items, movedItem: itemOptions.item, items: (0, _utils.setCollapse)(this.state.items, itemOptions.item.id, true) }); } if (!this.state.movedItem) { return; } switch (e.key) { case esc: this._setStateDecorator({ items: this.state.backup, backup: null, movedItem: null }); break; case left: if (!this.props.preventChangeDepth) { this._setStateDecorator({ items: (0, _utils.moveItemOutsideOfTheParent)(this.state.items, itemOptions.item) }); } break; case right: if (!this.props.preventChangeDepth) { this._setStateDecorator({ items: (0, _utils.moveItemToTheChildOfPrevSibling)(this.state.items, itemOptions.item) }); } break; case top: this._setStateDecorator({ items: (0, _utils.moveItemVertically)({ items: this.state.items, item: itemOptions.item, step: _utils.VerticalMovementDirection.top, preventChangeParent: this.props.preventChangeParent, enforcePinnedOrder: this.props.enforcePinnedOrder }) }); break; case bottom: this._setStateDecorator({ items: (0, _utils.moveItemVertically)({ items: this.state.items, item: itemOptions.item, step: _utils.VerticalMovementDirection.bottom, preventChangeParent: this.props.preventChangeParent, enforcePinnedOrder: this.props.enforcePinnedOrder }) }); break; default: case enter: this._releaseItems(); break; } }; this._onDragEnd = () => { this._setStateDecorator({ isDragging: false }); }; this._onDragStart = () => { this._setStateDecorator({ isDragging: true }); }; this._renderActionsFactory = function () { var data = arguments.length <= 0 ? undefined : arguments[0]; var actions = data.isRootAction ? _this.props.actions : data.item.actions; if (actions) { return _this._renderActions(...arguments); } return _this._renderAction(...arguments); }; } static getDerivedStateFromProps(props, state) { if (state.isInternalStateUpdate) { return _objectSpread(_objectSpread({}, state), {}, { isInternalStateUpdate: false }); } return { items: props.items, normalizedIndentSize: (0, _utils2.normalizeIndentSize)(props.indentSize) }; } _releaseItems() { if (this.state.movedItem) { var releaseItems = (0, _utils.setCollapse)(this.state.items, this.state.movedItem.id, this.state.movedItem.isCollapsed); this.props.onChange({ items: releaseItems, item: this.state.movedItem }); this._setStateDecorator({ movedItem: null, backup: null, items: releaseItems }); } } render() { var { dataHook, className, maxDepth, onChange, preventChangeDepth, preventChangeParent, enforcePinnedOrder, readOnly, zIndex, hierarchyIndicator } = this.props; var depthThreshold = (0, _utils2.getDepthThreshold)(this.state.normalizedIndentSize); return /*#__PURE__*/_react.default.createElement("div", { "data-hook": dataHook, className: (0, _NestableListSt.st)(_NestableListSt.classes.root, { dragEnabled: !readOnly }, className), __self: this, __source: { fileName: _jsxFileName, lineNumber: 427, columnNumber: 7 } }, /*#__PURE__*/_react.default.createElement(_NestableListBase.default, { items: this.state.items, renderItem: this._renderItem, renderPrefix: hierarchyIndicator ? this._renderPrefix : undefined, renderAction: this._renderActionsFactory, onDragEnd: this._onDragEnd, onDragStart: this._onDragStart, onUpdate: _ref => { var { items, item } = _ref; this._setStateDecorator({ items }); onChange({ items, item: item.data }); }, maxDepth: maxDepth, threshold: depthThreshold, theme: _NestableListThemeSt.classes, readOnly: readOnly, preventChangeDepth: preventChangeDepth, preventChangeParent: preventChangeParent, enforcePinnedOrder: enforcePinnedOrder, childrenStyle: { position: 'relative', marginLeft: "".concat(depthThreshold, "px") }, childrenProperty: "children", isRenderDraggingChildren: false, zIndex: zIndex, __self: this, __source: { fileName: _jsxFileName, lineNumber: 431, columnNumber: 9 } }), this._renderActionsFactory({ depth: 0, isRootAction: true })); } } NestableList.displayName = 'NestableList'; var actions = _propTypes.default.arrayOf(_propTypes.default.shape({ onClick: _propTypes.default.func, prefixIcon: _propTypes.default.node, label: _propTypes.default.string })); var Node = _objectSpread({ id: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]).isRequired, actions, dataHook: _propTypes.default.string, isCollapsed: _propTypes.default.bool, addItemLabel: _propTypes.default.string }, _TableListItem.default.propTypes); var NodeShape = _propTypes.default.shape(Node); Node.children = _propTypes.default.arrayOf(NodeShape); NestableList.propTypes = { /** Actions that will be rendered for on the root depth level */ actions, /** Adds a bottom border (divider) to the last item. */ withBottomBorder: _propTypes.default.bool, /** Prevents the list from being reordered by removing the dragging grip icons. */ readOnly: _propTypes.default.bool, /** Adds a button to create a new item (to the Root or a child to the existing item). */ addItemLabel: _propTypes.default.string, /** Size of the drag handle */ dragHandleSize: _propTypes.default.oneOf(['small', 'large']), /** Shows the drag handle only on hover. */ showDragHandleOnHover: _propTypes.default.bool, /** Triggers function when the "Add new ..." button is clicked. */ onAddItem: _propTypes.default.func, /** Triggers function when the item’s order or nesting position is changed. */ onChange: _propTypes.default.func, /** Defines a maximum depth (number of levels) for the list. */ maxDepth: _propTypes.default.number, /** Allows dragging and dropping an item only on its own depth (inside the same level). */ preventChangeDepth: _propTypes.default.bool, /** Allows dragging and dropping an item only on its own parent. */ preventChangeParent: _propTypes.default.bool, /** Allows dragging and dropping an item only on its pin section. */ enforcePinnedOrder: _propTypes.default.bool, /** * Defines each Nestable List item individually, using the following props: * * __id__ - specifies an item’s ID. * * __addItemLabel__ - creates the “Add new ...” button with a given label at the bottom of the item. * * __isCollapsed__ - bool prop, defines whether to render the item’s children. * * __children__ - defines an item’s children. * * __draggable__ - bool prop, turns on / off dragging ability for an item. * * __hideDragHandle__ - bool prop, turns on / off drag handle for an item. * * All <a href="https://www.wix-pages.com/wix-design-system-employees/?path=/story/components-lists-table--tablelistitem" target="_blank">`<TableListItem/>`</a> props can be used to format item’s style and content. */ items: _propTypes.default.arrayOf(NodeShape), /** Can be applied in the tests as a data-hook HTML attribute. */ dataHook: _propTypes.default.string, /** Specifies a CSS class name to be appended to the component’s root element. * @internal */ className: _propTypes.default.string, /** Defines the zIndex of the draggable layer */ zIndex: _propTypes.default.number, /** Sets the divider visibility */ dividers: _propTypes.default.bool, /** Sets the indent size */ indentSize: _propTypes.default.oneOf(_constants.indentSizes), /** Displays hierarchyIndicator from the parent to children */ hierarchyIndicator: _propTypes.default.bool }; NestableList.defaultProps = { maxDepth: 10, withBottomBorder: false, preventChangeDepth: false, preventChangeParent: false, dragHandleSize: 'large', showDragHandleOnHover: false, enforcePinnedOrder: false, hierarchyIndicator: true, items: [], onAddItem: () => {} }; var _default = exports.default = NestableList; //# sourceMappingURL=NestableList.js.map