UNPKG

@atlaskit/navigation-system

Version:

The latest navigation system for Atlassian apps.

210 lines (209 loc) • 12.1 kB
/* chat-panel.tsx generated by @compiled/babel-plugin v3.0.2 */ import _defineProperty from "@babel/runtime/helpers/defineProperty"; import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; import "./chat-panel.compiled.css"; import * as React from 'react'; import { ax, ix } from "@compiled/react/runtime"; import { useCallback, useEffect, useRef, useState } from 'react'; import { bind } from 'bind-event-listener'; import { fg } from '@atlaskit/platform-feature-flags/fg'; import { useSkipLinkInternal } from '../../context/skip-links/use-skip-link-internal'; import { chatPanelLiveWidthVar, chatPanelVar, defaultMainMinWidth, localSlotLayers, mainMinimumWidthVar } from './constants'; import { convertResizeBoundToPixels } from './panel-splitter/convert-resize-bound-to-pixels'; import { PanelSplitterProvider } from './panel-splitter/provider'; import { resolveLayoutWidth } from './resolve-layout-width'; import { gridRootId } from './root'; import { useLayoutAreaSizing } from './use-layout-area-sizing'; import { useLayoutId } from './use-layout-id'; import { useResizingWidthCssVarOnRootElement } from './use-resizing-width-css-var-on-root-element'; import { useSafeDefaultWidth } from './use-safe-default-width'; var chatPanelPanelSplitterId = Symbol('ChatPanel PanelSplitter'); var panelSplitterResizingVar = '--n_cPnlRsz'; var chatPanelOverlayWidthVar = '--n_cPnlOverlayW'; var fallbackDefaultWidth = 400; var fallbackCompactDefaultWidth = 320; var fallbackMinWidth = '320px'; var inlineMediaQuery = '(min-width: 40rem)'; function getPixelCustomProperty(element, propertyName, fallback) { var raw = getComputedStyle(element).getPropertyValue(propertyName).trim(); var value = Number.parseFloat(raw); return Number.isFinite(value) ? resolveLayoutWidth(raw.endsWith('vw') ? "".concat(value, "vw") : value, window.innerWidth) : fallback; } var styles = { root: "_nd5lquub _10fph9n0 _vchhusvi _p12f1osq _1pbyqfx8 _4t3i56xv _kqsw1if8 _152t1nws _bfhk1bhr _1bsb1ky5 _qhdr1ym0 _m5h51wug _1ttbvuon _1mxh8rg1", managedInline: "_12xt1ym0 _qo371wug _16hgvuon _w1ap8rg1", managedOverlay: "_12xtquub _qo37qfx8 _16hg1bhr _w1ap1ky5", scrollContainer: "_1reo1wug _18m91wug _4t3i1osq", border: "_191wglyw _16qs130s _19dmia51 _1ao7glyw", managedInlineBorder: "_i8luia51 _so1eglyw", managedOverlayBorder: "_i8luglyw _so1e130s" }; /** * The ChatPanel layout area is rendered below the banner and to the right (inline end) of the app. * * Below 40rem it overlays the app. At 40rem and above it is rendered as the final * full-height column in the page layout grid. * * You can optionally render a `PanelSplitter` as a child to make the chat panel resizable. */ export function ChatPanel(_ref) { var _managedSizing$mode, _managedSizing$width; var children = _ref.children, defaultWidthProp = _ref.defaultWidth, _ref$minWidth = _ref.minWidth, minWidth = _ref$minWidth === void 0 ? fallbackMinWidth : _ref$minWidth, maxWidth = _ref.maxWidth, _ref$label = _ref.label, label = _ref$label === void 0 ? 'Chat panel' : _ref$label, _ref$skipLinkLabel = _ref.skipLinkLabel, skipLinkLabel = _ref$skipLinkLabel === void 0 ? label : _ref$skipLinkLabel, testId = _ref.testId, providedId = _ref.id, xcss = _ref.xcss, _ref$hasBorder = _ref.hasBorder, hasBorder = _ref$hasBorder === void 0 ? true : _ref$hasBorder, onClose = _ref.onClose; var id = useLayoutId({ providedId: providedId }); var defaultWidth = useSafeDefaultWidth({ defaultWidthProp: defaultWidthProp !== null && defaultWidthProp !== void 0 ? defaultWidthProp : fallbackDefaultWidth, fallbackDefaultWidth: fallbackDefaultWidth, slotName: 'ChatPanel' }); var compactDefaultWidth = defaultWidthProp === undefined ? fallbackCompactDefaultWidth : defaultWidth; useSkipLinkInternal({ id: id, label: skipLinkLabel, isHidden: defaultWidth === 0 || fg('platform_dst_nav4_skip_link_a11y_1') }); var ref = useRef(null); var _useState = useState(defaultWidth), _useState2 = _slicedToArray(_useState, 2), inlineWidth = _useState2[0], setInlineWidth = _useState2[1]; var _useState3 = useState(compactDefaultWidth), _useState4 = _slicedToArray(_useState3, 2), overlayWidth = _useState4[0], setOverlayWidth = _useState4[1]; var _useState5 = useState(false), _useState6 = _slicedToArray(_useState5, 2), isInline = _useState6[0], setIsInline = _useState6[1]; var _useLayoutAreaSizing = useLayoutAreaSizing({ area: 'chat-panel', config: { defaultWidth: defaultWidth, compactDefaultWidth: compactDefaultWidth, minWidth: minWidth, maxWidth: maxWidth, isOpen: true, onRequestClose: onClose } }), isManaged = _useLayoutAreaSizing.isManaged, prepareResize = _useLayoutAreaSizing.prepareResize, managedSizing = _useLayoutAreaSizing.state, getManagedResizeBounds = _useLayoutAreaSizing.getResizeBounds, startResize = _useLayoutAreaSizing.startResize, resize = _useLayoutAreaSizing.resize, completeResize = _useLayoutAreaSizing.completeResize; useEffect(function () { var mediaQuery = window.matchMedia(inlineMediaQuery); setIsInline(mediaQuery.matches); var onChange = function onChange(event) { setIsInline(event.matches); }; return bind(mediaQuery, { type: 'change', listener: onChange }); }, []); var mode = (_managedSizing$mode = managedSizing === null || managedSizing === void 0 ? void 0 : managedSizing.mode) !== null && _managedSizing$mode !== void 0 ? _managedSizing$mode : isInline ? 'inline' : 'overlay'; var renderedWidth = (_managedSizing$width = managedSizing === null || managedSizing === void 0 ? void 0 : managedSizing.width) !== null && _managedSizing$width !== void 0 ? _managedSizing$width : mode === 'inline' ? inlineWidth : overlayWidth; useResizingWidthCssVarOnRootElement({ isEnabled: !managedSizing, cssVar: panelSplitterResizingVar, panelId: chatPanelPanelSplitterId }); var getResizeBounds = useCallback(function () { var managedBounds = getManagedResizeBounds(); if (managedBounds) { return managedBounds; } var chatPanel = ref.current; var layoutRoot = chatPanel === null || chatPanel === void 0 ? void 0 : chatPanel.parentElement; var main = layoutRoot === null || layoutRoot === void 0 ? void 0 : layoutRoot.querySelector(':scope > [data-layout-slot][role="main"]'); if (!chatPanel || !main || getComputedStyle(chatPanel).gridArea !== 'chat-panel') { return { min: minWidth, max: maxWidth !== null && maxWidth !== void 0 ? maxWidth : '90vw' }; } var chatPanelWidth = chatPanel.getBoundingClientRect().width; var mainWidth = main.getBoundingClientRect().width; if (chatPanelWidth === 0 || mainWidth === 0) { return { min: minWidth, max: maxWidth !== null && maxWidth !== void 0 ? maxWidth : '90vw' }; } var localPanel = main.querySelector('[data-layout-with-panel-slot]'); var isLocalPanelInline = localPanel && getComputedStyle(localPanel).gridArea === 'panel'; var localPanelWidth = isLocalPanelInline ? localPanel.getBoundingClientRect().width : 0; var mainMinimumWidth = getPixelCustomProperty(main, mainMinimumWidthVar, defaultMainMinWidth); var mainContentWidth = mainWidth - localPanelWidth; var availableWidth = Math.max(0, mainContentWidth - mainMinimumWidth); var availableInlineWidth = Math.floor(chatPanelWidth + availableWidth); var constrainedMaxWidth = maxWidth ? Math.min(convertResizeBoundToPixels(maxWidth), availableInlineWidth) : availableInlineWidth; return { min: minWidth, max: "".concat(Math.max(convertResizeBoundToPixels(minWidth), constrainedMaxWidth), "px") }; }, [getManagedResizeBounds, maxWidth, minWidth]); var configuredMaxWidth = maxWidth !== null && maxWidth !== void 0 ? maxWidth : '100vw'; var chatPanelVariableWidth = managedSizing ? "".concat(renderedWidth, "px") : "clamp(".concat(minWidth, ", ").concat(inlineWidth, "px, ").concat(configuredMaxWidth, ")"); var chatPanelOverlayVariableWidth = managedSizing ? "".concat(renderedWidth, "px") : "clamp(".concat(minWidth, ", ").concat(overlayWidth, "px, min(90vw, ").concat(configuredMaxWidth, "))"); var onCompleteResize = useCallback(function (finalWidth) { if (mode === 'inline') { setInlineWidth(finalWidth); } else { setOverlayWidth(finalWidth); } completeResize(mode, finalWidth); }, [completeResize, mode]); var onResizeStartInternal = useCallback(function () { startResize(mode); }, [mode, startResize]); var onResizeInternal = useCallback(function (width) { return resize(mode, width); }, [mode, resize]); return /*#__PURE__*/React.createElement("section", { id: id, "data-layout-slot": true, "aria-label": label, className: ax([styles.root, hasBorder && styles.border, (managedSizing === null || managedSizing === void 0 ? void 0 : managedSizing.mode) === 'inline' && styles.managedInline, (managedSizing === null || managedSizing === void 0 ? void 0 : managedSizing.mode) === 'overlay' && styles.managedOverlay, hasBorder && (managedSizing === null || managedSizing === void 0 ? void 0 : managedSizing.mode) === 'inline' && styles.managedInlineBorder, hasBorder && (managedSizing === null || managedSizing === void 0 ? void 0 : managedSizing.mode) === 'overlay' && styles.managedOverlayBorder, xcss]), style: _defineProperty(_defineProperty({}, chatPanelVar, chatPanelVariableWidth), chatPanelOverlayWidthVar, chatPanelOverlayVariableWidth), "data-testid": testId, "data-layout-chat-panel": "", ref: ref }, /*#__PURE__*/ // Hoist the committed or actively resizing inline width so SideNav can yield // space to ChatPanel without allowing the page layout to overflow. // eslint-disable-next-line @atlaskit/ui-styling-standard/no-global-styles React.createElement("style", null, managedSizing ? "\n#".concat(gridRootId, " { --n_chatTrack: ").concat(mode === 'inline' ? "".concat(renderedWidth, "px") : '0px', "; ").concat(chatPanelLiveWidthVar, ": var(--n_chatTrack); }\n") : "\n#".concat(gridRootId, " { --n_chatTrack: 0px; ").concat(chatPanelLiveWidthVar, ": 0px; }\n#").concat(gridRootId, " [data-layout-chat-panel] {\n grid-area: 2 / 1 / -1 / -1;\n width: min(calc(var(--n_layoutW) * 0.9), ").concat(chatPanelOverlayVariableWidth, ");\n z-index: ").concat(localSlotLayers.chatPanelOverlay, ";\n background-color: ", "var(--ds-surface-overlay, #FFFFFF)", ";\n ").concat(hasBorder ? "box-shadow: ".concat("var(--ds-shadow-overlay, 0px 8px 12px #1E1F2126, 0px 0px 1px #1E1F214f)", "; border-inline-start: none;") : '', "\n}\n@media (min-width: 40rem) {\n @container navigation-chat-space (min-width: ").concat(minWidth, ") {\n #").concat(gridRootId, " { --n_chatTrack: min(100cqw, var(").concat(panelSplitterResizingVar, ", ").concat(chatPanelVariableWidth, ")); ").concat(chatPanelLiveWidthVar, ": var(--n_chatTrack); }\n #").concat(gridRootId, " [data-layout-chat-panel] {\n grid-area: chat-panel;\n width: min(100cqw, var(").concat(panelSplitterResizingVar, ", ").concat(chatPanelVariableWidth, "));\n z-index: auto;\n background-color: ", "var(--ds-surface, #FFFFFF)", ";\n ").concat(hasBorder ? "box-shadow: initial; border-inline-start: ".concat("var(--ds-border-width, 1px)", " solid ", "var(--ds-border, #0B120E24)", ";") : '', "\n }\n }\n}\n")), /*#__PURE__*/React.createElement(PanelSplitterProvider, { panelId: chatPanelPanelSplitterId, panelRef: ref, panelWidth: renderedWidth, onCompleteResize: onCompleteResize, prepareResize: prepareResize, onResizeStartInternal: isManaged ? onResizeStartInternal : undefined, onResizeInternal: isManaged ? onResizeInternal : undefined, getResizeBounds: getResizeBounds, resizingCssVar: panelSplitterResizingVar, position: "start" }, /*#__PURE__*/React.createElement("div", { className: ax([styles.scrollContainer]) }, children))); }