@atlaskit/navigation-system
Version:
The latest navigation system for Atlassian apps.
253 lines (244 loc) • 13.1 kB
JavaScript
/* panel.tsx generated by @compiled/babel-plugin v3.0.2 */
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Panel = Panel;
require("./panel.compiled.css");
var _react = _interopRequireWildcard(require("react"));
var React = _react;
var _runtime = require("@compiled/react/runtime");
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _mergeRefs = _interopRequireDefault(require("@atlaskit/ds-lib/merge-refs"));
var _useMotion3 = require("@atlaskit/motion/entering/use-motion");
var _exitingPersistence = _interopRequireDefault(require("@atlaskit/motion/exiting-persistence"));
var _reanimate = require("@atlaskit/motion/reanimate");
var _fg = require("@atlaskit/platform-feature-flags/fg");
var _useSkipLinkInternal = require("../../context/skip-links/use-skip-link-internal");
var _constants = require("./constants");
var _dangerouslyHoistCssVarToDocumentRoot = require("./dangerously-hoist-css-var-to-document-root");
var _hoistSlotSizesContext = require("./hoist-slot-sizes-context");
var _provider = require("./panel-splitter/provider");
var _useSideNavRef = require("./side-nav/use-side-nav-ref");
var _useLayoutId = require("./use-layout-id");
var _useResizingWidthCssVarOnRootElement = require("./use-resizing-width-css-var-on-root-element");
var _useSafeDefaultWidth = require("./use-safe-default-width");
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
// eslint-disable-next-line @atlaskit/design-system/no-emotion-primitives -- TODO: migrate to @atlaskit/primitives/compiled
var panelSplitterResizingVar = '--n_pnlRsz';
var fallbackDefaultWidth = 365;
/**
* We typically use the `defaultWidth` as the minimum resizing width,
* but for large default widths we fallback to a standard value.
*
* This standard value of `400px` is to align with the Global Preview Panels.
*/
var fallbackResizeMinWidth = 400;
var styles = {
root: "_nd5l1b6c _10fph9n0 _vchhusvi _1pbykb7n _4t3ieqxy _kqsw1if8 _152timx3 _bfhk1bhr _1bsb1dxx _14b54rrg _4ap3vuon _1dhy1c6w _9sns1wug",
border: "_191wglyw _16qs130s _1w6eia51 _scbpglyw",
scrollContainer: "_1reo1wug _18m91wug _4t3i1osq",
hidden: "_1e0cglyw",
entering: "_k1af1nn1 _10t81ia4 _xrrp147i _1wsa4so3 _1vrh1a5r _1kmh1n9t _105abamb",
exiting: "_k1af14vv _10t81ia4 _xrrp147i _1wsa1jkh _1vrh1a5r _bq641n9t _105aeydr",
contentEntering: "_y44v1mph",
contentExiting: "_y44vf1qi",
contentChangeContainer: "_4t3i1osq"
};
var PanelContentMotion = function PanelContentMotion(_ref) {
var children = _ref.children;
var _useMotion = (0, _useMotion3.useMotion)(),
state = _useMotion.state,
ref = _useMotion.ref;
return /*#__PURE__*/React.createElement("div", {
ref: ref,
className: (0, _runtime.ax)([styles.contentChangeContainer, state === 'entering' && styles.contentEntering, state === 'exiting' && styles.contentExiting])
}, children);
};
/**
* The Panel layout area is rendered to the right (inline end) of the Main area, or the Aside area if it is present.
*
* On small viewports (below 64rem, or 1024px), the Panel slot will become an overlay.
*
* You can optionally render a `PanelSplitter` as a child to make the panel area resizable.
*/
function Panel(_ref2) {
var children = _ref2.children,
_ref2$defaultWidth = _ref2.defaultWidth,
defaultWidthProp = _ref2$defaultWidth === void 0 ? fallbackDefaultWidth : _ref2$defaultWidth,
_ref2$label = _ref2.label,
label = _ref2$label === void 0 ? 'Panel' : _ref2$label,
_ref2$skipLinkLabel = _ref2.skipLinkLabel,
skipLinkLabel = _ref2$skipLinkLabel === void 0 ? label : _ref2$skipLinkLabel,
testId = _ref2.testId,
providedId = _ref2.id,
xcss = _ref2.xcss,
_ref2$hasBorder = _ref2.hasBorder,
hasBorder = _ref2$hasBorder === void 0 ? true : _ref2$hasBorder,
maxWidth = _ref2.maxWidth,
contentKey = _ref2.contentKey;
var dangerouslyHoistSlotSizes = (0, _react.useContext)(_hoistSlotSizesContext.DangerouslyHoistSlotSizes);
var id = (0, _useLayoutId.useLayoutId)({
providedId: providedId
});
var isMotionUpliftEnabled = (0, _fg.fg)('platform-dst-motion-uplift-panel');
var isContentMotionEnabled = (0, _fg.fg)('platform-dst-motion-uplift-panel-content');
var prevContentKeyRef = (0, _react.useRef)(contentKey);
(0, _react.useEffect)(function () {
if (isContentMotionEnabled && contentKey !== undefined) {
prevContentKeyRef.current = contentKey;
}
}, [contentKey, isContentMotionEnabled]);
var defaultWidth = (0, _useSafeDefaultWidth.useSafeDefaultWidth)({
defaultWidthProp: defaultWidthProp,
fallbackDefaultWidth: fallbackDefaultWidth,
slotName: 'Panel'
});
// useMotion is applied only when the `platform-dst-motion-uplift-panel` gate is enabled.
var _useMotion2 = (0, _useMotion3.useMotion)({
onFinish: function onFinish(state) {
if (state === 'exiting' && defaultWidthRef.current === 0) {
// Set width to 0 as animation is complete
setWidth(0);
}
},
initialState: defaultWidth === 0 ? 'hidden' : undefined
}),
state = _useMotion2.state,
motionRef = _useMotion2.ref,
reanimate = _useMotion2.reanimate;
/**
* Don't show the skip link if the slot has 0 width.
*
* Remove `isHidden` usage after https://jplat.atlassian.net/browse/BLU-3951
*
* TODO: when cleaning up 'platform_dst_nav4_skip_link_a11y_1' remove this call entirely
*/
(0, _useSkipLinkInternal.useSkipLinkInternal)({
id: id,
label: skipLinkLabel,
isHidden: defaultWidth === 0 || (0, _fg.fg)('platform_dst_nav4_skip_link_a11y_1')
});
var ref = (0, _react.useRef)(null);
var _useState = (0, _react.useState)(defaultWidth),
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
width = _useState2[0],
setWidth = _useState2[1];
// Used to track the previous value of the `defaultWidth` prop, for logging dev warnings when it changes.
var defaultWidthRef = (0, _react.useRef)(defaultWidth);
// `mergeRefs` returns a new callback ref on every call, and combined with a new array literal
// this would cause React to detach/re-attach the ref on every render. Memoise it so the merged
// ref is stable across renders.
var mergedRef = (0, _react.useMemo)(function () {
return isMotionUpliftEnabled ? (0, _mergeRefs.default)([ref, motionRef]) : ref;
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[isMotionUpliftEnabled, motionRef]);
/**
* TODO: Remove this useEffect once the `width: 0` usage is removed from Jira.
* It updates the width state based on changes to `defaultWidth`, as a temporary stopgap to support Jira's current usage.
* https://jplat.atlassian.net/browse/BLU-3951
*/
(0, _react.useEffect)(function () {
if (defaultWidthRef.current === defaultWidth) {
return;
}
if (isMotionUpliftEnabled) {
if (defaultWidth === 0) {
reanimate(_reanimate.Reanimate.exit);
defaultWidthRef.current = defaultWidth;
// Set width to 0 once the exit animation is complete
return;
} else if (defaultWidthRef.current === 0) {
reanimate(_reanimate.Reanimate.enter);
}
}
defaultWidthRef.current = defaultWidth;
setWidth(defaultWidth);
if (process.env.NODE_ENV !== 'production') {
// eslint-disable-next-line no-console
console.warn('Page Layout warning\n\n', 'The value of the `defaultWidth` prop on the `Panel` layout slot component has changed. This should not be changed after the component has been mounted.\n\n', 'In the future, changes to the `defaultWidth` prop will not be respected. It is only supported as a stopgap to enable migration from Nav3 to Nav4.\n\n');
}
}, [defaultWidth, isMotionUpliftEnabled, reanimate]);
var sideNavRef = (0, _useSideNavRef.useSideNavRef)();
/**
* The minimum width that the panel can be resized to by the user.
*
* We only use the `defaultWidth` up to a point to avoid huge panels.
*/
var minWidth = Math.min(defaultWidth, fallbackResizeMinWidth);
/**
* Returns the bounds for resizing, evaluated lazily when needed.
*
* Defined separately to the slot bounds because the resizing bounds need to be resolvable to a pixel value,
* and the panel's slot bounds use a complex CSS expression.
*/
var getResizeBounds = (0, _react.useCallback)(function () {
var _sideNavRef$current$o, _sideNavRef$current;
var sideNavWidth = (_sideNavRef$current$o = (_sideNavRef$current = sideNavRef.current) === null || _sideNavRef$current === void 0 ? void 0 : _sideNavRef$current.offsetWidth) !== null && _sideNavRef$current$o !== void 0 ? _sideNavRef$current$o : 0;
/**
* By default the panel should not resize larger than the page content, equivalent to the `Main` + `Aside` slots.
*
* This maximum width is equivalent to half the viewport width, after removing the sidebar width.
*
* Consumers can opt in to a larger maximum via the `maxWidth` prop.
*/
var defaultMaxWidth = "".concat(Math.round((window.innerWidth - sideNavWidth) / 2), "px");
return {
min: "".concat(minWidth, "px"),
max: maxWidth !== null && maxWidth !== void 0 ? maxWidth : defaultMaxWidth
};
}, [maxWidth, minWidth, sideNavRef]);
var panelWidthSlotBounds = {
min: "".concat(minWidth, "px"),
// `sideNavLiveWidthVar` is not defined if the `SideNav` is not mounted, so we fallback to `0px`.
// Consumers can opt in to a larger maximum via the `maxWidth` prop.
max: maxWidth !== null && maxWidth !== void 0 ? maxWidth : "round(nearest, calc((100vw - var(".concat(_constants.sideNavLiveWidthVar, ", 0px)) / 2), 1px)")
};
var panelVariableWidth = "clamp(".concat(panelWidthSlotBounds.min, ", ").concat(width, "px, ").concat(panelWidthSlotBounds.max, ")");
(0, _useResizingWidthCssVarOnRootElement.useResizingWidthCssVarOnRootElement)({
isEnabled: dangerouslyHoistSlotSizes,
cssVar: panelSplitterResizingVar,
panelId: _constants.panelPanelSplitterId
});
return /*#__PURE__*/React.createElement("section", {
id: id,
"data-layout-slot": true,
"aria-label": label
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
,
className: (0, _runtime.ax)([styles.root, isMotionUpliftEnabled && state === 'hidden' && styles.hidden, isMotionUpliftEnabled && state === 'entering' && styles.entering, isMotionUpliftEnabled && state === 'exiting' && styles.exiting, !isMotionUpliftEnabled && defaultWidth === 0 && styles.hidden, hasBorder && styles.border, xcss]),
style: (0, _defineProperty2.default)((0, _defineProperty2.default)({}, _constants.panelVar, panelVariableWidth), '--minWidth', "".concat(minWidth, "px")),
"data-testid": testId,
ref: mergedRef
}, dangerouslyHoistSlotSizes &&
/*#__PURE__*/
// ------ START UNSAFE STYLES ------
// These styles are only needed for the UNSAFE legacy use case for Jira + Confluence.
// When they aren't needed anymore we can delete them wholesale.
React.createElement(_dangerouslyHoistCssVarToDocumentRoot.DangerouslyHoistCssVarToDocumentRoot, {
variableName: _constants.UNSAFE_panelLayoutVar,
value: "0px",
mediaQuery: '@media (min-width: 90rem)',
responsiveValue: "var(".concat(panelSplitterResizingVar, ", ").concat(panelVariableWidth, ")")
})
// ------ END UNSAFE STYLES ------
, /*#__PURE__*/React.createElement(_provider.PanelSplitterProvider, {
panelId: _constants.panelPanelSplitterId,
panelRef: ref,
panelWidth: width,
onCompleteResize: setWidth,
getResizeBounds: getResizeBounds,
resizingCssVar: panelSplitterResizingVar,
position: "start"
}, /*#__PURE__*/React.createElement("div", {
className: (0, _runtime.ax)([styles.scrollContainer, isMotionUpliftEnabled && state === 'entering' && styles.contentEntering, isMotionUpliftEnabled && state === 'exiting' && styles.contentExiting])
}, isContentMotionEnabled ? /*#__PURE__*/React.createElement(_exitingPersistence.default, {
exitThenEnter: contentKey !== undefined
}, /*#__PURE__*/React.createElement(PanelContentMotion, {
key: contentKey === undefined ? prevContentKeyRef.current : contentKey
}, children)) : children)));
}