UNPKG

@awsui/components-react

Version:

On July 19th, 2022, we launched [Cloudscape Design System](https://cloudscape.design). Cloudscape is an evolution of AWS-UI. It consists of user interface guidelines, front-end components, design resources, and development tools for building intuitive, en

228 lines • 13.7 kB
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 import { useEffect, useRef, useState } from 'react'; import { useStableCallback } from '@awsui/component-toolkit/internal'; import { fireNonCancelableEvent } from '../../internal/events'; import { useControllable } from '../../internal/hooks/use-controllable'; import { awsuiPluginsInternal } from '../../internal/plugins/api'; import { sortByPriority } from '../../internal/plugins/helpers/utils'; import { convertRuntimeDrawers } from '../runtime-drawer'; import { togglesConfig } from '../toggles'; export const TOOLS_DRAWER_ID = 'awsui-internal-tools'; function getToolsDrawerItem(props) { if (props.toolsHide) { return null; } const { iconName, getLabels } = togglesConfig.tools; const { mainLabel, closeLabel, openLabel } = getLabels(props.ariaLabels); return { id: TOOLS_DRAWER_ID, content: props.tools, resizable: false, ariaLabels: { triggerButton: openLabel, closeButton: closeLabel, drawerName: mainLabel !== null && mainLabel !== void 0 ? mainLabel : '', }, trigger: { iconName: iconName, }, }; } const DRAWERS_LIMIT = 2; const DEFAULT_ON_CHANGE_PARAMS = { initiatedByUserAction: true }; function useRuntimeDrawers(disableRuntimeDrawers, activeDrawerId, onActiveDrawerChange, activeGlobalDrawersIds, onActiveGlobalDrawersChange) { const [runtimeDrawers, setRuntimeDrawers] = useState({ localBefore: [], localAfter: [], global: [], }); const onLocalDrawerChangeStable = useStableCallback(onActiveDrawerChange); const onGlobalDrawersChangeStable = useStableCallback(onActiveGlobalDrawersChange); const localDrawerWasOpenRef = useRef(false); localDrawerWasOpenRef.current = localDrawerWasOpenRef.current || !!activeDrawerId; const activeGlobalDrawersIdsRef = useRef([]); activeGlobalDrawersIdsRef.current = activeGlobalDrawersIds; useEffect(() => { if (disableRuntimeDrawers) { return; } const unsubscribe = awsuiPluginsInternal.appLayout.onDrawersRegistered(drawers => { const localDrawers = drawers.filter(drawer => drawer.type !== 'global'); const globalDrawers = drawers.filter(drawer => drawer.type === 'global'); setRuntimeDrawers(convertRuntimeDrawers(localDrawers, globalDrawers)); if (!localDrawerWasOpenRef.current) { const defaultActiveLocalDrawer = sortByPriority(localDrawers).find(drawer => drawer.defaultActive); if (defaultActiveLocalDrawer) { onLocalDrawerChangeStable(defaultActiveLocalDrawer.id, { initiatedByUserAction: false }); } } const drawersNotActiveByDefault = globalDrawers.filter(drawer => !drawer.defaultActive); const hasDrawersOpenByUserAction = drawersNotActiveByDefault.find(drawer => activeGlobalDrawersIdsRef.current.includes(drawer.id)); if (hasDrawersOpenByUserAction || activeGlobalDrawersIdsRef.current.length === DRAWERS_LIMIT) { return; } const defaultActiveGlobalDrawers = sortByPriority(globalDrawers).filter(drawer => !activeGlobalDrawersIdsRef.current.includes(drawer.id) && drawer.defaultActive); defaultActiveGlobalDrawers.forEach(drawer => { onGlobalDrawersChangeStable(drawer.id, { initiatedByUserAction: false }); }); }); return () => { unsubscribe(); setRuntimeDrawers({ localBefore: [], localAfter: [], global: [] }); }; }, [disableRuntimeDrawers, onGlobalDrawersChangeStable, onLocalDrawerChangeStable]); return runtimeDrawers; } function useDrawerRuntimeOpenClose(disableRuntimeDrawers, localDrawers, globalDrawers, activeDrawerId, onActiveDrawerChange, activeGlobalDrawersIds, onActiveGlobalDrawersChange) { const onDrawerOpened = useStableCallback((drawerId, params = DEFAULT_ON_CHANGE_PARAMS) => { const localDrawer = localDrawers === null || localDrawers === void 0 ? void 0 : localDrawers.find(drawer => drawer.id === drawerId); const globalDrawer = globalDrawers.find(drawer => drawer.id === drawerId); if (localDrawer && activeDrawerId !== drawerId) { onActiveDrawerChange(drawerId, params); } if (globalDrawer && !activeGlobalDrawersIds.includes(drawerId)) { onActiveGlobalDrawersChange(drawerId, params); } }); const onDrawerClosed = useStableCallback((drawerId, params = DEFAULT_ON_CHANGE_PARAMS) => { const localDrawer = localDrawers === null || localDrawers === void 0 ? void 0 : localDrawers.find(drawer => drawer.id === drawerId); const globalDrawer = globalDrawers.find(drawer => drawer.id === drawerId); if (localDrawer && activeDrawerId === drawerId) { onActiveDrawerChange(null, params); } if (globalDrawer && activeGlobalDrawersIds.includes(drawerId)) { onActiveGlobalDrawersChange(drawerId, params); } }); useEffect(() => { if (disableRuntimeDrawers) { return; } return awsuiPluginsInternal.appLayout.onDrawerOpened(onDrawerOpened); }, [disableRuntimeDrawers, onDrawerOpened]); useEffect(() => { if (disableRuntimeDrawers) { return; } return awsuiPluginsInternal.appLayout.onDrawerClosed(onDrawerClosed); }, [disableRuntimeDrawers, onDrawerClosed]); } function applyToolsDrawer(toolsProps, runtimeDrawers) { const drawers = [...runtimeDrawers.localBefore, ...runtimeDrawers.localAfter]; if (drawers.length === 0 && toolsProps.disableDrawersMerge) { return null; } const toolsItem = getToolsDrawerItem(toolsProps); if (toolsItem) { drawers.unshift(toolsItem); } return drawers; } export const MIN_DRAWER_SIZE = 290; export function useDrawers({ drawers, activeDrawerId: controlledActiveDrawerId, onDrawerChange, onGlobalDrawerFocus, onAddNewActiveDrawer, __disableRuntimeDrawers: disableRuntimeDrawers, }, ariaLabels, toolsProps) { var _a, _b, _c, _d; const [activeDrawerId = null, setActiveDrawerId] = useControllable(controlledActiveDrawerId, onDrawerChange, null, { componentName: 'AppLayout', controlledProp: 'activeDrawerId', changeHandler: 'onChange', }); const [activeGlobalDrawersIds, setActiveGlobalDrawersIds] = useState([]); const [drawerSizes, setDrawerSizes] = useState({}); // FIFO queue that keeps track of open drawers, where the first element is the most recently opened drawer const drawersOpenQueue = useRef([]); function onActiveDrawerResize({ id, size }) { setDrawerSizes(oldSizes => (Object.assign(Object.assign({}, oldSizes), { [id]: size }))); fireNonCancelableEvent(activeDrawer === null || activeDrawer === void 0 ? void 0 : activeDrawer.onResize, { id, size }); const activeGlobalDrawer = runtimeGlobalDrawers.find(drawer => drawer.id === id); fireNonCancelableEvent(activeGlobalDrawer === null || activeGlobalDrawer === void 0 ? void 0 : activeGlobalDrawer.onResize, { id, size }); } function onActiveDrawerChange(newDrawerId, { initiatedByUserAction } = DEFAULT_ON_CHANGE_PARAMS) { var _a, _b; setActiveDrawerId(newDrawerId); if (newDrawerId) { onAddNewActiveDrawer === null || onAddNewActiveDrawer === void 0 ? void 0 : onAddNewActiveDrawer(newDrawerId); } if (hasOwnDrawers) { fireNonCancelableEvent(onDrawerChange, { activeDrawerId: newDrawerId }); } else if (!toolsProps.toolsHide) { toolsProps.onToolsToggle(newDrawerId === TOOLS_DRAWER_ID); } if (newDrawerId) { drawersOpenQueue.current = [newDrawerId, ...drawersOpenQueue.current]; const newDrawer = (_a = [...runtimeDrawers.localBefore, ...runtimeDrawers.localAfter]) === null || _a === void 0 ? void 0 : _a.find(drawer => drawer.id === newDrawerId); fireNonCancelableEvent(newDrawer === null || newDrawer === void 0 ? void 0 : newDrawer.onToggle, { isOpen: true, initiatedByUserAction }); } if (activeDrawerId) { drawersOpenQueue.current = drawersOpenQueue.current.filter(id => id !== activeDrawerId); const activeDrawer = (_b = [...runtimeDrawers.localBefore, ...runtimeDrawers.localAfter]) === null || _b === void 0 ? void 0 : _b.find(drawer => drawer.id === activeDrawerId); fireNonCancelableEvent(activeDrawer === null || activeDrawer === void 0 ? void 0 : activeDrawer.onToggle, { isOpen: false, initiatedByUserAction }); } } function onActiveGlobalDrawersChange(drawerId, { initiatedByUserAction } = DEFAULT_ON_CHANGE_PARAMS) { const drawer = runtimeGlobalDrawers.find(drawer => drawer.id === drawerId); if (activeGlobalDrawersIds.includes(drawerId)) { setActiveGlobalDrawersIds(currentState => currentState.filter(id => id !== drawerId)); onGlobalDrawerFocus === null || onGlobalDrawerFocus === void 0 ? void 0 : onGlobalDrawerFocus(drawerId, false); drawersOpenQueue.current = drawersOpenQueue.current.filter(id => id !== drawerId); fireNonCancelableEvent(drawer === null || drawer === void 0 ? void 0 : drawer.onToggle, { isOpen: false, initiatedByUserAction }); } else if (drawerId) { onAddNewActiveDrawer === null || onAddNewActiveDrawer === void 0 ? void 0 : onAddNewActiveDrawer(drawerId); setActiveGlobalDrawersIds(currentState => [drawerId, ...currentState].slice(0, DRAWERS_LIMIT)); onGlobalDrawerFocus === null || onGlobalDrawerFocus === void 0 ? void 0 : onGlobalDrawerFocus(drawerId, true); drawersOpenQueue.current = [drawerId, ...drawersOpenQueue.current]; fireNonCancelableEvent(drawer === null || drawer === void 0 ? void 0 : drawer.onToggle, { isOpen: true, initiatedByUserAction }); } } const hasOwnDrawers = !!drawers; // support toolsOpen in runtime-drawers-only mode let activeDrawerIdResolved = (toolsProps === null || toolsProps === void 0 ? void 0 : toolsProps.toolsOpen) && !hasOwnDrawers ? TOOLS_DRAWER_ID : activeDrawerId !== TOOLS_DRAWER_ID ? activeDrawerId : null; const runtimeDrawers = useRuntimeDrawers(disableRuntimeDrawers, activeDrawerIdResolved, onActiveDrawerChange, activeGlobalDrawersIds, onActiveGlobalDrawersChange); const { localBefore, localAfter, global: runtimeGlobalDrawers } = runtimeDrawers; const combinedLocalDrawers = drawers ? [...localBefore, ...drawers, ...localAfter] : applyToolsDrawer(toolsProps, runtimeDrawers); const activeDrawer = combinedLocalDrawers === null || combinedLocalDrawers === void 0 ? void 0 : combinedLocalDrawers.find(drawer => drawer.id === activeDrawerIdResolved); // ensure that id is only defined when the drawer exists activeDrawerIdResolved = (_a = activeDrawer === null || activeDrawer === void 0 ? void 0 : activeDrawer.id) !== null && _a !== void 0 ? _a : null; const activeGlobalDrawers = runtimeGlobalDrawers.filter(drawer => activeGlobalDrawersIds.includes(drawer.id)); useDrawerRuntimeOpenClose(disableRuntimeDrawers, combinedLocalDrawers, runtimeGlobalDrawers, activeDrawerId, onActiveDrawerChange, activeGlobalDrawersIds, onActiveGlobalDrawersChange); const activeDrawerSize = activeDrawerIdResolved ? (_c = (_b = drawerSizes[activeDrawerIdResolved]) !== null && _b !== void 0 ? _b : activeDrawer === null || activeDrawer === void 0 ? void 0 : activeDrawer.defaultSize) !== null && _c !== void 0 ? _c : toolsProps.toolsWidth : toolsProps.toolsWidth; const activeGlobalDrawersSizes = activeGlobalDrawersIds.reduce((acc, currentGlobalDrawerId) => { var _a, _b; const currentGlobalDrawer = runtimeGlobalDrawers.find(drawer => drawer.id === currentGlobalDrawerId); return Object.assign(Object.assign({}, acc), { [currentGlobalDrawerId]: (_b = (_a = drawerSizes[currentGlobalDrawerId]) !== null && _a !== void 0 ? _a : currentGlobalDrawer === null || currentGlobalDrawer === void 0 ? void 0 : currentGlobalDrawer.defaultSize) !== null && _b !== void 0 ? _b : MIN_DRAWER_SIZE }); }, {}); const minGlobalDrawersSizes = runtimeGlobalDrawers.reduce((acc, globalDrawer) => { var _a; return Object.assign(Object.assign({}, acc), { [globalDrawer.id]: Math.min((_a = globalDrawer.defaultSize) !== null && _a !== void 0 ? _a : MIN_DRAWER_SIZE, MIN_DRAWER_SIZE) }); }, {}); const minDrawerSize = Math.min((toolsProps === null || toolsProps === void 0 ? void 0 : toolsProps.toolsOpen) ? toolsProps.toolsWidth : (_d = activeDrawer === null || activeDrawer === void 0 ? void 0 : activeDrawer.defaultSize) !== null && _d !== void 0 ? _d : MIN_DRAWER_SIZE, MIN_DRAWER_SIZE); return { ariaLabelsWithDrawers: ariaLabels, drawers: combinedLocalDrawers || undefined, activeDrawer, activeDrawerId: activeDrawerIdResolved, globalDrawers: runtimeGlobalDrawers, activeGlobalDrawers: activeGlobalDrawers, activeGlobalDrawersIds, activeGlobalDrawersSizes, activeDrawerSize, minDrawerSize, minGlobalDrawersSizes, drawerSizes, drawersOpenQueue: drawersOpenQueue.current, onActiveDrawerChange, onActiveDrawerResize, onActiveGlobalDrawersChange, }; } //# sourceMappingURL=use-drawers.js.map