@vuu-ui/vuu-popups 0.8.81 → 0.8.83

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"ContextMenu.js","sources":["../../src/menu/ContextMenu.tsx"],"sourcesContent":["import { useId } from \"@vuu-ui/vuu-utils\";\nimport { useCallback, useRef } from \"react\";\nimport { PopupCloseCallback, PopupComponent } from \"../popup\";\nimport { Portal, PortalProps } from \"../portal\";\nimport { MenuList, MenuListProps } from \"./MenuList\";\nimport { useCascade } from \"./use-cascade\";\nimport { useItemsWithIdsNext } from \"./use-items-with-ids-next\";\nimport { MenuCloseHandler } from \"./use-keyboard-navigation\";\nimport { ContextMenuOptions } from \"./useContextMenu\";\n\nexport interface ContextMenuProps extends Omit<MenuListProps, \"onCloseMenu\"> {\n PortalProps?: Partial<PortalProps>;\n onClose?: PopupCloseCallback;\n position?: { x: number; y: number };\n withPortal?: boolean;\n}\n\nconst noop = () => undefined;\n\nexport const ContextMenu = ({\n PortalProps,\n activatedByKeyboard,\n children: childrenProp,\n className,\n id: idProp,\n onClose = () => undefined,\n position = { x: 0, y: 0 },\n style,\n ...menuListProps\n}: ContextMenuProps) => {\n const id = useId(idProp);\n const closeMenuRef = useRef<(location?: string) => void>(noop);\n const [menus, actions] = useItemsWithIdsNext(childrenProp, id);\n const navigatingWithKeyboard = useRef(activatedByKeyboard);\n const handleMouseEnterItem = useCallback(() => {\n navigatingWithKeyboard.current = false;\n }, []);\n\n const handleActivate = useCallback(\n (menuItemId: string) => {\n const actionId = menuItemId.slice(9);\n const { action, options } = actions[actionId];\n closeMenuRef.current(id);\n onClose({\n type: \"menu-action\",\n menuId: action,\n options: options as ContextMenuOptions,\n });\n },\n [actions, id, onClose]\n );\n\n const {\n closeMenu,\n listItemProps,\n openMenu: onOpenMenu,\n openMenus,\n handleRender,\n } = useCascade({\n // FIXME\n id: `${id}`,\n onActivate: handleActivate,\n onMouseEnterItem: handleMouseEnterItem,\n position,\n });\n closeMenuRef.current = closeMenu;\n\n const handleCloseMenu = useCallback<MenuCloseHandler>(\n (evt, reason) => {\n navigatingWithKeyboard.current = true;\n closeMenu();\n if (reason === \"tab-away\") {\n // TODO we should fire onclose whenever we're closing\n // the root menu, not just on Tab\n onClose({\n event: evt,\n type: \"tab-away\",\n });\n }\n },\n [closeMenu, onClose]\n );\n\n const handleHighlightMenuItem = () => {\n // console.log(`highlight ${idx}`);\n };\n\n const lastMenu = openMenus.length - 1;\n\n const getChildMenuId = (i: number) => {\n if (i >= lastMenu) {\n return undefined;\n } else {\n const { id } = openMenus[i + 1];\n return id;\n }\n };\n\n return (\n <>\n {openMenus.map(({ id: menuId, left, top }, i, all) => {\n const childMenuId = getChildMenuId(i);\n return (\n <Portal {...PortalProps} key={i} onRender={handleRender}>\n <PopupComponent\n anchorElement={{ current: document.body }}\n placement=\"absolute\"\n position={{ left, top }}\n >\n <MenuList\n {...menuListProps}\n activatedByKeyboard={navigatingWithKeyboard.current}\n childMenuShowing={childMenuId}\n className={className}\n id={menuId}\n isRoot={i === 0}\n key={i}\n listItemProps={listItemProps}\n onActivate={handleActivate}\n onHighlightMenuItem={handleHighlightMenuItem}\n onCloseMenu={handleCloseMenu}\n openMenu={onOpenMenu}\n style={style}\n tabIndex={i === all.length - 1 ? 0 : undefined}\n >\n {menus[menuId]}\n </MenuList>\n </PopupComponent>\n </Portal>\n );\n })}\n </>\n );\n};\n\nContextMenu.displayName = \"ContextMenu\";\n"],"names":["PortalProps","useId","useRef","useItemsWithIdsNext","useCallback","useCascade","id","jsx","Fragment","Portal","PopupComponent","createElement","MenuList"],"mappings":"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"}
1
+ {"version":3,"file":"ContextMenu.js","sources":["../../src/menu/ContextMenu.tsx"],"sourcesContent":["import { useId } from \"@vuu-ui/vuu-utils\";\nimport { useCallback, useRef } from \"react\";\nimport { PopupCloseCallback, PopupComponent } from \"../popup\";\nimport { Portal, PortalProps } from \"../portal\";\nimport { MenuList, MenuListProps } from \"./MenuList\";\nimport { useCascade } from \"./use-cascade\";\nimport { useItemsWithIdsNext } from \"./use-items-with-ids-next\";\nimport { MenuCloseHandler } from \"./use-keyboard-navigation\";\nimport { ContextMenuOptions } from \"./useContextMenu\";\n\nexport interface ContextMenuProps extends Omit<MenuListProps, \"onCloseMenu\"> {\n PortalProps?: Partial<PortalProps>;\n onClose?: PopupCloseCallback;\n position?: { x: number; y: number };\n withPortal?: boolean;\n}\n\nconst noop = () => undefined;\n\nexport const ContextMenu = ({\n PortalProps,\n activatedByKeyboard,\n children: childrenProp,\n className,\n id: idProp,\n onClose = () => undefined,\n position = { x: 0, y: 0 },\n style,\n ...menuListProps\n}: ContextMenuProps) => {\n const id = useId(idProp);\n const closeMenuRef = useRef<(location?: string) => void>(noop);\n const [menus, actions] = useItemsWithIdsNext(childrenProp, id);\n const navigatingWithKeyboard = useRef(activatedByKeyboard);\n const handleMouseEnterItem = useCallback(() => {\n navigatingWithKeyboard.current = false;\n }, []);\n\n const handleActivate = useCallback(\n (menuItemId: string) => {\n const actionId = menuItemId.slice(9);\n const { action, options } = actions[actionId];\n closeMenuRef.current(id);\n onClose({\n type: \"menu-action\",\n menuId: action,\n options: options as ContextMenuOptions,\n });\n },\n [actions, id, onClose],\n );\n\n const {\n closeMenu,\n listItemProps,\n openMenu: onOpenMenu,\n openMenus,\n handleRender,\n } = useCascade({\n // FIXME\n id: `${id}`,\n onActivate: handleActivate,\n onMouseEnterItem: handleMouseEnterItem,\n position,\n });\n closeMenuRef.current = closeMenu;\n\n const handleCloseMenu = useCallback<MenuCloseHandler>(\n (evt, reason) => {\n navigatingWithKeyboard.current = true;\n closeMenu();\n if (reason === \"tab-away\") {\n // TODO we should fire onclose whenever we're closing\n // the root menu, not just on Tab\n onClose({\n event: evt,\n type: \"tab-away\",\n });\n }\n },\n [closeMenu, onClose],\n );\n\n const handleHighlightMenuItem = () => {\n // console.log(`highlight ${idx}`);\n };\n\n const lastMenu = openMenus.length - 1;\n\n const getChildMenuId = (i: number) => {\n if (i >= lastMenu) {\n return undefined;\n } else {\n const { id } = openMenus[i + 1];\n return id;\n }\n };\n\n return (\n <>\n {openMenus.map(({ id: menuId, left, top }, i, all) => {\n const childMenuId = getChildMenuId(i);\n return (\n <Portal {...PortalProps} key={i} onRender={handleRender}>\n <PopupComponent\n anchorElement={{ current: document.body }}\n placement=\"absolute\"\n position={{ left, top }}\n >\n <MenuList\n {...menuListProps}\n activatedByKeyboard={navigatingWithKeyboard.current}\n childMenuShowing={childMenuId}\n className={className}\n id={menuId}\n isRoot={i === 0}\n key={i}\n listItemProps={listItemProps}\n onActivate={handleActivate}\n onHighlightMenuItem={handleHighlightMenuItem}\n onCloseMenu={handleCloseMenu}\n openMenu={onOpenMenu}\n style={style}\n tabIndex={i === all.length - 1 ? 0 : undefined}\n >\n {menus[menuId]}\n </MenuList>\n </PopupComponent>\n </Portal>\n );\n })}\n </>\n );\n};\n\nContextMenu.displayName = \"ContextMenu\";\n"],"names":["PortalProps","useId","useRef","useItemsWithIdsNext","useCallback","useCascade","id","jsx","Fragment","Portal","PopupComponent","createElement","MenuList"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"MenuList.js","sources":["../../src/menu/MenuList.tsx"],"sourcesContent":["import cx from \"clsx\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport React, {\n FC,\n HTMLAttributes,\n ReactElement,\n ReactNode,\n useLayoutEffect,\n useMemo,\n useRef,\n} from \"react\";\n//TODO do we want this dependency ?\nimport { useId } from \"@vuu-ui/vuu-utils\";\nimport {\n MenuCloseHandler,\n useKeyboardNavigation,\n} from \"./use-keyboard-navigation\";\n\nimport menuListCss from \"./MenuList.css\";\n\nconst classBase = \"vuuMenuList\";\n\nexport const Separator = () => <li className=\"vuuMenuItem-divider\" />;\n\nexport const isMenuItemGroup = (child: ReactElement) =>\n child.type === MenuItemGroup || !!child.props[\"data-group\"];\n\nexport interface MenuItemGroupProps {\n children:\n | ReactElement<MenuItemProps>[]\n | [ReactElement<MenuItemLabelProps>, ...ReactElement<MenuItemProps>[]];\n label?: string;\n}\n\nexport interface MenuItemProps extends HTMLAttributes<HTMLDivElement> {\n action?: string;\n idx?: number;\n options?: unknown;\n}\n\n// Purely used as markers, props will be extracted\nexport const MenuItemGroup: FC<MenuItemGroupProps> = () => null;\n// eslint-disable-next-line no-unused-vars\nexport const MenuItem = ({\n children,\n idx,\n options,\n ...props\n}: MenuItemProps) => {\n return <div {...props}>{children}</div>;\n};\n\nexport interface MenuItemLabelProps {\n children: ReactNode;\n}\nconst MenuItemLabel = ({ children }: { children: ReactNode }) => (\n <>{children}</>\n);\nMenuItemLabel.displayName = \"MenuItemLabel\";\nMenuItem.Label = MenuItemLabel;\n\nconst getDisplayName = (item: ReactNode) =>\n React.isValidElement(item) &&\n typeof item.type !== \"string\" &&\n \"displayName\" in item.type\n ? item.type.displayName\n : undefined;\n\nexport const isMenuItemLabel = (\n item: ReactNode\n): item is ReactElement<MenuItemLabelProps> =>\n getDisplayName(item) === \"MenuItemLabel\";\n\nconst hasIcon = (child: ReactElement) => child.props[\"data-icon\"];\n\nexport type MenuOpenHandler = (\n menuItemEl: HTMLElement,\n immediate?: boolean\n) => void;\nexport interface MenuListProps extends HTMLAttributes<HTMLDivElement> {\n activatedByKeyboard?: boolean;\n children: ReactElement[];\n childMenuShowing?: string;\n defaultHighlightedIdx?: number;\n highlightedIdx?: number;\n isRoot?: boolean;\n listItemProps?: Partial<MenuItemProps>;\n onActivate?: (menuId: string) => void;\n onCloseMenu: MenuCloseHandler;\n openMenu?: MenuOpenHandler;\n onHighlightMenuItem?: (idx: number) => void;\n}\n\nexport const MenuList = ({\n activatedByKeyboard,\n childMenuShowing,\n children,\n className,\n defaultHighlightedIdx,\n highlightedIdx: highlightedIdxProp,\n id: idProp,\n isRoot,\n listItemProps,\n onHighlightMenuItem,\n onActivate,\n onCloseMenu,\n openMenu: onOpenMenu,\n ...props\n}: MenuListProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-menu-list\",\n css: menuListCss,\n window: targetWindow,\n });\n\n const id = useId(idProp);\n const root = useRef<HTMLDivElement>(null);\n\n // The id generation be,ongs in useIttemsWithIds\n const mapIdxToId = useMemo(() => new Map(), []);\n\n const handleActivate = (idx: number) => {\n const el = root.current?.querySelector(`:scope > [data-index='${idx}']`);\n el?.id && onActivate?.(el.id);\n };\n\n const { focusVisible, highlightedIndex, listProps } = useKeyboardNavigation({\n count: React.Children.count(children),\n defaultHighlightedIdx,\n highlightedIndex: highlightedIdxProp,\n onActivate: handleActivate,\n onHighlight: onHighlightMenuItem,\n onOpenMenu,\n onCloseMenu,\n });\n\n const appliedFocusVisible = childMenuShowing == undefined ? focusVisible : -1;\n\n useLayoutEffect(() => {\n if (childMenuShowing === undefined && activatedByKeyboard) {\n root.current?.focus();\n }\n }, [activatedByKeyboard, childMenuShowing]);\n\n const getActiveDescendant = () =>\n highlightedIndex === undefined || highlightedIndex === -1\n ? undefined\n : mapIdxToId.get(highlightedIndex);\n\n function renderContent() {\n const propsCommonToAllListItems = {\n ...listItemProps,\n role: \"menuitem\",\n };\n\n const maybeIcon = (\n childElement: ReactElement,\n withIcon: boolean,\n iconName?: string\n ) =>\n withIcon\n ? [\n <span\n className=\"vuuIconContainer\"\n data-icon={iconName}\n key=\"icon\"\n />,\n ].concat(childElement)\n : childElement;\n\n function addClonedChild(\n list: ReactElement[],\n child: ReactElement,\n idx: number,\n withIcon: boolean\n ) {\n const {\n children,\n className,\n \"data-icon\": iconName,\n id: itemId,\n hasSeparator,\n label,\n ...props\n } = child.props;\n const hasSubMenu = isMenuItemGroup(child);\n const subMenuShowing = hasSubMenu && childMenuShowing === itemId;\n const ariaControls = subMenuShowing ? `${id}-${itemId}` : undefined;\n\n const ariaLabel =\n label ?? typeof children === \"string\" ? children : undefined;\n\n list.push(\n <MenuItem\n {...props}\n {...propsCommonToAllListItems}\n {...getMenuItemProps(\n itemId,\n idx,\n child.key ?? itemId,\n highlightedIndex,\n appliedFocusVisible,\n className,\n hasSeparator\n )}\n aria-controls={ariaControls}\n aria-haspopup={hasSubMenu || undefined}\n aria-expanded={subMenuShowing || undefined}\n aria-label={ariaLabel}\n >\n {hasSubMenu\n ? maybeIcon(label ?? children, withIcon, iconName)\n : maybeIcon(children, withIcon, iconName)}\n </MenuItem>\n );\n // mapIdxToId.set(idx, itemId);\n }\n\n const listItems: ReactElement[] = [];\n\n if (children.length > 0) {\n const withIcon = children.some(hasIcon);\n children.forEach((child, idx) => {\n addClonedChild(listItems, child, idx, withIcon);\n });\n }\n\n return listItems;\n }\n\n return (\n <div\n {...props}\n {...listProps}\n aria-activedescendant={getActiveDescendant()}\n className={cx(classBase, className, {\n [`${classBase}-childMenuShowing`]: childMenuShowing !== undefined,\n })}\n data-root={isRoot || undefined}\n id={id}\n ref={root}\n role=\"menu\"\n >\n {renderContent()}\n </div>\n );\n};\n\nconst getMenuItemProps = (\n itemId: string,\n idx: number,\n key: string,\n highlightedIdx: number,\n focusVisible: number,\n className: string,\n hasSeparator: boolean\n) => ({\n id: `menuitem-${itemId}`,\n key: key ?? idx,\n \"data-index\": idx,\n className: cx(\"vuuMenuItem\", className, {\n \"vuuMenuItem-separator\": hasSeparator,\n vuuHighlighted: idx === highlightedIdx,\n focusVisible: focusVisible === idx,\n }),\n});\n\nMenuList.displayName = \"MenuList\";\n"],"names":["jsx","useWindow","useComponentCssInjection","menuListCss","useId","useRef","useMemo","useKeyboardNavigation","useLayoutEffect","children","className","props"],"mappings":"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"}
1
+ {"version":3,"file":"MenuList.js","sources":["../../src/menu/MenuList.tsx"],"sourcesContent":["import cx from \"clsx\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport React, {\n FC,\n HTMLAttributes,\n ReactElement,\n ReactNode,\n useLayoutEffect,\n useMemo,\n useRef,\n} from \"react\";\n//TODO do we want this dependency ?\nimport { useId } from \"@vuu-ui/vuu-utils\";\nimport {\n MenuCloseHandler,\n useKeyboardNavigation,\n} from \"./use-keyboard-navigation\";\n\nimport menuListCss from \"./MenuList.css\";\n\nconst classBase = \"vuuMenuList\";\n\nexport const Separator = () => <li className=\"vuuMenuItem-divider\" />;\n\nexport const isMenuItemGroup = (child: ReactElement) =>\n child.type === MenuItemGroup || !!child.props[\"data-group\"];\n\nexport interface MenuItemGroupProps {\n children:\n | ReactElement<MenuItemProps>[]\n | [ReactElement<MenuItemLabelProps>, ...ReactElement<MenuItemProps>[]];\n label?: string;\n}\n\nexport interface MenuItemProps extends HTMLAttributes<HTMLDivElement> {\n action?: string;\n idx?: number;\n options?: unknown;\n}\n\n// Purely used as markers, props will be extracted\nexport const MenuItemGroup: FC<MenuItemGroupProps> = () => null;\n// eslint-disable-next-line no-unused-vars\nexport const MenuItem = ({\n children,\n idx,\n options,\n ...props\n}: MenuItemProps) => {\n return <div {...props}>{children}</div>;\n};\n\nexport interface MenuItemLabelProps {\n children: ReactNode;\n}\nconst MenuItemLabel = ({ children }: { children: ReactNode }) => (\n <>{children}</>\n);\nMenuItemLabel.displayName = \"MenuItemLabel\";\nMenuItem.Label = MenuItemLabel;\n\nconst getDisplayName = (item: ReactNode) =>\n React.isValidElement(item) &&\n typeof item.type !== \"string\" &&\n \"displayName\" in item.type\n ? item.type.displayName\n : undefined;\n\nexport const isMenuItemLabel = (\n item: ReactNode,\n): item is ReactElement<MenuItemLabelProps> =>\n getDisplayName(item) === \"MenuItemLabel\";\n\nconst hasIcon = (child: ReactElement) => child.props[\"data-icon\"];\n\nexport type MenuOpenHandler = (\n menuItemEl: HTMLElement,\n immediate?: boolean,\n) => void;\nexport interface MenuListProps extends HTMLAttributes<HTMLDivElement> {\n activatedByKeyboard?: boolean;\n children: ReactElement[];\n childMenuShowing?: string;\n defaultHighlightedIdx?: number;\n highlightedIdx?: number;\n isRoot?: boolean;\n listItemProps?: Partial<MenuItemProps>;\n onActivate?: (menuId: string) => void;\n onCloseMenu: MenuCloseHandler;\n openMenu?: MenuOpenHandler;\n onHighlightMenuItem?: (idx: number) => void;\n}\n\nexport const MenuList = ({\n activatedByKeyboard,\n childMenuShowing,\n children,\n className,\n defaultHighlightedIdx,\n highlightedIdx: highlightedIdxProp,\n id: idProp,\n isRoot,\n listItemProps,\n onHighlightMenuItem,\n onActivate,\n onCloseMenu,\n openMenu: onOpenMenu,\n ...props\n}: MenuListProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-menu-list\",\n css: menuListCss,\n window: targetWindow,\n });\n\n const id = useId(idProp);\n const root = useRef<HTMLDivElement>(null);\n\n // The id generation be,ongs in useIttemsWithIds\n const mapIdxToId = useMemo(() => new Map(), []);\n\n const handleActivate = (idx: number) => {\n const el = root.current?.querySelector(`:scope > [data-index='${idx}']`);\n el?.id && onActivate?.(el.id);\n };\n\n const { focusVisible, highlightedIndex, listProps } = useKeyboardNavigation({\n count: React.Children.count(children),\n defaultHighlightedIdx,\n highlightedIndex: highlightedIdxProp,\n onActivate: handleActivate,\n onHighlight: onHighlightMenuItem,\n onOpenMenu,\n onCloseMenu,\n });\n\n const appliedFocusVisible = childMenuShowing == undefined ? focusVisible : -1;\n\n useLayoutEffect(() => {\n if (childMenuShowing === undefined && activatedByKeyboard) {\n root.current?.focus();\n }\n }, [activatedByKeyboard, childMenuShowing]);\n\n const getActiveDescendant = () =>\n highlightedIndex === undefined || highlightedIndex === -1\n ? undefined\n : mapIdxToId.get(highlightedIndex);\n\n function renderContent() {\n const propsCommonToAllListItems = {\n ...listItemProps,\n role: \"menuitem\",\n };\n\n const maybeIcon = (\n childElement: ReactElement,\n withIcon: boolean,\n iconName?: string,\n ) =>\n withIcon\n ? [\n <span\n className=\"vuuIconContainer\"\n data-icon={iconName}\n key=\"icon\"\n />,\n ].concat(childElement)\n : childElement;\n\n function addClonedChild(\n list: ReactElement[],\n child: ReactElement,\n idx: number,\n withIcon: boolean,\n ) {\n const {\n children,\n className,\n \"data-icon\": iconName,\n id: itemId,\n hasSeparator,\n label,\n ...props\n } = child.props;\n const hasSubMenu = isMenuItemGroup(child);\n const subMenuShowing = hasSubMenu && childMenuShowing === itemId;\n const ariaControls = subMenuShowing ? `${id}-${itemId}` : undefined;\n\n const ariaLabel =\n (label ?? typeof children === \"string\") ? children : undefined;\n\n list.push(\n <MenuItem\n {...props}\n {...propsCommonToAllListItems}\n {...getMenuItemProps(\n itemId,\n idx,\n child.key ?? itemId,\n highlightedIndex,\n appliedFocusVisible,\n className,\n hasSeparator,\n )}\n aria-controls={ariaControls}\n aria-haspopup={hasSubMenu || undefined}\n aria-expanded={subMenuShowing || undefined}\n aria-label={ariaLabel}\n >\n {hasSubMenu\n ? maybeIcon(label ?? children, withIcon, iconName)\n : maybeIcon(children, withIcon, iconName)}\n </MenuItem>,\n );\n // mapIdxToId.set(idx, itemId);\n }\n\n const listItems: ReactElement[] = [];\n\n if (children.length > 0) {\n const withIcon = children.some(hasIcon);\n children.forEach((child, idx) => {\n addClonedChild(listItems, child, idx, withIcon);\n });\n }\n\n return listItems;\n }\n\n return (\n <div\n {...props}\n {...listProps}\n aria-activedescendant={getActiveDescendant()}\n className={cx(classBase, className, {\n [`${classBase}-childMenuShowing`]: childMenuShowing !== undefined,\n })}\n data-root={isRoot || undefined}\n id={id}\n ref={root}\n role=\"menu\"\n >\n {renderContent()}\n </div>\n );\n};\n\nconst getMenuItemProps = (\n itemId: string,\n idx: number,\n key: string,\n highlightedIdx: number,\n focusVisible: number,\n className: string,\n hasSeparator: boolean,\n) => ({\n id: `menuitem-${itemId}`,\n key: key ?? idx,\n \"data-index\": idx,\n className: cx(\"vuuMenuItem\", className, {\n \"vuuMenuItem-separator\": hasSeparator,\n vuuHighlighted: idx === highlightedIdx,\n focusVisible: focusVisible === idx,\n }),\n});\n\nMenuList.displayName = \"MenuList\";\n"],"names":["jsx","useWindow","useComponentCssInjection","menuListCss","useId","useRef","useMemo","useKeyboardNavigation","useLayoutEffect","children","className","props"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"context-menu-provider.js","sources":["../../src/menu/context-menu-provider.tsx"],"sourcesContent":["import type {\n ContextMenuContextType,\n MenuActionHandler,\n MenuBuilder,\n} from \"@vuu-ui/vuu-data-types\";\nimport { createContext, ReactNode, useCallback, useMemo } from \"react\";\n\nexport const ContextMenuContext = createContext<ContextMenuContextType | null>(\n null\n);\n\nexport interface ContextMenuConfiguration {\n menuActionHandler?: MenuActionHandler;\n menuBuilder: MenuBuilder;\n}\n\nexport interface ContextMenuProviderProps extends ContextMenuConfiguration {\n children: ReactNode;\n label?: string;\n}\n\ninterface ProviderProps extends ContextMenuProviderProps {\n context: ContextMenuContextType | null;\n}\n\nconst Provider = ({\n children,\n context,\n menuActionHandler,\n menuBuilder,\n}: ProviderProps) => {\n const menuBuilders = useMemo(() => {\n if (context?.menuBuilders && menuBuilder) {\n return context.menuBuilders.concat(menuBuilder);\n } else if (menuBuilder) {\n return [menuBuilder];\n } else {\n return context?.menuBuilders || [];\n }\n }, [context, menuBuilder]);\n\n const handleMenuAction = useCallback(\n (reason) => {\n if (menuActionHandler?.(reason)) {\n return true;\n }\n\n if (context?.menuActionHandler?.(reason)) {\n return true;\n }\n },\n [context, menuActionHandler]\n );\n\n return (\n <ContextMenuContext.Provider\n value={{\n menuActionHandler: handleMenuAction,\n menuBuilders,\n }}\n >\n {children}\n </ContextMenuContext.Provider>\n );\n};\n\n// Need an option for local menu to override higher-level menu, rather than extend\nexport const ContextMenuProvider = ({\n children,\n label,\n menuActionHandler,\n menuBuilder,\n}: ContextMenuProviderProps) => {\n return (\n <ContextMenuContext.Consumer>\n {(parentContext) => (\n <Provider\n context={parentContext}\n label={label}\n menuActionHandler={menuActionHandler}\n menuBuilder={menuBuilder}\n >\n {children}\n </Provider>\n )}\n </ContextMenuContext.Consumer>\n );\n};\n"],"names":["createContext","useMemo","useCallback","jsx"],"mappings":";;;;;AAOO,MAAM,kBAAqB,GAAAA,mBAAA;AAAA,EAChC,IAAA;AACF,EAAA;AAgBA,MAAM,WAAW,CAAC;AAAA,EAChB,QAAA;AAAA,EACA,OAAA;AAAA,EACA,iBAAA;AAAA,EACA,WAAA;AACF,CAAqB,KAAA;AACnB,EAAM,MAAA,YAAA,GAAeC,cAAQ,MAAM;AACjC,IAAI,IAAA,OAAA,EAAS,gBAAgB,WAAa,EAAA;AACxC,MAAO,OAAA,OAAA,CAAQ,YAAa,CAAA,MAAA,CAAO,WAAW,CAAA,CAAA;AAAA,eACrC,WAAa,EAAA;AACtB,MAAA,OAAO,CAAC,WAAW,CAAA,CAAA;AAAA,KACd,MAAA;AACL,MAAO,OAAA,OAAA,EAAS,gBAAgB,EAAC,CAAA;AAAA,KACnC;AAAA,GACC,EAAA,CAAC,OAAS,EAAA,WAAW,CAAC,CAAA,CAAA;AAEzB,EAAA,MAAM,gBAAmB,GAAAC,iBAAA;AAAA,IACvB,CAAC,MAAW,KAAA;AACV,MAAI,IAAA,iBAAA,GAAoB,MAAM,CAAG,EAAA;AAC/B,QAAO,OAAA,IAAA,CAAA;AAAA,OACT;AAEA,MAAI,IAAA,OAAA,EAAS,iBAAoB,GAAA,MAAM,CAAG,EAAA;AACxC,QAAO,OAAA,IAAA,CAAA;AAAA,OACT;AAAA,KACF;AAAA,IACA,CAAC,SAAS,iBAAiB,CAAA;AAAA,GAC7B,CAAA;AAEA,EACE,uBAAAC,cAAA;AAAA,IAAC,kBAAmB,CAAA,QAAA;AAAA,IAAnB;AAAA,MACC,KAAO,EAAA;AAAA,QACL,iBAAmB,EAAA,gBAAA;AAAA,QACnB,YAAA;AAAA,OACF;AAAA,MAEC,QAAA;AAAA,KAAA;AAAA,GACH,CAAA;AAEJ,CAAA,CAAA;AAGO,MAAM,sBAAsB,CAAC;AAAA,EAClC,QAAA;AAAA,EACA,KAAA;AAAA,EACA,iBAAA;AAAA,EACA,WAAA;AACF,CAAgC,KAAA;AAC9B,EAAA,uBACGA,cAAA,CAAA,kBAAA,CAAmB,QAAnB,EAAA,EACE,WAAC,aACA,qBAAAA,cAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,OAAS,EAAA,aAAA;AAAA,MACT,KAAA;AAAA,MACA,iBAAA;AAAA,MACA,WAAA;AAAA,MAEC,QAAA;AAAA,KAAA;AAAA,GAGP,EAAA,CAAA,CAAA;AAEJ;;;;;"}
1
+ {"version":3,"file":"context-menu-provider.js","sources":["../../src/menu/context-menu-provider.tsx"],"sourcesContent":["import type {\n ContextMenuContextType,\n MenuActionHandler,\n MenuBuilder,\n} from \"@vuu-ui/vuu-data-types\";\nimport { createContext, ReactNode, useCallback, useMemo } from \"react\";\n\nexport const ContextMenuContext = createContext<ContextMenuContextType | null>(\n null,\n);\n\nexport interface ContextMenuConfiguration {\n menuActionHandler?: MenuActionHandler;\n menuBuilder: MenuBuilder;\n}\n\nexport interface ContextMenuProviderProps extends ContextMenuConfiguration {\n children: ReactNode;\n label?: string;\n}\n\ninterface ProviderProps extends ContextMenuProviderProps {\n context: ContextMenuContextType | null;\n}\n\nconst Provider = ({\n children,\n context,\n menuActionHandler,\n menuBuilder,\n}: ProviderProps) => {\n const menuBuilders = useMemo(() => {\n if (context?.menuBuilders && menuBuilder) {\n return context.menuBuilders.concat(menuBuilder);\n } else if (menuBuilder) {\n return [menuBuilder];\n } else {\n return context?.menuBuilders || [];\n }\n }, [context, menuBuilder]);\n\n const handleMenuAction = useCallback(\n (reason) => {\n if (menuActionHandler?.(reason)) {\n return true;\n }\n\n if (context?.menuActionHandler?.(reason)) {\n return true;\n }\n },\n [context, menuActionHandler],\n );\n\n return (\n <ContextMenuContext.Provider\n value={{\n menuActionHandler: handleMenuAction,\n menuBuilders,\n }}\n >\n {children}\n </ContextMenuContext.Provider>\n );\n};\n\n// Need an option for local menu to override higher-level menu, rather than extend\nexport const ContextMenuProvider = ({\n children,\n label,\n menuActionHandler,\n menuBuilder,\n}: ContextMenuProviderProps) => {\n return (\n <ContextMenuContext.Consumer>\n {(parentContext) => (\n <Provider\n context={parentContext}\n label={label}\n menuActionHandler={menuActionHandler}\n menuBuilder={menuBuilder}\n >\n {children}\n </Provider>\n )}\n </ContextMenuContext.Consumer>\n );\n};\n"],"names":["createContext","useMemo","useCallback","jsx"],"mappings":";;;;;AAOO,MAAM,kBAAqB,GAAAA,mBAAA;AAAA,EAChC,IAAA;AACF,EAAA;AAgBA,MAAM,WAAW,CAAC;AAAA,EAChB,QAAA;AAAA,EACA,OAAA;AAAA,EACA,iBAAA;AAAA,EACA,WAAA;AACF,CAAqB,KAAA;AACnB,EAAM,MAAA,YAAA,GAAeC,cAAQ,MAAM;AACjC,IAAI,IAAA,OAAA,EAAS,gBAAgB,WAAa,EAAA;AACxC,MAAO,OAAA,OAAA,CAAQ,YAAa,CAAA,MAAA,CAAO,WAAW,CAAA,CAAA;AAAA,eACrC,WAAa,EAAA;AACtB,MAAA,OAAO,CAAC,WAAW,CAAA,CAAA;AAAA,KACd,MAAA;AACL,MAAO,OAAA,OAAA,EAAS,gBAAgB,EAAC,CAAA;AAAA,KACnC;AAAA,GACC,EAAA,CAAC,OAAS,EAAA,WAAW,CAAC,CAAA,CAAA;AAEzB,EAAA,MAAM,gBAAmB,GAAAC,iBAAA;AAAA,IACvB,CAAC,MAAW,KAAA;AACV,MAAI,IAAA,iBAAA,GAAoB,MAAM,CAAG,EAAA;AAC/B,QAAO,OAAA,IAAA,CAAA;AAAA,OACT;AAEA,MAAI,IAAA,OAAA,EAAS,iBAAoB,GAAA,MAAM,CAAG,EAAA;AACxC,QAAO,OAAA,IAAA,CAAA;AAAA,OACT;AAAA,KACF;AAAA,IACA,CAAC,SAAS,iBAAiB,CAAA;AAAA,GAC7B,CAAA;AAEA,EACE,uBAAAC,cAAA;AAAA,IAAC,kBAAmB,CAAA,QAAA;AAAA,IAAnB;AAAA,MACC,KAAO,EAAA;AAAA,QACL,iBAAmB,EAAA,gBAAA;AAAA,QACnB,YAAA;AAAA,OACF;AAAA,MAEC,QAAA;AAAA,KAAA;AAAA,GACH,CAAA;AAEJ,CAAA,CAAA;AAGO,MAAM,sBAAsB,CAAC;AAAA,EAClC,QAAA;AAAA,EACA,KAAA;AAAA,EACA,iBAAA;AAAA,EACA,WAAA;AACF,CAAgC,KAAA;AAC9B,EAAA,uBACGA,cAAA,CAAA,kBAAA,CAAmB,QAAnB,EAAA,EACE,WAAC,aACA,qBAAAA,cAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,OAAS,EAAA,aAAA;AAAA,MACT,KAAA;AAAA,MACA,iBAAA;AAAA,MACA,WAAA;AAAA,MAEC,QAAA;AAAA,KAAA;AAAA,GAGP,EAAA,CAAA,CAAA;AAEJ;;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-keyboard-navigation.js","sources":["../../src/menu/use-keyboard-navigation.ts"],"sourcesContent":["import {\n FocusEvent,\n KeyboardEvent,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { hasPopup, isRoot } from \"./utils\";\nimport { isNavigationKey } from \"./key-code\";\nimport { isValidNumber } from \"@vuu-ui/vuu-utils\";\nimport { MenuOpenHandler } from \"./MenuList\";\n\nexport type MenuCloseReason = \"tab-away\" | \"close-child-menu\";\n\nexport type MenuCloseHandler = (\n evt: KeyboardEvent,\n reason: MenuCloseReason\n) => void;\n\nexport interface KeyboardNavigationProps {\n autoHighlightFirstItem?: boolean;\n count: number;\n defaultHighlightedIdx?: number;\n highlightedIndex?: number;\n onActivate: (idx: number) => void;\n onHighlight?: (idx: number) => void;\n onCloseMenu: MenuCloseHandler;\n onOpenMenu?: MenuOpenHandler;\n}\n\nexport interface KeyboardHookListProps {\n // onBlur: (evt: FocusEvent) => void;\n onFocus: (evt: FocusEvent) => void;\n onKeyDown: (evt: KeyboardEvent) => void;\n onMouseDownCapture: () => void;\n onMouseMove: () => void;\n onMouseLeave: () => void;\n}\n\nexport interface NavigationHookResult {\n focusVisible: number;\n controlledHighlighting: boolean;\n highlightedIndex: number;\n setHighlightedIndex: (idx: number) => void;\n // keyboardNavigation: RefObject<boolean>;\n listProps: KeyboardHookListProps;\n setIgnoreFocus: (ignoreFocus: boolean) => void;\n}\n\n// we need a way to set highlightedIdx when selection changes\nexport const useKeyboardNavigation = ({\n autoHighlightFirstItem = false,\n count,\n defaultHighlightedIdx,\n highlightedIndex: highlightedIndexProp,\n onActivate,\n onHighlight,\n // onKeyDown,\n onCloseMenu,\n onOpenMenu,\n}: KeyboardNavigationProps): NavigationHookResult => {\n if (\n isValidNumber(highlightedIndexProp) &&\n isValidNumber(defaultHighlightedIdx)\n ) {\n throw Error(\n \"useKeyboardNavigation do not pass values for both highlightedIndex and defaultHighlightedIdx\"\n );\n }\n\n const controlledHighlighting = isValidNumber(highlightedIndexProp);\n const highlightedIndexRef = useRef(\n defaultHighlightedIdx ??\n highlightedIndexProp ??\n (autoHighlightFirstItem ? 0 : -1)\n );\n const [, forceRender] = useState<unknown>(null);\n\n const setHighlightedIdx = useCallback(\n (idx) => {\n highlightedIndexRef.current = idx;\n onHighlight?.(idx);\n forceRender({});\n },\n [onHighlight]\n );\n\n const setHighlightedIndex = useCallback(\n (idx) => {\n if (idx !== highlightedIndexRef.current) {\n if (!controlledHighlighting) {\n setHighlightedIdx(idx);\n }\n }\n },\n [controlledHighlighting, setHighlightedIdx]\n );\n\n // does this belong here or should it be a method passed in?\n const keyBoardNavigation = useRef(true);\n const ignoreFocus = useRef(false);\n const setIgnoreFocus = (value: boolean) => (ignoreFocus.current = value);\n\n const highlightedIndex = controlledHighlighting\n ? highlightedIndexProp\n : highlightedIndexRef.current;\n\n const navigateChildldItems = useCallback(\n (e: KeyboardEvent) => {\n const nextIdx = nextItemIdx(count, e.key, highlightedIndexRef.current);\n if (nextIdx !== highlightedIndexRef.current) {\n setHighlightedIndex(nextIdx);\n }\n },\n [count, setHighlightedIndex]\n );\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n if (isNavigationKey(e)) {\n e.preventDefault();\n e.stopPropagation();\n keyBoardNavigation.current = true;\n navigateChildldItems(e);\n } else if (\n (e.key === \"ArrowRight\" || e.key === \"Enter\") &&\n hasPopup(e.target as HTMLElement, highlightedIndex)\n ) {\n const menuEl = e.target as HTMLElement;\n const menuItemEl = menuEl.querySelector(\n `:scope > [data-index='${highlightedIndex}']`\n ) as HTMLElement;\n\n if (menuItemEl) {\n onOpenMenu?.(menuItemEl, true);\n }\n } else if (e.key === \"ArrowLeft\" && !isRoot(e.target as HTMLElement)) {\n onCloseMenu(e, \"close-child-menu\");\n } else if (e.key === \"Enter\") {\n e.preventDefault();\n e.stopPropagation();\n onActivate && onActivate(highlightedIndex);\n } else if (e.key === \"Tab\") {\n onCloseMenu(e, \"tab-away\");\n }\n },\n [\n highlightedIndex,\n navigateChildldItems,\n onActivate,\n onCloseMenu,\n onOpenMenu,\n ]\n );\n\n const listProps: KeyboardHookListProps = useMemo(\n () => ({\n onFocus: () => {\n if (highlightedIndex === -1) {\n setHighlightedIdx(0);\n }\n },\n onKeyDown: handleKeyDown,\n onMouseDownCapture: () => {\n keyBoardNavigation.current = false;\n setIgnoreFocus(true);\n },\n\n // onMouseEnter would seem less expensive but it misses some cases\n onMouseMove: () => {\n if (keyBoardNavigation.current) {\n keyBoardNavigation.current = false;\n }\n },\n onMouseLeave: () => {\n // label === 'ParsedInput' && console.log(`%c[useKeyboardNavigationHook]<${label}> onMouseLeave`,'color:brown')\n keyBoardNavigation.current = true;\n setIgnoreFocus(false);\n setHighlightedIndex(-1);\n },\n }),\n [handleKeyDown, highlightedIndex, setHighlightedIdx, setHighlightedIndex]\n );\n\n return {\n focusVisible: keyBoardNavigation.current ? highlightedIndex : -1,\n controlledHighlighting,\n highlightedIndex,\n setHighlightedIndex: setHighlightedIndex,\n // keyBoardNavigation,\n listProps,\n setIgnoreFocus,\n };\n};\n\n// need to be able to accommodate disabled items\nfunction nextItemIdx(count: number, key: string, idx: number) {\n if (key === \"ArrowUp\") {\n if (idx > 0) {\n return idx - 1;\n } else {\n return idx;\n }\n } else {\n if (idx === null) {\n return 0;\n } else if (idx === count - 1) {\n return idx;\n } else {\n return idx + 1;\n }\n }\n}\n"],"names":["isValidNumber","useRef","useState","useCallback","isNavigationKey","hasPopup","isRoot","useMemo"],"mappings":"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"}
1
+ {"version":3,"file":"use-keyboard-navigation.js","sources":["../../src/menu/use-keyboard-navigation.ts"],"sourcesContent":["import {\n FocusEvent,\n KeyboardEvent,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { hasPopup, isRoot } from \"./utils\";\nimport { isNavigationKey } from \"./key-code\";\nimport { isValidNumber } from \"@vuu-ui/vuu-utils\";\nimport { MenuOpenHandler } from \"./MenuList\";\n\nexport type MenuCloseReason = \"tab-away\" | \"close-child-menu\";\n\nexport type MenuCloseHandler = (\n evt: KeyboardEvent,\n reason: MenuCloseReason,\n) => void;\n\nexport interface KeyboardNavigationProps {\n autoHighlightFirstItem?: boolean;\n count: number;\n defaultHighlightedIdx?: number;\n highlightedIndex?: number;\n onActivate: (idx: number) => void;\n onHighlight?: (idx: number) => void;\n onCloseMenu: MenuCloseHandler;\n onOpenMenu?: MenuOpenHandler;\n}\n\nexport interface KeyboardHookListProps {\n // onBlur: (evt: FocusEvent) => void;\n onFocus: (evt: FocusEvent) => void;\n onKeyDown: (evt: KeyboardEvent) => void;\n onMouseDownCapture: () => void;\n onMouseMove: () => void;\n onMouseLeave: () => void;\n}\n\nexport interface NavigationHookResult {\n focusVisible: number;\n controlledHighlighting: boolean;\n highlightedIndex: number;\n setHighlightedIndex: (idx: number) => void;\n // keyboardNavigation: RefObject<boolean>;\n listProps: KeyboardHookListProps;\n setIgnoreFocus: (ignoreFocus: boolean) => void;\n}\n\n// we need a way to set highlightedIdx when selection changes\nexport const useKeyboardNavigation = ({\n autoHighlightFirstItem = false,\n count,\n defaultHighlightedIdx,\n highlightedIndex: highlightedIndexProp,\n onActivate,\n onHighlight,\n // onKeyDown,\n onCloseMenu,\n onOpenMenu,\n}: KeyboardNavigationProps): NavigationHookResult => {\n if (\n isValidNumber(highlightedIndexProp) &&\n isValidNumber(defaultHighlightedIdx)\n ) {\n throw Error(\n \"useKeyboardNavigation do not pass values for both highlightedIndex and defaultHighlightedIdx\",\n );\n }\n\n const controlledHighlighting = isValidNumber(highlightedIndexProp);\n const highlightedIndexRef = useRef(\n defaultHighlightedIdx ??\n highlightedIndexProp ??\n (autoHighlightFirstItem ? 0 : -1),\n );\n const [, forceRender] = useState<unknown>(null);\n\n const setHighlightedIdx = useCallback(\n (idx) => {\n highlightedIndexRef.current = idx;\n onHighlight?.(idx);\n forceRender({});\n },\n [onHighlight],\n );\n\n const setHighlightedIndex = useCallback(\n (idx) => {\n if (idx !== highlightedIndexRef.current) {\n if (!controlledHighlighting) {\n setHighlightedIdx(idx);\n }\n }\n },\n [controlledHighlighting, setHighlightedIdx],\n );\n\n // does this belong here or should it be a method passed in?\n const keyBoardNavigation = useRef(true);\n const ignoreFocus = useRef(false);\n const setIgnoreFocus = (value: boolean) => (ignoreFocus.current = value);\n\n const highlightedIndex = controlledHighlighting\n ? highlightedIndexProp\n : highlightedIndexRef.current;\n\n const navigateChildldItems = useCallback(\n (e: KeyboardEvent) => {\n const nextIdx = nextItemIdx(count, e.key, highlightedIndexRef.current);\n if (nextIdx !== highlightedIndexRef.current) {\n setHighlightedIndex(nextIdx);\n }\n },\n [count, setHighlightedIndex],\n );\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n if (isNavigationKey(e)) {\n e.preventDefault();\n e.stopPropagation();\n keyBoardNavigation.current = true;\n navigateChildldItems(e);\n } else if (\n (e.key === \"ArrowRight\" || e.key === \"Enter\") &&\n hasPopup(e.target as HTMLElement, highlightedIndex)\n ) {\n const menuEl = e.target as HTMLElement;\n const menuItemEl = menuEl.querySelector(\n `:scope > [data-index='${highlightedIndex}']`,\n ) as HTMLElement;\n\n if (menuItemEl) {\n onOpenMenu?.(menuItemEl, true);\n }\n } else if (e.key === \"ArrowLeft\" && !isRoot(e.target as HTMLElement)) {\n onCloseMenu(e, \"close-child-menu\");\n } else if (e.key === \"Enter\") {\n e.preventDefault();\n e.stopPropagation();\n onActivate && onActivate(highlightedIndex);\n } else if (e.key === \"Tab\") {\n onCloseMenu(e, \"tab-away\");\n }\n },\n [\n highlightedIndex,\n navigateChildldItems,\n onActivate,\n onCloseMenu,\n onOpenMenu,\n ],\n );\n\n const listProps: KeyboardHookListProps = useMemo(\n () => ({\n onFocus: () => {\n if (highlightedIndex === -1) {\n setHighlightedIdx(0);\n }\n },\n onKeyDown: handleKeyDown,\n onMouseDownCapture: () => {\n keyBoardNavigation.current = false;\n setIgnoreFocus(true);\n },\n\n // onMouseEnter would seem less expensive but it misses some cases\n onMouseMove: () => {\n if (keyBoardNavigation.current) {\n keyBoardNavigation.current = false;\n }\n },\n onMouseLeave: () => {\n // label === 'ParsedInput' && console.log(`%c[useKeyboardNavigationHook]<${label}> onMouseLeave`,'color:brown')\n keyBoardNavigation.current = true;\n setIgnoreFocus(false);\n setHighlightedIndex(-1);\n },\n }),\n [handleKeyDown, highlightedIndex, setHighlightedIdx, setHighlightedIndex],\n );\n\n return {\n focusVisible: keyBoardNavigation.current ? highlightedIndex : -1,\n controlledHighlighting,\n highlightedIndex,\n setHighlightedIndex: setHighlightedIndex,\n // keyBoardNavigation,\n listProps,\n setIgnoreFocus,\n };\n};\n\n// need to be able to accommodate disabled items\nfunction nextItemIdx(count: number, key: string, idx: number) {\n if (key === \"ArrowUp\") {\n if (idx > 0) {\n return idx - 1;\n } else {\n return idx;\n }\n } else {\n if (idx === null) {\n return 0;\n } else if (idx === count - 1) {\n return idx;\n } else {\n return idx + 1;\n }\n }\n}\n"],"names":["isValidNumber","useRef","useState","useCallback","isNavigationKey","hasPopup","isRoot","useMemo"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useContextMenu.js","sources":["../../src/menu/useContextMenu.tsx"],"sourcesContent":["import {\n ContextMenuItemDescriptor,\n MenuActionHandler,\n MenuBuilder,\n} from \"@vuu-ui/vuu-data-types\";\nimport {\n isGroupMenuItemDescriptor,\n useThemeAttributes,\n} from \"@vuu-ui/vuu-utils\";\nimport { cloneElement, useCallback, useContext, useMemo } from \"react\";\nimport {\n MenuActionClosePopup,\n PopupCloseReason,\n PopupService,\n reasonIsMenuAction,\n} from \"../popup\";\nimport { ContextMenu, ContextMenuProps } from \"./ContextMenu\";\nimport { MenuItem, MenuItemGroup } from \"./MenuList\";\nimport { ContextMenuContext } from \"./context-menu-provider\";\n\nexport type ContextMenuOptions = {\n [key: string]: unknown;\n contextMenu?: JSX.Element;\n ContextMenuProps?: Partial<ContextMenuProps> & {\n className?: string;\n };\n controlledComponentId?: string;\n};\n\nexport type EventLike = {\n clientX: number;\n clientY: number;\n preventDefault?: () => void;\n stopPropagation?: () => void;\n};\n\nexport type ShowContextMenu = (\n e: EventLike,\n location: string,\n options: ContextMenuOptions\n) => void;\n\n// The argument allows a top-level menuBuilder to operate outside the Context\nexport const useContextMenu = (\n menuBuilder?: MenuBuilder,\n menuActionHandler?: MenuActionHandler\n): [ShowContextMenu, () => void] => {\n const ctx = useContext(ContextMenuContext);\n\n const [themeClass, densityClass, dataMode] = useThemeAttributes();\n const themeAttributes = useMemo(\n () => ({\n themeClass,\n densityClass,\n dataMode,\n }),\n [dataMode, densityClass, themeClass]\n );\n\n const buildMenuOptions = useCallback(\n (menuBuilders: MenuBuilder[], location, options) => {\n let results: ContextMenuItemDescriptor[] = [];\n for (const menuBuilder of menuBuilders) {\n // Maybe we should leave the concatenation to the menuBuilder, then it can control menuItem order\n results = results.concat(menuBuilder(location, options));\n }\n return results;\n },\n []\n );\n\n const handleShowContextMenu = useCallback<ShowContextMenu>(\n (e, location, { ContextMenuProps, contextMenu, ...options }) => {\n e.stopPropagation?.();\n e.preventDefault?.();\n\n if (contextMenu) {\n return showContextMenuComponent(\n {\n x: e.clientX,\n y: e.clientY,\n },\n contextMenu\n );\n }\n\n const menuBuilders: MenuBuilder[] = [];\n if (menuBuilder) {\n menuBuilders.push(menuBuilder);\n }\n if (\n ctx &&\n Array.isArray(ctx?.menuBuilders) &&\n ctx.menuBuilders.length > 0\n ) {\n menuBuilders.push(...ctx.menuBuilders);\n }\n\n if (menuBuilders.length > 0) {\n const menuItemDescriptors = buildMenuOptions(\n menuBuilders,\n location,\n options\n );\n\n // const menuHandler = menuActionHandler ?? ctx?.menuActionHandler;\n const menuHandler: MenuActionHandler = (\n action: MenuActionClosePopup\n ) => {\n if (menuActionHandler?.(action) === true) {\n return true;\n } else {\n return ctx?.menuActionHandler(action);\n }\n };\n\n if (menuItemDescriptors.length && menuHandler) {\n // because showPopup is going to be used to render the context menu, it will not\n // have access to the ContextMenuContext. Pass the theme attributes here\n showContextMenu(e, menuItemDescriptors, menuHandler, {\n PortalProps: {\n themeAttributes,\n },\n ...ContextMenuProps,\n });\n }\n } else {\n console.warn(\n \"useContextMenu, no menuBuilders configured. These should be supplied via the ContextMenuProvider(s)\"\n );\n }\n },\n [buildMenuOptions, ctx, menuActionHandler, menuBuilder, themeAttributes]\n );\n\n const hideContextMenu = useCallback(() => {\n console.log(\"hide context menu\");\n }, []);\n\n return [handleShowContextMenu, hideContextMenu];\n};\n\nconst NO_OPTIONS = {};\n\nconst showContextMenuComponent = (\n position: { x: number; y: number },\n contextMenu: JSX.Element\n) => {\n PopupService.showPopup({\n focus: true,\n left: 0,\n top: 0,\n component: cloneElement(contextMenu, { position }),\n });\n};\n\nconst showContextMenu = (\n e: EventLike,\n menuDescriptors: ContextMenuItemDescriptor[],\n handleContextMenuAction: MenuActionHandler,\n {\n position: positionProp,\n ...contextMenuProps\n }: ContextMenuOptions[\"ContextMenuProps\"] = NO_OPTIONS\n) => {\n const menuItems = (menuDescriptors: ContextMenuItemDescriptor[]) => {\n const fromDescriptor = (menuItem: ContextMenuItemDescriptor, i: number) =>\n isGroupMenuItemDescriptor(menuItem) ? (\n <MenuItemGroup key={i} label={menuItem.label}>\n {menuItem.children.map(fromDescriptor)}\n </MenuItemGroup>\n ) : (\n <MenuItem\n key={i}\n action={menuItem.action}\n className={menuItem.className}\n data-icon={menuItem.icon}\n options={menuItem.options}\n >\n {menuItem.label}\n </MenuItem>\n );\n\n return menuDescriptors.map(fromDescriptor);\n };\n\n const handleClose = (reason?: PopupCloseReason) => {\n if (reasonIsMenuAction(reason)) {\n if (reason?.closedBy === \"popup-service\") {\n return;\n }\n handleContextMenuAction(reason);\n // TODO this results in onClose being called twice on component\n // cant simply be removed, some refactoring work needed\n PopupService.hidePopup(reason);\n }\n contextMenuProps?.onClose?.(reason);\n };\n\n const position = positionProp ?? {\n x: e.clientX,\n y: e.clientY,\n };\n\n const component = (\n <ContextMenu\n {...contextMenuProps}\n onClose={handleClose}\n position={position}\n >\n {menuItems(menuDescriptors)}\n </ContextMenu>\n );\n PopupService.showPopup({ left: 0, top: 0, component, focus: true });\n};\n"],"names":["useContext","ContextMenuContext","useThemeAttributes","useMemo","useCallback","menuBuilder","ContextMenuProps","PopupService","cloneElement","menuDescriptors","isGroupMenuItemDescriptor","jsx","MenuItemGroup","MenuItem","reasonIsMenuAction","ContextMenu"],"mappings":"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"}
1
+ {"version":3,"file":"useContextMenu.js","sources":["../../src/menu/useContextMenu.tsx"],"sourcesContent":["import {\n ContextMenuItemDescriptor,\n MenuActionHandler,\n MenuBuilder,\n} from \"@vuu-ui/vuu-data-types\";\nimport {\n isGroupMenuItemDescriptor,\n useThemeAttributes,\n} from \"@vuu-ui/vuu-utils\";\nimport { cloneElement, useCallback, useContext, useMemo } from \"react\";\nimport {\n MenuActionClosePopup,\n PopupCloseReason,\n PopupService,\n reasonIsMenuAction,\n} from \"../popup\";\nimport { ContextMenu, ContextMenuProps } from \"./ContextMenu\";\nimport { MenuItem, MenuItemGroup } from \"./MenuList\";\nimport { ContextMenuContext } from \"./context-menu-provider\";\n\nexport type ContextMenuOptions = {\n [key: string]: unknown;\n contextMenu?: JSX.Element;\n ContextMenuProps?: Partial<ContextMenuProps> & {\n className?: string;\n };\n controlledComponentId?: string;\n};\n\nexport type EventLike = {\n clientX: number;\n clientY: number;\n preventDefault?: () => void;\n stopPropagation?: () => void;\n};\n\nexport type ShowContextMenu = (\n e: EventLike,\n location: string,\n options: ContextMenuOptions,\n) => void;\n\n// The argument allows a top-level menuBuilder to operate outside the Context\nexport const useContextMenu = (\n menuBuilder?: MenuBuilder,\n menuActionHandler?: MenuActionHandler,\n): [ShowContextMenu, () => void] => {\n const ctx = useContext(ContextMenuContext);\n\n const [themeClass, densityClass, dataMode] = useThemeAttributes();\n const themeAttributes = useMemo(\n () => ({\n themeClass,\n densityClass,\n dataMode,\n }),\n [dataMode, densityClass, themeClass],\n );\n\n const buildMenuOptions = useCallback(\n (menuBuilders: MenuBuilder[], location, options) => {\n let results: ContextMenuItemDescriptor[] = [];\n for (const menuBuilder of menuBuilders) {\n // Maybe we should leave the concatenation to the menuBuilder, then it can control menuItem order\n results = results.concat(menuBuilder(location, options));\n }\n return results;\n },\n [],\n );\n\n const handleShowContextMenu = useCallback<ShowContextMenu>(\n (e, location, { ContextMenuProps, contextMenu, ...options }) => {\n e.stopPropagation?.();\n e.preventDefault?.();\n\n if (contextMenu) {\n return showContextMenuComponent(\n {\n x: e.clientX,\n y: e.clientY,\n },\n contextMenu,\n );\n }\n\n const menuBuilders: MenuBuilder[] = [];\n if (menuBuilder) {\n menuBuilders.push(menuBuilder);\n }\n if (\n ctx &&\n Array.isArray(ctx?.menuBuilders) &&\n ctx.menuBuilders.length > 0\n ) {\n menuBuilders.push(...ctx.menuBuilders);\n }\n\n if (menuBuilders.length > 0) {\n const menuItemDescriptors = buildMenuOptions(\n menuBuilders,\n location,\n options,\n );\n\n // const menuHandler = menuActionHandler ?? ctx?.menuActionHandler;\n const menuHandler: MenuActionHandler = (\n action: MenuActionClosePopup,\n ) => {\n if (menuActionHandler?.(action) === true) {\n return true;\n } else {\n return ctx?.menuActionHandler(action);\n }\n };\n\n if (menuItemDescriptors.length && menuHandler) {\n // because showPopup is going to be used to render the context menu, it will not\n // have access to the ContextMenuContext. Pass the theme attributes here\n showContextMenu(e, menuItemDescriptors, menuHandler, {\n PortalProps: {\n themeAttributes,\n },\n ...ContextMenuProps,\n });\n }\n } else {\n console.warn(\n \"useContextMenu, no menuBuilders configured. These should be supplied via the ContextMenuProvider(s)\",\n );\n }\n },\n [buildMenuOptions, ctx, menuActionHandler, menuBuilder, themeAttributes],\n );\n\n const hideContextMenu = useCallback(() => {\n console.log(\"hide context menu\");\n }, []);\n\n return [handleShowContextMenu, hideContextMenu];\n};\n\nconst NO_OPTIONS = {};\n\nconst showContextMenuComponent = (\n position: { x: number; y: number },\n contextMenu: JSX.Element,\n) => {\n PopupService.showPopup({\n focus: true,\n left: 0,\n top: 0,\n component: cloneElement(contextMenu, { position }),\n });\n};\n\nconst showContextMenu = (\n e: EventLike,\n menuDescriptors: ContextMenuItemDescriptor[],\n handleContextMenuAction: MenuActionHandler,\n {\n position: positionProp,\n ...contextMenuProps\n }: ContextMenuOptions[\"ContextMenuProps\"] = NO_OPTIONS,\n) => {\n const menuItems = (menuDescriptors: ContextMenuItemDescriptor[]) => {\n const fromDescriptor = (menuItem: ContextMenuItemDescriptor, i: number) =>\n isGroupMenuItemDescriptor(menuItem) ? (\n <MenuItemGroup key={i} label={menuItem.label}>\n {menuItem.children.map(fromDescriptor)}\n </MenuItemGroup>\n ) : (\n <MenuItem\n key={i}\n action={menuItem.action}\n className={menuItem.className}\n data-icon={menuItem.icon}\n options={menuItem.options}\n >\n {menuItem.label}\n </MenuItem>\n );\n\n return menuDescriptors.map(fromDescriptor);\n };\n\n const handleClose = (reason?: PopupCloseReason) => {\n if (reasonIsMenuAction(reason)) {\n if (reason?.closedBy === \"popup-service\") {\n return;\n }\n handleContextMenuAction(reason);\n // TODO this results in onClose being called twice on component\n // cant simply be removed, some refactoring work needed\n PopupService.hidePopup(reason);\n }\n contextMenuProps?.onClose?.(reason);\n };\n\n const position = positionProp ?? {\n x: e.clientX,\n y: e.clientY,\n };\n\n const component = (\n <ContextMenu\n {...contextMenuProps}\n onClose={handleClose}\n position={position}\n >\n {menuItems(menuDescriptors)}\n </ContextMenu>\n );\n PopupService.showPopup({ left: 0, top: 0, component, focus: true });\n};\n"],"names":["useContext","ContextMenuContext","useThemeAttributes","useMemo","useCallback","menuBuilder","ContextMenuProps","PopupService","cloneElement","menuDescriptors","isGroupMenuItemDescriptor","jsx","MenuItemGroup","MenuItem","reasonIsMenuAction","ContextMenu"],"mappings":"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"}
@@ -21,9 +21,12 @@ const NotificationsCenter = ({
21
21
  id: vuuUtils.getUniqueId()
22
22
  };
23
23
  setNotifications((prev) => prev.concat(newNotification));
24
- setTimeout(() => {
25
- setNotifications((prev) => prev.filter((n) => n !== newNotification));
26
- }, toastDisplayDuration + horizontalTransitionDuration * 2);
24
+ setTimeout(
25
+ () => {
26
+ setNotifications((prev) => prev.filter((n) => n !== newNotification));
27
+ },
28
+ toastDisplayDuration + horizontalTransitionDuration * 2
29
+ );
27
30
  });
28
31
  }, [notificationsContext]);
29
32
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: notifications.map((notification, i) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -1 +1 @@
1
- {"version":3,"file":"NotificationsCenter.js","sources":["../../src/notifications/NotificationsCenter.tsx"],"sourcesContent":["import { useMemo, useState } from \"react\";\nimport { NotificationsContext } from \"./NotificationsProvider\";\nimport { getUniqueId } from \"@vuu-ui/vuu-utils\";\nimport { ToastNotification } from \"./ToastNotification\";\nimport { Notification } from \"./notificationTypes\";\n\nexport interface NotificationsCenterProps {\n notificationsContext: NotificationsContext;\n}\n\n// animation times in milliseconds\nconst toastOffsetTop = 60;\nconst toastDisplayDuration = 6000;\nconst horizontalTransitionDuration = 1000;\n\n// toast size in pixels\nconst toastHeight = 56;\nconst toastContainerContentGap = 10;\n// rightPadding is used together with the toastWidth to compute the toast position\n// at the beginning and at the end of the animation\n\nexport const NotificationsCenter = ({\n notificationsContext,\n}: NotificationsCenterProps) => {\n const [notifications, setNotifications] = useState<Notification[]>([]);\n\n useMemo(() => {\n notificationsContext.setNotify((notification) => {\n const newNotification: Notification = {\n ...notification,\n id: getUniqueId(),\n };\n setNotifications((prev) => prev.concat(newNotification));\n setTimeout(() => {\n setNotifications((prev) => prev.filter((n) => n !== newNotification));\n }, toastDisplayDuration + horizontalTransitionDuration * 2);\n });\n }, [notificationsContext]);\n\n return (\n <>\n {notifications.map((notification, i) => (\n <ToastNotification\n top={toastOffsetTop + (toastHeight + toastContainerContentGap) * i}\n notification={notification}\n key={notification.id}\n />\n ))}\n </>\n );\n};\n"],"names":["useState","useMemo","getUniqueId","jsx","Fragment","ToastNotification"],"mappings":";;;;;;;AAWA,MAAM,cAAiB,GAAA,EAAA,CAAA;AACvB,MAAM,oBAAuB,GAAA,GAAA,CAAA;AAC7B,MAAM,4BAA+B,GAAA,GAAA,CAAA;AAGrC,MAAM,WAAc,GAAA,EAAA,CAAA;AACpB,MAAM,wBAA2B,GAAA,EAAA,CAAA;AAI1B,MAAM,sBAAsB,CAAC;AAAA,EAClC,oBAAA;AACF,CAAgC,KAAA;AAC9B,EAAA,MAAM,CAAC,aAAe,EAAA,gBAAgB,CAAI,GAAAA,cAAA,CAAyB,EAAE,CAAA,CAAA;AAErE,EAAAC,aAAA,CAAQ,MAAM;AACZ,IAAqB,oBAAA,CAAA,SAAA,CAAU,CAAC,YAAiB,KAAA;AAC/C,MAAA,MAAM,eAAgC,GAAA;AAAA,QACpC,GAAG,YAAA;AAAA,QACH,IAAIC,oBAAY,EAAA;AAAA,OAClB,CAAA;AACA,MAAA,gBAAA,CAAiB,CAAC,IAAA,KAAS,IAAK,CAAA,MAAA,CAAO,eAAe,CAAC,CAAA,CAAA;AACvD,MAAA,UAAA,CAAW,MAAM;AACf,QAAiB,gBAAA,CAAA,CAAC,SAAS,IAAK,CAAA,MAAA,CAAO,CAAC,CAAM,KAAA,CAAA,KAAM,eAAe,CAAC,CAAA,CAAA;AAAA,OACtE,EAAG,oBAAuB,GAAA,4BAAA,GAA+B,CAAC,CAAA,CAAA;AAAA,KAC3D,CAAA,CAAA;AAAA,GACH,EAAG,CAAC,oBAAoB,CAAC,CAAA,CAAA;AAEzB,EAAA,uBAEKC,cAAA,CAAAC,mBAAA,EAAA,EAAA,QAAA,EAAA,aAAA,CAAc,GAAI,CAAA,CAAC,cAAc,CAChC,qBAAAD,cAAA;AAAA,IAACE,mCAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,cAAkB,GAAA,CAAA,WAAA,GAAc,wBAA4B,IAAA,CAAA;AAAA,MACjE,YAAA;AAAA,KAAA;AAAA,IACK,YAAa,CAAA,EAAA;AAAA,GAErB,CACH,EAAA,CAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"NotificationsCenter.js","sources":["../../src/notifications/NotificationsCenter.tsx"],"sourcesContent":["import { useMemo, useState } from \"react\";\nimport { NotificationsContext } from \"./NotificationsProvider\";\nimport { getUniqueId } from \"@vuu-ui/vuu-utils\";\nimport { ToastNotification } from \"./ToastNotification\";\nimport { Notification } from \"./notificationTypes\";\n\nexport interface NotificationsCenterProps {\n notificationsContext: NotificationsContext;\n}\n\n// animation times in milliseconds\nconst toastOffsetTop = 60;\nconst toastDisplayDuration = 6000;\nconst horizontalTransitionDuration = 1000;\n\n// toast size in pixels\nconst toastHeight = 56;\nconst toastContainerContentGap = 10;\n// rightPadding is used together with the toastWidth to compute the toast position\n// at the beginning and at the end of the animation\n\nexport const NotificationsCenter = ({\n notificationsContext,\n}: NotificationsCenterProps) => {\n const [notifications, setNotifications] = useState<Notification[]>([]);\n\n useMemo(() => {\n notificationsContext.setNotify((notification) => {\n const newNotification: Notification = {\n ...notification,\n id: getUniqueId(),\n };\n setNotifications((prev) => prev.concat(newNotification));\n setTimeout(\n () => {\n setNotifications((prev) => prev.filter((n) => n !== newNotification));\n },\n toastDisplayDuration + horizontalTransitionDuration * 2,\n );\n });\n }, [notificationsContext]);\n\n return (\n <>\n {notifications.map((notification, i) => (\n <ToastNotification\n top={toastOffsetTop + (toastHeight + toastContainerContentGap) * i}\n notification={notification}\n key={notification.id}\n />\n ))}\n </>\n );\n};\n"],"names":["useState","useMemo","getUniqueId","jsx","Fragment","ToastNotification"],"mappings":";;;;;;;AAWA,MAAM,cAAiB,GAAA,EAAA,CAAA;AACvB,MAAM,oBAAuB,GAAA,GAAA,CAAA;AAC7B,MAAM,4BAA+B,GAAA,GAAA,CAAA;AAGrC,MAAM,WAAc,GAAA,EAAA,CAAA;AACpB,MAAM,wBAA2B,GAAA,EAAA,CAAA;AAI1B,MAAM,sBAAsB,CAAC;AAAA,EAClC,oBAAA;AACF,CAAgC,KAAA;AAC9B,EAAA,MAAM,CAAC,aAAe,EAAA,gBAAgB,CAAI,GAAAA,cAAA,CAAyB,EAAE,CAAA,CAAA;AAErE,EAAAC,aAAA,CAAQ,MAAM;AACZ,IAAqB,oBAAA,CAAA,SAAA,CAAU,CAAC,YAAiB,KAAA;AAC/C,MAAA,MAAM,eAAgC,GAAA;AAAA,QACpC,GAAG,YAAA;AAAA,QACH,IAAIC,oBAAY,EAAA;AAAA,OAClB,CAAA;AACA,MAAA,gBAAA,CAAiB,CAAC,IAAA,KAAS,IAAK,CAAA,MAAA,CAAO,eAAe,CAAC,CAAA,CAAA;AACvD,MAAA,UAAA;AAAA,QACE,MAAM;AACJ,UAAiB,gBAAA,CAAA,CAAC,SAAS,IAAK,CAAA,MAAA,CAAO,CAAC,CAAM,KAAA,CAAA,KAAM,eAAe,CAAC,CAAA,CAAA;AAAA,SACtE;AAAA,QACA,uBAAuB,4BAA+B,GAAA,CAAA;AAAA,OACxD,CAAA;AAAA,KACD,CAAA,CAAA;AAAA,GACH,EAAG,CAAC,oBAAoB,CAAC,CAAA,CAAA;AAEzB,EAAA,uBAEKC,cAAA,CAAAC,mBAAA,EAAA,EAAA,QAAA,EAAA,aAAA,CAAc,GAAI,CAAA,CAAC,cAAc,CAChC,qBAAAD,cAAA;AAAA,IAACE,mCAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,cAAkB,GAAA,CAAA,WAAA,GAAc,wBAA4B,IAAA,CAAA;AAAA,MACjE,YAAA;AAAA,KAAA;AAAA,IACK,YAAa,CAAA,EAAA;AAAA,GAErB,CACH,EAAA,CAAA,CAAA;AAEJ;;;;"}
@@ -4,24 +4,13 @@ var jsxRuntime = require('react/jsx-runtime');
4
4
  var React = require('react');
5
5
  var NotificationsCenter = require('./NotificationsCenter.js');
6
6
 
7
- var __accessCheck = (obj, member, msg) => {
8
- if (!member.has(obj))
9
- throw TypeError("Cannot " + msg);
10
- };
11
- var __privateGet = (obj, member, getter) => {
12
- __accessCheck(obj, member, "read from private field");
13
- return getter ? getter.call(obj) : member.get(obj);
14
- };
15
- var __privateAdd = (obj, member, value) => {
16
- if (member.has(obj))
17
- throw TypeError("Cannot add the same private member more than once");
18
- member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
19
- };
20
- var __privateSet = (obj, member, value, setter) => {
21
- __accessCheck(obj, member, "write to private field");
22
- setter ? setter.call(obj, value) : member.set(obj, value);
23
- return value;
7
+ var __typeError = (msg) => {
8
+ throw TypeError(msg);
24
9
  };
10
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
11
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
12
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
13
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
25
14
  var _notify;
26
15
  class NotificationsContextObject {
27
16
  constructor() {
@@ -1 +1 @@
1
- {"version":3,"file":"NotificationsProvider.js","sources":["../../src/notifications/NotificationsProvider.tsx"],"sourcesContent":["import React, { useContext } from \"react\";\nimport { NotificationsCenter } from \"./NotificationsCenter\";\nimport { Notification } from \"./notificationTypes\";\n\nexport type DispatchNotification = (\n notification: Omit<Notification, \"id\">\n) => void;\n\nexport type NotificationsContext = {\n notify: DispatchNotification;\n setNotify: (dispatcher: DispatchNotification) => void;\n};\n\n/*\n The Context is not exposed outside this module, only the notify\n prop can be accessed via the useNotifications hook.\n The NotificationsCenter receives the full context object and\n sets the notify method. State management around dispatched\n notifications is handled entirely within the NotificationsCenter,\n avoiding rerendering our children when notifications are \n dispatched.\n*/\nclass NotificationsContextObject implements NotificationsContext {\n #notify: DispatchNotification = () =>\n console.log(\"have you forgotten to provide a NotificationsCenter?\");\n // We want the public notify method to be stable, setNotify call should not trigger re-renders\n notify: DispatchNotification = (notification) => this.#notify(notification);\n setNotify = (dispatcher: DispatchNotification) => {\n this.#notify = dispatcher;\n };\n}\n\nconst NotificationsContext = React.createContext<NotificationsContext>(\n new NotificationsContextObject()\n);\n\nexport const NotificationsProvider = (props: {\n children: JSX.Element | JSX.Element[];\n}) => {\n const context = useContext(NotificationsContext);\n return (\n <NotificationsContext.Provider value={context}>\n <NotificationsCenter notificationsContext={context} />\n {props.children}\n </NotificationsContext.Provider>\n );\n};\n\nexport const useNotifications = () => {\n const { notify } = useContext(NotificationsContext);\n return notify;\n};\n"],"names":["useContext","jsxs","jsx","NotificationsCenter"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAA,OAAA,CAAA;AAsBA,MAAM,0BAA2D,CAAA;AAAA,EAAjE,WAAA,GAAA;AACE,IAAgC,YAAA,CAAA,IAAA,EAAA,OAAA,EAAA,MAC9B,OAAQ,CAAA,GAAA,CAAI,sDAAsD,CAAA,CAAA,CAAA;AAEpE;AAAA,IAAA,IAAA,CAAA,MAAA,GAA+B,CAAC,YAAA,KAAiB,YAAK,CAAA,IAAA,EAAA,OAAA,CAAA,CAAL,IAAa,CAAA,IAAA,EAAA,YAAA,CAAA,CAAA;AAC9D,IAAA,IAAA,CAAA,SAAA,GAAY,CAAC,UAAqC,KAAA;AAChD,MAAA,YAAA,CAAA,IAAA,EAAK,OAAU,EAAA,UAAA,CAAA,CAAA;AAAA,KACjB,CAAA;AAAA,GAAA;AACF,CAAA;AAPE,OAAA,GAAA,IAAA,OAAA,EAAA,CAAA;AASF,MAAM,uBAAuB,KAAM,CAAA,aAAA;AAAA,EACjC,IAAI,0BAA2B,EAAA;AACjC,CAAA,CAAA;AAEa,MAAA,qBAAA,GAAwB,CAAC,KAEhC,KAAA;AACJ,EAAM,MAAA,OAAA,GAAUA,iBAAW,oBAAoB,CAAA,CAAA;AAC/C,EAAA,uBACGC,eAAA,CAAA,oBAAA,CAAqB,QAArB,EAAA,EAA8B,OAAO,OACpC,EAAA,QAAA,EAAA;AAAA,oBAACC,cAAA,CAAAC,uCAAA,EAAA,EAAoB,sBAAsB,OAAS,EAAA,CAAA;AAAA,IACnD,KAAM,CAAA,QAAA;AAAA,GACT,EAAA,CAAA,CAAA;AAEJ,EAAA;AAEO,MAAM,mBAAmB,MAAM;AACpC,EAAA,MAAM,EAAE,MAAA,EAAW,GAAAH,gBAAA,CAAW,oBAAoB,CAAA,CAAA;AAClD,EAAO,OAAA,MAAA,CAAA;AACT;;;;;"}
1
+ {"version":3,"file":"NotificationsProvider.js","sources":["../../src/notifications/NotificationsProvider.tsx"],"sourcesContent":["import React, { useContext } from \"react\";\nimport { NotificationsCenter } from \"./NotificationsCenter\";\nimport { Notification } from \"./notificationTypes\";\n\nexport type DispatchNotification = (\n notification: Omit<Notification, \"id\">\n) => void;\n\nexport type NotificationsContext = {\n notify: DispatchNotification;\n setNotify: (dispatcher: DispatchNotification) => void;\n};\n\n/*\n The Context is not exposed outside this module, only the notify\n prop can be accessed via the useNotifications hook.\n The NotificationsCenter receives the full context object and\n sets the notify method. State management around dispatched\n notifications is handled entirely within the NotificationsCenter,\n avoiding rerendering our children when notifications are \n dispatched.\n*/\nclass NotificationsContextObject implements NotificationsContext {\n #notify: DispatchNotification = () =>\n console.log(\"have you forgotten to provide a NotificationsCenter?\");\n // We want the public notify method to be stable, setNotify call should not trigger re-renders\n notify: DispatchNotification = (notification) => this.#notify(notification);\n setNotify = (dispatcher: DispatchNotification) => {\n this.#notify = dispatcher;\n };\n}\n\nconst NotificationsContext = React.createContext<NotificationsContext>(\n new NotificationsContextObject()\n);\n\nexport const NotificationsProvider = (props: {\n children: JSX.Element | JSX.Element[];\n}) => {\n const context = useContext(NotificationsContext);\n return (\n <NotificationsContext.Provider value={context}>\n <NotificationsCenter notificationsContext={context} />\n {props.children}\n </NotificationsContext.Provider>\n );\n};\n\nexport const useNotifications = () => {\n const { notify } = useContext(NotificationsContext);\n return notify;\n};\n"],"names":["useContext","jsxs","jsx","NotificationsCenter"],"mappings":";;;;;;;;;;;;;AAAA,IAAA,OAAA,CAAA;AAsBA,MAAM,0BAA2D,CAAA;AAAA,EAAjE,WAAA,GAAA;AACE,IAAgC,YAAA,CAAA,IAAA,EAAA,OAAA,EAAA,MAC9B,OAAQ,CAAA,GAAA,CAAI,sDAAsD,CAAA,CAAA,CAAA;AAEpE;AAAA,IAAA,IAAA,CAAA,MAAA,GAA+B,CAAC,YAAA,KAAiB,YAAK,CAAA,IAAA,EAAA,OAAA,CAAA,CAAL,IAAa,CAAA,IAAA,EAAA,YAAA,CAAA,CAAA;AAC9D,IAAA,IAAA,CAAA,SAAA,GAAY,CAAC,UAAqC,KAAA;AAChD,MAAA,YAAA,CAAA,IAAA,EAAK,OAAU,EAAA,UAAA,CAAA,CAAA;AAAA,KACjB,CAAA;AAAA,GAAA;AACF,CAAA;AAPE,OAAA,GAAA,IAAA,OAAA,EAAA,CAAA;AASF,MAAM,uBAAuB,KAAM,CAAA,aAAA;AAAA,EACjC,IAAI,0BAA2B,EAAA;AACjC,CAAA,CAAA;AAEa,MAAA,qBAAA,GAAwB,CAAC,KAEhC,KAAA;AACJ,EAAM,MAAA,OAAA,GAAUA,iBAAW,oBAAoB,CAAA,CAAA;AAC/C,EAAA,uBACGC,eAAA,CAAA,oBAAA,CAAqB,QAArB,EAAA,EAA8B,OAAO,OACpC,EAAA,QAAA,EAAA;AAAA,oBAACC,cAAA,CAAAC,uCAAA,EAAA,EAAoB,sBAAsB,OAAS,EAAA,CAAA;AAAA,IACnD,KAAM,CAAA,QAAA;AAAA,GACT,EAAA,CAAA,CAAA;AAEJ,EAAA;AAEO,MAAM,mBAAmB,MAAM;AACpC,EAAA,MAAM,EAAE,MAAA,EAAW,GAAAH,gBAAA,CAAW,oBAAoB,CAAA,CAAA;AAClD,EAAO,OAAA,MAAA,CAAA;AACT;;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ToastNotification.js","sources":["../../src/notifications/ToastNotification.tsx"],"sourcesContent":["import { Icon } from \"@vuu-ui/vuu-ui-controls\";\nimport cx from \"clsx\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { useEffect, useState } from \"react\";\nimport { Portal } from \"../portal\";\nimport type { Notification } from \"./notificationTypes\";\n\nimport toastNotificationCss from \"./ToastNotification.css\";\n\nconst toastWidth = 300;\nconst toastContainerRightPadding = 50;\nconst toastDisplayDuration = 6000;\nconst horizontalTransitionDuration = 1000;\nconst toastHeight = 56;\nconst verticalTransitionDuration = 300;\n\nexport type ToastNotificationProps = {\n top: number;\n notification: Notification;\n animated?: boolean;\n};\n\nconst classBase = \"vuuToastNotification\";\n\nconst icon = {\n error: \"error\",\n info: \"info-circle\",\n success: \"tick\",\n warning: \"warn-triangle\",\n};\n\nexport const ToastNotification = (props: ToastNotificationProps) => {\n const { top, notification, animated = true } = props;\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-toast-notification\",\n css: toastNotificationCss,\n window: targetWindow,\n });\n\n const [right, setRight] = useState(-toastWidth - toastContainerRightPadding);\n\n useEffect(() => {\n setTimeout(() => setRight(toastContainerRightPadding));\n\n if (animated) {\n setTimeout(\n () => setRight(-toastWidth - toastContainerRightPadding),\n toastDisplayDuration + horizontalTransitionDuration\n );\n }\n }, [animated]);\n\n return (\n <Portal>\n <div\n className={cx(classBase, `${classBase}-${notification.type}`)}\n style={{\n height: toastHeight,\n right,\n width: toastWidth,\n top,\n transition: animated\n ? `right ${horizontalTransitionDuration}ms, top ${verticalTransitionDuration}ms `\n : \"none\",\n }}\n >\n <Icon name={icon[notification.type]} />\n <div className={`${classBase}-toastContent`}>\n <strong className={`${classBase}-toastHeader`}>\n {notification.header}\n </strong>\n <div>{notification.body}</div>\n </div>\n </div>\n </Portal>\n );\n};\n"],"names":["useWindow","useComponentCssInjection","toastNotificationCss","useState","useEffect","Portal","jsxs","jsx","Icon"],"mappings":";;;;;;;;;;;AAUA,MAAM,UAAa,GAAA,GAAA,CAAA;AACnB,MAAM,0BAA6B,GAAA,EAAA,CAAA;AACnC,MAAM,oBAAuB,GAAA,GAAA,CAAA;AAC7B,MAAM,4BAA+B,GAAA,GAAA,CAAA;AACrC,MAAM,WAAc,GAAA,EAAA,CAAA;AACpB,MAAM,0BAA6B,GAAA,GAAA,CAAA;AAQnC,MAAM,SAAY,GAAA,sBAAA,CAAA;AAElB,MAAM,IAAO,GAAA;AAAA,EACX,KAAO,EAAA,OAAA;AAAA,EACP,IAAM,EAAA,aAAA;AAAA,EACN,OAAS,EAAA,MAAA;AAAA,EACT,OAAS,EAAA,eAAA;AACX,CAAA,CAAA;AAEa,MAAA,iBAAA,GAAoB,CAAC,KAAkC,KAAA;AAClE,EAAA,MAAM,EAAE,GAAA,EAAK,YAAc,EAAA,QAAA,GAAW,MAAS,GAAA,KAAA,CAAA;AAC/C,EAAA,MAAM,eAAeA,gBAAU,EAAA,CAAA;AAC/B,EAAyBC,+BAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,wBAAA;AAAA,IACR,GAAK,EAAAC,mBAAA;AAAA,IACL,MAAQ,EAAA,YAAA;AAAA,GACT,CAAA,CAAA;AAED,EAAA,MAAM,CAAC,KAAO,EAAA,QAAQ,IAAIC,cAAS,CAAA,CAAC,aAAa,0BAA0B,CAAA,CAAA;AAE3E,EAAAC,eAAA,CAAU,MAAM;AACd,IAAW,UAAA,CAAA,MAAM,QAAS,CAAA,0BAA0B,CAAC,CAAA,CAAA;AAErD,IAAA,IAAI,QAAU,EAAA;AACZ,MAAA,UAAA;AAAA,QACE,MAAM,QAAA,CAAS,CAAC,UAAA,GAAa,0BAA0B,CAAA;AAAA,QACvD,oBAAuB,GAAA,4BAAA;AAAA,OACzB,CAAA;AAAA,KACF;AAAA,GACF,EAAG,CAAC,QAAQ,CAAC,CAAA,CAAA;AAEb,EAAA,sCACGC,aACC,EAAA,EAAA,QAAA,kBAAAC,eAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,GAAG,SAAW,EAAA,CAAA,EAAG,SAAS,CAAI,CAAA,EAAA,YAAA,CAAa,IAAI,CAAE,CAAA,CAAA;AAAA,MAC5D,KAAO,EAAA;AAAA,QACL,MAAQ,EAAA,WAAA;AAAA,QACR,KAAA;AAAA,QACA,KAAO,EAAA,UAAA;AAAA,QACP,GAAA;AAAA,QACA,YAAY,QACR,GAAA,CAAA,MAAA,EAAS,4BAA4B,CAAA,QAAA,EAAW,0BAA0B,CAC1E,GAAA,CAAA,GAAA,MAAA;AAAA,OACN;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAAC,cAAA,CAACC,kBAAK,EAAA,EAAA,IAAA,EAAM,IAAK,CAAA,YAAA,CAAa,IAAI,CAAG,EAAA,CAAA;AAAA,wBACpCF,eAAA,CAAA,KAAA,EAAA,EAAI,SAAW,EAAA,CAAA,EAAG,SAAS,CAC1B,aAAA,CAAA,EAAA,QAAA,EAAA;AAAA,0BAAAC,cAAA,CAAC,YAAO,SAAW,EAAA,CAAA,EAAG,SAAS,CAAA,YAAA,CAAA,EAC5B,uBAAa,MAChB,EAAA,CAAA;AAAA,0BACAA,cAAA,CAAC,KAAK,EAAA,EAAA,QAAA,EAAA,YAAA,CAAa,IAAK,EAAA,CAAA;AAAA,SAC1B,EAAA,CAAA;AAAA,OAAA;AAAA,KAAA;AAAA,GAEJ,EAAA,CAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"ToastNotification.js","sources":["../../src/notifications/ToastNotification.tsx"],"sourcesContent":["import { Icon } from \"@vuu-ui/vuu-ui-controls\";\nimport cx from \"clsx\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { useEffect, useState } from \"react\";\nimport { Portal } from \"../portal\";\nimport type { Notification } from \"./notificationTypes\";\n\nimport toastNotificationCss from \"./ToastNotification.css\";\n\nconst toastWidth = 300;\nconst toastContainerRightPadding = 50;\nconst toastDisplayDuration = 6000;\nconst horizontalTransitionDuration = 1000;\nconst toastHeight = 56;\nconst verticalTransitionDuration = 300;\n\nexport type ToastNotificationProps = {\n top: number;\n notification: Notification;\n animated?: boolean;\n};\n\nconst classBase = \"vuuToastNotification\";\n\nconst icon = {\n error: \"error\",\n info: \"info-circle\",\n success: \"tick\",\n warning: \"warn-triangle\",\n};\n\nexport const ToastNotification = (props: ToastNotificationProps) => {\n const { top, notification, animated = true } = props;\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-toast-notification\",\n css: toastNotificationCss,\n window: targetWindow,\n });\n\n const [right, setRight] = useState(-toastWidth - toastContainerRightPadding);\n\n useEffect(() => {\n setTimeout(() => setRight(toastContainerRightPadding));\n\n if (animated) {\n setTimeout(\n () => setRight(-toastWidth - toastContainerRightPadding),\n toastDisplayDuration + horizontalTransitionDuration,\n );\n }\n }, [animated]);\n\n return (\n <Portal>\n <div\n className={cx(classBase, `${classBase}-${notification.type}`)}\n style={{\n height: toastHeight,\n right,\n width: toastWidth,\n top,\n transition: animated\n ? `right ${horizontalTransitionDuration}ms, top ${verticalTransitionDuration}ms `\n : \"none\",\n }}\n >\n <Icon name={icon[notification.type]} />\n <div className={`${classBase}-toastContent`}>\n <strong className={`${classBase}-toastHeader`}>\n {notification.header}\n </strong>\n <div>{notification.body}</div>\n </div>\n </div>\n </Portal>\n );\n};\n"],"names":["useWindow","useComponentCssInjection","toastNotificationCss","useState","useEffect","Portal","jsxs","jsx","Icon"],"mappings":";;;;;;;;;;;AAUA,MAAM,UAAa,GAAA,GAAA,CAAA;AACnB,MAAM,0BAA6B,GAAA,EAAA,CAAA;AACnC,MAAM,oBAAuB,GAAA,GAAA,CAAA;AAC7B,MAAM,4BAA+B,GAAA,GAAA,CAAA;AACrC,MAAM,WAAc,GAAA,EAAA,CAAA;AACpB,MAAM,0BAA6B,GAAA,GAAA,CAAA;AAQnC,MAAM,SAAY,GAAA,sBAAA,CAAA;AAElB,MAAM,IAAO,GAAA;AAAA,EACX,KAAO,EAAA,OAAA;AAAA,EACP,IAAM,EAAA,aAAA;AAAA,EACN,OAAS,EAAA,MAAA;AAAA,EACT,OAAS,EAAA,eAAA;AACX,CAAA,CAAA;AAEa,MAAA,iBAAA,GAAoB,CAAC,KAAkC,KAAA;AAClE,EAAA,MAAM,EAAE,GAAA,EAAK,YAAc,EAAA,QAAA,GAAW,MAAS,GAAA,KAAA,CAAA;AAC/C,EAAA,MAAM,eAAeA,gBAAU,EAAA,CAAA;AAC/B,EAAyBC,+BAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,wBAAA;AAAA,IACR,GAAK,EAAAC,mBAAA;AAAA,IACL,MAAQ,EAAA,YAAA;AAAA,GACT,CAAA,CAAA;AAED,EAAA,MAAM,CAAC,KAAO,EAAA,QAAQ,IAAIC,cAAS,CAAA,CAAC,aAAa,0BAA0B,CAAA,CAAA;AAE3E,EAAAC,eAAA,CAAU,MAAM;AACd,IAAW,UAAA,CAAA,MAAM,QAAS,CAAA,0BAA0B,CAAC,CAAA,CAAA;AAErD,IAAA,IAAI,QAAU,EAAA;AACZ,MAAA,UAAA;AAAA,QACE,MAAM,QAAA,CAAS,CAAC,UAAA,GAAa,0BAA0B,CAAA;AAAA,QACvD,oBAAuB,GAAA,4BAAA;AAAA,OACzB,CAAA;AAAA,KACF;AAAA,GACF,EAAG,CAAC,QAAQ,CAAC,CAAA,CAAA;AAEb,EAAA,sCACGC,aACC,EAAA,EAAA,QAAA,kBAAAC,eAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,GAAG,SAAW,EAAA,CAAA,EAAG,SAAS,CAAI,CAAA,EAAA,YAAA,CAAa,IAAI,CAAE,CAAA,CAAA;AAAA,MAC5D,KAAO,EAAA;AAAA,QACL,MAAQ,EAAA,WAAA;AAAA,QACR,KAAA;AAAA,QACA,KAAO,EAAA,UAAA;AAAA,QACP,GAAA;AAAA,QACA,YAAY,QACR,GAAA,CAAA,MAAA,EAAS,4BAA4B,CAAA,QAAA,EAAW,0BAA0B,CAC1E,GAAA,CAAA,GAAA,MAAA;AAAA,OACN;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAAC,cAAA,CAACC,kBAAK,EAAA,EAAA,IAAA,EAAM,IAAK,CAAA,YAAA,CAAa,IAAI,CAAG,EAAA,CAAA;AAAA,wBACpCF,eAAA,CAAA,KAAA,EAAA,EAAI,SAAW,EAAA,CAAA,EAAG,SAAS,CAC1B,aAAA,CAAA,EAAA,QAAA,EAAA;AAAA,0BAAAC,cAAA,CAAC,YAAO,SAAW,EAAA,CAAA,EAAG,SAAS,CAAA,YAAA,CAAA,EAC5B,uBAAa,MAChB,EAAA,CAAA;AAAA,0BACAA,cAAA,CAAC,KAAK,EAAA,EAAA,QAAA,EAAA,YAAA,CAAa,IAAK,EAAA,CAAA;AAAA,SAC1B,EAAA,CAAA;AAAA,OAAA;AAAA,KAAA;AAAA,GAEJ,EAAA,CAAA,CAAA;AAEJ;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Portal.js","sources":["../../src/portal/Portal.tsx"],"sourcesContent":["import { ThemeAttributes, useThemeAttributes } from \"@vuu-ui/vuu-utils\";\nimport { ReactNode, useLayoutEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\n\nimport portalCss from \"./Portal.css\";\n\nexport interface PortalProps {\n /**\n * The children to render into the `container`.\n */\n children?: ReactNode;\n /**\n * An HTML element, component instance, or function that returns either.\n * The `container` will have the portal children appended to it.\n *\n * By default, it uses the body of the top-level document object,\n * so it's simply `document.body` most of the time.\n */\n container?: Element | (() => Element | null) | null;\n /**\n * Id of element into which portal will be rendered. If this node does not exist on the document,\n * it will be created for you. If more than one value is provided, the first element found will\n * be used.\n */\n id?: string | string[];\n /**\n * Callback invoked immediately after render (in layoutEffect). Can be\n * used to check position vis-a-vis viewport and adjust if out of bounds\n */\n onRender?: () => void;\n /**\n * Allow conditional rendering of this Portal, if false, will render nothing.\n * Defaults to true\n */\n open?: boolean;\n /**\n * ThemeAttributes can be passed in for cases where ContextMenu is\n * rendered via popup-service showPopup, outside the Context hierarchy.\n */\n themeAttributes?: ThemeAttributes;\n}\n\nfunction getContainer(container: PortalProps[\"container\"]) {\n return typeof container === \"function\" ? container() : container;\n}\n\nconst DEFAULT_ID = [\"vuu-dialog-portal-root\", \"vuu-portal-root\"];\n\nconst getFirstAvailableElementById = (id: string | string[]) => {\n if (Array.isArray(id)) {\n for (const i of id) {\n const element = document.getElementById(i);\n if (element) {\n return element;\n }\n }\n } else {\n return document.getElementById(id);\n }\n return null;\n};\n\n/**\n * Portals provide a first-class way to render children into a DOM node\n * that exists outside the DOM hierarchy of the parent component.\n */\nexport const Portal = ({\n children,\n container: containerProp = document.body,\n id = DEFAULT_ID,\n onRender,\n open = true,\n themeAttributes,\n}: PortalProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-portal\",\n css: portalCss,\n window: targetWindow,\n });\n\n const [mounted, setMounted] = useState(false);\n const portalRef = useRef<HTMLElement | null>(null);\n const container = getContainer(containerProp) ?? document.body;\n const [themeClass, densityClass, dataMode] =\n useThemeAttributes(themeAttributes);\n\n useLayoutEffect(() => {\n const root = getFirstAvailableElementById(id);\n if (root) {\n portalRef.current = root;\n } else {\n portalRef.current = document.createElement(\"div\");\n portalRef.current.id =\n typeof id === \"string\"\n ? id\n : id.length > 0\n ? (id.at(-1) as string)\n : \"vuu-portal-root\";\n }\n const el = portalRef.current;\n if (!container.contains(el)) {\n container.appendChild(el);\n }\n el.classList.add(themeClass, densityClass);\n el.dataset.mode = dataMode;\n setMounted(true);\n }, [id, container, themeClass, densityClass, dataMode]);\n\n useLayoutEffect(() => {\n requestAnimationFrame(() => {\n onRender?.();\n });\n }, [onRender]);\n\n if (open && mounted && portalRef.current && children) {\n return createPortal(children, portalRef.current);\n }\n\n return null;\n};\n"],"names":["useWindow","useComponentCssInjection","portalCss","useState","useRef","useThemeAttributes","useLayoutEffect","createPortal"],"mappings":"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"}
1
+ {"version":3,"file":"Portal.js","sources":["../../src/portal/Portal.tsx"],"sourcesContent":["import { ThemeAttributes, useThemeAttributes } from \"@vuu-ui/vuu-utils\";\nimport { ReactNode, useLayoutEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\n\nimport portalCss from \"./Portal.css\";\n\nexport interface PortalProps {\n /**\n * The children to render into the `container`.\n */\n children?: ReactNode;\n /**\n * An HTML element, component instance, or function that returns either.\n * The `container` will have the portal children appended to it.\n *\n * By default, it uses the body of the top-level document object,\n * so it's simply `document.body` most of the time.\n */\n container?: Element | (() => Element | null) | null;\n /**\n * Id of element into which portal will be rendered. If this node does not exist on the document,\n * it will be created for you. If more than one value is provided, the first element found will\n * be used.\n */\n id?: string | string[];\n /**\n * Callback invoked immediately after render (in layoutEffect). Can be\n * used to check position vis-a-vis viewport and adjust if out of bounds\n */\n onRender?: () => void;\n /**\n * Allow conditional rendering of this Portal, if false, will render nothing.\n * Defaults to true\n */\n open?: boolean;\n /**\n * ThemeAttributes can be passed in for cases where ContextMenu is\n * rendered via popup-service showPopup, outside the Context hierarchy.\n */\n themeAttributes?: ThemeAttributes;\n}\n\nfunction getContainer(container: PortalProps[\"container\"]) {\n return typeof container === \"function\" ? container() : container;\n}\n\nconst DEFAULT_ID = [\"vuu-dialog-portal-root\", \"vuu-portal-root\"];\n\nconst getFirstAvailableElementById = (id: string | string[]) => {\n if (Array.isArray(id)) {\n for (const i of id) {\n const element = document.getElementById(i);\n if (element) {\n return element;\n }\n }\n } else {\n return document.getElementById(id);\n }\n return null;\n};\n\n/**\n * Portals provide a first-class way to render children into a DOM node\n * that exists outside the DOM hierarchy of the parent component.\n */\nexport const Portal = ({\n children,\n container: containerProp = document.body,\n id = DEFAULT_ID,\n onRender,\n open = true,\n themeAttributes,\n}: PortalProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-portal\",\n css: portalCss,\n window: targetWindow,\n });\n\n const [mounted, setMounted] = useState(false);\n const portalRef = useRef<HTMLElement | null>(null);\n const container = getContainer(containerProp) ?? document.body;\n const [themeClass, densityClass, dataMode] =\n useThemeAttributes(themeAttributes);\n\n useLayoutEffect(() => {\n const root = getFirstAvailableElementById(id);\n if (root) {\n portalRef.current = root;\n } else {\n portalRef.current = document.createElement(\"div\");\n portalRef.current.id =\n typeof id === \"string\"\n ? id\n : id.length > 0\n ? (id.at(-1) as string)\n : \"vuu-portal-root\";\n }\n const el = portalRef.current;\n if (!container.contains(el)) {\n container.appendChild(el);\n }\n el.classList.add(themeClass, densityClass);\n el.dataset.mode = dataMode;\n setMounted(true);\n }, [id, container, themeClass, densityClass, dataMode]);\n\n useLayoutEffect(() => {\n requestAnimationFrame(() => {\n onRender?.();\n });\n }, [onRender]);\n\n if (open && mounted && portalRef.current && children) {\n return createPortal(children, portalRef.current);\n }\n\n return null;\n};\n"],"names":["useWindow","useComponentCssInjection","portalCss","useState","useRef","useThemeAttributes","useLayoutEffect","createPortal"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useTooltip.js","sources":["../../src/tooltip/useTooltip.ts"],"sourcesContent":["import { queryClosest, useId } from \"@vuu-ui/vuu-utils\";\nimport { MouseEvent, ReactNode, useCallback, useRef, useState } from \"react\";\nimport { TooltipProps } from \"./Tooltip\";\nimport { TooltipPlacement } from \"./useTooltipAnchoredPosition\";\n\nexport interface TooltipHookProps {\n anchorQuery?: string;\n id: string;\n placement?: TooltipPlacement | TooltipPlacement[];\n tooltipContent: ReactNode;\n}\n\nexport const useTooltip = ({\n anchorQuery = \"*\",\n id: idProp,\n placement = [\"right\", \"above\", \"below\"],\n tooltipContent,\n}: TooltipHookProps) => {\n const hideTooltipRef = useRef<() => void>();\n const isHoveringRef = useRef(false);\n const anchorElementRef = useRef<HTMLElement | null>(null);\n const mouseEnterTimerRef = useRef<number | undefined>();\n const mouseLeaveTimerRef = useRef<number | undefined>();\n const [tooltipProps, setTooltipProps] = useState<TooltipProps | undefined>();\n\n const id = useId(idProp);\n\n const escapeListener = useCallback((evt: KeyboardEvent) => {\n if (evt.key === \"Escape\") {\n hideTooltipRef.current?.();\n }\n }, []);\n\n hideTooltipRef.current = useCallback(() => {\n setTooltipProps(undefined);\n document.removeEventListener(\"keydown\", escapeListener);\n }, [escapeListener]);\n\n const handleMouseEnterTooltip = useCallback(() => {\n window.clearTimeout(mouseLeaveTimerRef.current);\n }, []);\n\n const handleMouseLeaveTooltip = useCallback(() => {\n hideTooltipRef.current?.();\n }, []);\n\n const hideTooltip = useCallback((defer = 0) => {\n if (mouseEnterTimerRef.current) {\n window.clearTimeout(mouseEnterTimerRef.current);\n mouseEnterTimerRef.current = undefined;\n } else if (hideTooltipRef.current) {\n if (defer === 0) {\n hideTooltipRef.current();\n } else {\n mouseLeaveTimerRef.current = window.setTimeout(\n hideTooltipRef.current,\n defer\n );\n }\n }\n }, []);\n\n const showTooltip = useCallback(\n (ref = anchorElementRef) => {\n const { current: anchorEl } = ref;\n if (anchorEl) {\n setTooltipProps({\n anchorElement: ref,\n children: tooltipContent,\n id: `${id}-tooltip`,\n onMouseEnter: handleMouseEnterTooltip,\n onMouseLeave: handleMouseLeaveTooltip,\n placement: placement,\n });\n // register ESC listener\n document.addEventListener(\"keydown\", escapeListener);\n }\n mouseEnterTimerRef.current = undefined;\n hideTooltip(isHoveringRef.current ? 3000 : 1000);\n },\n [\n escapeListener,\n handleMouseEnterTooltip,\n handleMouseLeaveTooltip,\n hideTooltip,\n id,\n placement,\n tooltipContent,\n ]\n );\n\n const handleMouseEnter = useCallback(\n (evt: MouseEvent) => {\n isHoveringRef.current = true;\n const el = queryClosest(evt.target, anchorQuery);\n if (el) {\n console.log(`el ${el.classList}`);\n anchorElementRef.current = el;\n mouseEnterTimerRef.current = window.setTimeout(showTooltip, 800);\n }\n },\n [anchorQuery, showTooltip]\n );\n\n const handleMouseLeave = useCallback(() => {\n isHoveringRef.current = false;\n hideTooltip(200);\n }, [hideTooltip]);\n\n const anchorProps = {\n \"aria-describedby\": `${id}-tooltip`,\n onMouseEnter: handleMouseEnter,\n onMouseLeave: handleMouseLeave,\n };\n\n return {\n anchorProps,\n hideTooltip,\n showTooltip,\n tooltipProps,\n };\n};\n"],"names":["useRef","useState","useId","useCallback","queryClosest"],"mappings":"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"}
1
+ {"version":3,"file":"useTooltip.js","sources":["../../src/tooltip/useTooltip.ts"],"sourcesContent":["import { queryClosest, useId } from \"@vuu-ui/vuu-utils\";\nimport { MouseEvent, ReactNode, useCallback, useRef, useState } from \"react\";\nimport { TooltipProps } from \"./Tooltip\";\nimport { TooltipPlacement } from \"./useTooltipAnchoredPosition\";\n\nexport interface TooltipHookProps {\n anchorQuery?: string;\n id: string;\n placement?: TooltipPlacement | TooltipPlacement[];\n tooltipContent: ReactNode;\n}\n\nexport const useTooltip = ({\n anchorQuery = \"*\",\n id: idProp,\n placement = [\"right\", \"above\", \"below\"],\n tooltipContent,\n}: TooltipHookProps) => {\n const hideTooltipRef = useRef<() => void>();\n const isHoveringRef = useRef(false);\n const anchorElementRef = useRef<HTMLElement | null>(null);\n const mouseEnterTimerRef = useRef<number | undefined>();\n const mouseLeaveTimerRef = useRef<number | undefined>();\n const [tooltipProps, setTooltipProps] = useState<TooltipProps | undefined>();\n\n const id = useId(idProp);\n\n const escapeListener = useCallback((evt: KeyboardEvent) => {\n if (evt.key === \"Escape\") {\n hideTooltipRef.current?.();\n }\n }, []);\n\n hideTooltipRef.current = useCallback(() => {\n setTooltipProps(undefined);\n document.removeEventListener(\"keydown\", escapeListener);\n }, [escapeListener]);\n\n const handleMouseEnterTooltip = useCallback(() => {\n window.clearTimeout(mouseLeaveTimerRef.current);\n }, []);\n\n const handleMouseLeaveTooltip = useCallback(() => {\n hideTooltipRef.current?.();\n }, []);\n\n const hideTooltip = useCallback((defer = 0) => {\n if (mouseEnterTimerRef.current) {\n window.clearTimeout(mouseEnterTimerRef.current);\n mouseEnterTimerRef.current = undefined;\n } else if (hideTooltipRef.current) {\n if (defer === 0) {\n hideTooltipRef.current();\n } else {\n mouseLeaveTimerRef.current = window.setTimeout(\n hideTooltipRef.current,\n defer,\n );\n }\n }\n }, []);\n\n const showTooltip = useCallback(\n (ref = anchorElementRef) => {\n const { current: anchorEl } = ref;\n if (anchorEl) {\n setTooltipProps({\n anchorElement: ref,\n children: tooltipContent,\n id: `${id}-tooltip`,\n onMouseEnter: handleMouseEnterTooltip,\n onMouseLeave: handleMouseLeaveTooltip,\n placement: placement,\n });\n // register ESC listener\n document.addEventListener(\"keydown\", escapeListener);\n }\n mouseEnterTimerRef.current = undefined;\n hideTooltip(isHoveringRef.current ? 3000 : 1000);\n },\n [\n escapeListener,\n handleMouseEnterTooltip,\n handleMouseLeaveTooltip,\n hideTooltip,\n id,\n placement,\n tooltipContent,\n ],\n );\n\n const handleMouseEnter = useCallback(\n (evt: MouseEvent) => {\n isHoveringRef.current = true;\n const el = queryClosest(evt.target, anchorQuery);\n if (el) {\n console.log(`el ${el.classList}`);\n anchorElementRef.current = el;\n mouseEnterTimerRef.current = window.setTimeout(showTooltip, 800);\n }\n },\n [anchorQuery, showTooltip],\n );\n\n const handleMouseLeave = useCallback(() => {\n isHoveringRef.current = false;\n hideTooltip(200);\n }, [hideTooltip]);\n\n const anchorProps = {\n \"aria-describedby\": `${id}-tooltip`,\n onMouseEnter: handleMouseEnter,\n onMouseLeave: handleMouseLeave,\n };\n\n return {\n anchorProps,\n hideTooltip,\n showTooltip,\n tooltipProps,\n };\n};\n"],"names":["useRef","useState","useId","useCallback","queryClosest"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ContextMenu.js","sources":["../../src/menu/ContextMenu.tsx"],"sourcesContent":["import { useId } from \"@vuu-ui/vuu-utils\";\nimport { useCallback, useRef } from \"react\";\nimport { PopupCloseCallback, PopupComponent } from \"../popup\";\nimport { Portal, PortalProps } from \"../portal\";\nimport { MenuList, MenuListProps } from \"./MenuList\";\nimport { useCascade } from \"./use-cascade\";\nimport { useItemsWithIdsNext } from \"./use-items-with-ids-next\";\nimport { MenuCloseHandler } from \"./use-keyboard-navigation\";\nimport { ContextMenuOptions } from \"./useContextMenu\";\n\nexport interface ContextMenuProps extends Omit<MenuListProps, \"onCloseMenu\"> {\n PortalProps?: Partial<PortalProps>;\n onClose?: PopupCloseCallback;\n position?: { x: number; y: number };\n withPortal?: boolean;\n}\n\nconst noop = () => undefined;\n\nexport const ContextMenu = ({\n PortalProps,\n activatedByKeyboard,\n children: childrenProp,\n className,\n id: idProp,\n onClose = () => undefined,\n position = { x: 0, y: 0 },\n style,\n ...menuListProps\n}: ContextMenuProps) => {\n const id = useId(idProp);\n const closeMenuRef = useRef<(location?: string) => void>(noop);\n const [menus, actions] = useItemsWithIdsNext(childrenProp, id);\n const navigatingWithKeyboard = useRef(activatedByKeyboard);\n const handleMouseEnterItem = useCallback(() => {\n navigatingWithKeyboard.current = false;\n }, []);\n\n const handleActivate = useCallback(\n (menuItemId: string) => {\n const actionId = menuItemId.slice(9);\n const { action, options } = actions[actionId];\n closeMenuRef.current(id);\n onClose({\n type: \"menu-action\",\n menuId: action,\n options: options as ContextMenuOptions,\n });\n },\n [actions, id, onClose]\n );\n\n const {\n closeMenu,\n listItemProps,\n openMenu: onOpenMenu,\n openMenus,\n handleRender,\n } = useCascade({\n // FIXME\n id: `${id}`,\n onActivate: handleActivate,\n onMouseEnterItem: handleMouseEnterItem,\n position,\n });\n closeMenuRef.current = closeMenu;\n\n const handleCloseMenu = useCallback<MenuCloseHandler>(\n (evt, reason) => {\n navigatingWithKeyboard.current = true;\n closeMenu();\n if (reason === \"tab-away\") {\n // TODO we should fire onclose whenever we're closing\n // the root menu, not just on Tab\n onClose({\n event: evt,\n type: \"tab-away\",\n });\n }\n },\n [closeMenu, onClose]\n );\n\n const handleHighlightMenuItem = () => {\n // console.log(`highlight ${idx}`);\n };\n\n const lastMenu = openMenus.length - 1;\n\n const getChildMenuId = (i: number) => {\n if (i >= lastMenu) {\n return undefined;\n } else {\n const { id } = openMenus[i + 1];\n return id;\n }\n };\n\n return (\n <>\n {openMenus.map(({ id: menuId, left, top }, i, all) => {\n const childMenuId = getChildMenuId(i);\n return (\n <Portal {...PortalProps} key={i} onRender={handleRender}>\n <PopupComponent\n anchorElement={{ current: document.body }}\n placement=\"absolute\"\n position={{ left, top }}\n >\n <MenuList\n {...menuListProps}\n activatedByKeyboard={navigatingWithKeyboard.current}\n childMenuShowing={childMenuId}\n className={className}\n id={menuId}\n isRoot={i === 0}\n key={i}\n listItemProps={listItemProps}\n onActivate={handleActivate}\n onHighlightMenuItem={handleHighlightMenuItem}\n onCloseMenu={handleCloseMenu}\n openMenu={onOpenMenu}\n style={style}\n tabIndex={i === all.length - 1 ? 0 : undefined}\n >\n {menus[menuId]}\n </MenuList>\n </PopupComponent>\n </Portal>\n );\n })}\n </>\n );\n};\n\nContextMenu.displayName = \"ContextMenu\";\n"],"names":["PortalProps","id"],"mappings":"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"}
1
+ {"version":3,"file":"ContextMenu.js","sources":["../../src/menu/ContextMenu.tsx"],"sourcesContent":["import { useId } from \"@vuu-ui/vuu-utils\";\nimport { useCallback, useRef } from \"react\";\nimport { PopupCloseCallback, PopupComponent } from \"../popup\";\nimport { Portal, PortalProps } from \"../portal\";\nimport { MenuList, MenuListProps } from \"./MenuList\";\nimport { useCascade } from \"./use-cascade\";\nimport { useItemsWithIdsNext } from \"./use-items-with-ids-next\";\nimport { MenuCloseHandler } from \"./use-keyboard-navigation\";\nimport { ContextMenuOptions } from \"./useContextMenu\";\n\nexport interface ContextMenuProps extends Omit<MenuListProps, \"onCloseMenu\"> {\n PortalProps?: Partial<PortalProps>;\n onClose?: PopupCloseCallback;\n position?: { x: number; y: number };\n withPortal?: boolean;\n}\n\nconst noop = () => undefined;\n\nexport const ContextMenu = ({\n PortalProps,\n activatedByKeyboard,\n children: childrenProp,\n className,\n id: idProp,\n onClose = () => undefined,\n position = { x: 0, y: 0 },\n style,\n ...menuListProps\n}: ContextMenuProps) => {\n const id = useId(idProp);\n const closeMenuRef = useRef<(location?: string) => void>(noop);\n const [menus, actions] = useItemsWithIdsNext(childrenProp, id);\n const navigatingWithKeyboard = useRef(activatedByKeyboard);\n const handleMouseEnterItem = useCallback(() => {\n navigatingWithKeyboard.current = false;\n }, []);\n\n const handleActivate = useCallback(\n (menuItemId: string) => {\n const actionId = menuItemId.slice(9);\n const { action, options } = actions[actionId];\n closeMenuRef.current(id);\n onClose({\n type: \"menu-action\",\n menuId: action,\n options: options as ContextMenuOptions,\n });\n },\n [actions, id, onClose],\n );\n\n const {\n closeMenu,\n listItemProps,\n openMenu: onOpenMenu,\n openMenus,\n handleRender,\n } = useCascade({\n // FIXME\n id: `${id}`,\n onActivate: handleActivate,\n onMouseEnterItem: handleMouseEnterItem,\n position,\n });\n closeMenuRef.current = closeMenu;\n\n const handleCloseMenu = useCallback<MenuCloseHandler>(\n (evt, reason) => {\n navigatingWithKeyboard.current = true;\n closeMenu();\n if (reason === \"tab-away\") {\n // TODO we should fire onclose whenever we're closing\n // the root menu, not just on Tab\n onClose({\n event: evt,\n type: \"tab-away\",\n });\n }\n },\n [closeMenu, onClose],\n );\n\n const handleHighlightMenuItem = () => {\n // console.log(`highlight ${idx}`);\n };\n\n const lastMenu = openMenus.length - 1;\n\n const getChildMenuId = (i: number) => {\n if (i >= lastMenu) {\n return undefined;\n } else {\n const { id } = openMenus[i + 1];\n return id;\n }\n };\n\n return (\n <>\n {openMenus.map(({ id: menuId, left, top }, i, all) => {\n const childMenuId = getChildMenuId(i);\n return (\n <Portal {...PortalProps} key={i} onRender={handleRender}>\n <PopupComponent\n anchorElement={{ current: document.body }}\n placement=\"absolute\"\n position={{ left, top }}\n >\n <MenuList\n {...menuListProps}\n activatedByKeyboard={navigatingWithKeyboard.current}\n childMenuShowing={childMenuId}\n className={className}\n id={menuId}\n isRoot={i === 0}\n key={i}\n listItemProps={listItemProps}\n onActivate={handleActivate}\n onHighlightMenuItem={handleHighlightMenuItem}\n onCloseMenu={handleCloseMenu}\n openMenu={onOpenMenu}\n style={style}\n tabIndex={i === all.length - 1 ? 0 : undefined}\n >\n {menus[menuId]}\n </MenuList>\n </PopupComponent>\n </Portal>\n );\n })}\n </>\n );\n};\n\nContextMenu.displayName = \"ContextMenu\";\n"],"names":["PortalProps","id"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"MenuList.js","sources":["../../src/menu/MenuList.tsx"],"sourcesContent":["import cx from \"clsx\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport React, {\n FC,\n HTMLAttributes,\n ReactElement,\n ReactNode,\n useLayoutEffect,\n useMemo,\n useRef,\n} from \"react\";\n//TODO do we want this dependency ?\nimport { useId } from \"@vuu-ui/vuu-utils\";\nimport {\n MenuCloseHandler,\n useKeyboardNavigation,\n} from \"./use-keyboard-navigation\";\n\nimport menuListCss from \"./MenuList.css\";\n\nconst classBase = \"vuuMenuList\";\n\nexport const Separator = () => <li className=\"vuuMenuItem-divider\" />;\n\nexport const isMenuItemGroup = (child: ReactElement) =>\n child.type === MenuItemGroup || !!child.props[\"data-group\"];\n\nexport interface MenuItemGroupProps {\n children:\n | ReactElement<MenuItemProps>[]\n | [ReactElement<MenuItemLabelProps>, ...ReactElement<MenuItemProps>[]];\n label?: string;\n}\n\nexport interface MenuItemProps extends HTMLAttributes<HTMLDivElement> {\n action?: string;\n idx?: number;\n options?: unknown;\n}\n\n// Purely used as markers, props will be extracted\nexport const MenuItemGroup: FC<MenuItemGroupProps> = () => null;\n// eslint-disable-next-line no-unused-vars\nexport const MenuItem = ({\n children,\n idx,\n options,\n ...props\n}: MenuItemProps) => {\n return <div {...props}>{children}</div>;\n};\n\nexport interface MenuItemLabelProps {\n children: ReactNode;\n}\nconst MenuItemLabel = ({ children }: { children: ReactNode }) => (\n <>{children}</>\n);\nMenuItemLabel.displayName = \"MenuItemLabel\";\nMenuItem.Label = MenuItemLabel;\n\nconst getDisplayName = (item: ReactNode) =>\n React.isValidElement(item) &&\n typeof item.type !== \"string\" &&\n \"displayName\" in item.type\n ? item.type.displayName\n : undefined;\n\nexport const isMenuItemLabel = (\n item: ReactNode\n): item is ReactElement<MenuItemLabelProps> =>\n getDisplayName(item) === \"MenuItemLabel\";\n\nconst hasIcon = (child: ReactElement) => child.props[\"data-icon\"];\n\nexport type MenuOpenHandler = (\n menuItemEl: HTMLElement,\n immediate?: boolean\n) => void;\nexport interface MenuListProps extends HTMLAttributes<HTMLDivElement> {\n activatedByKeyboard?: boolean;\n children: ReactElement[];\n childMenuShowing?: string;\n defaultHighlightedIdx?: number;\n highlightedIdx?: number;\n isRoot?: boolean;\n listItemProps?: Partial<MenuItemProps>;\n onActivate?: (menuId: string) => void;\n onCloseMenu: MenuCloseHandler;\n openMenu?: MenuOpenHandler;\n onHighlightMenuItem?: (idx: number) => void;\n}\n\nexport const MenuList = ({\n activatedByKeyboard,\n childMenuShowing,\n children,\n className,\n defaultHighlightedIdx,\n highlightedIdx: highlightedIdxProp,\n id: idProp,\n isRoot,\n listItemProps,\n onHighlightMenuItem,\n onActivate,\n onCloseMenu,\n openMenu: onOpenMenu,\n ...props\n}: MenuListProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-menu-list\",\n css: menuListCss,\n window: targetWindow,\n });\n\n const id = useId(idProp);\n const root = useRef<HTMLDivElement>(null);\n\n // The id generation be,ongs in useIttemsWithIds\n const mapIdxToId = useMemo(() => new Map(), []);\n\n const handleActivate = (idx: number) => {\n const el = root.current?.querySelector(`:scope > [data-index='${idx}']`);\n el?.id && onActivate?.(el.id);\n };\n\n const { focusVisible, highlightedIndex, listProps } = useKeyboardNavigation({\n count: React.Children.count(children),\n defaultHighlightedIdx,\n highlightedIndex: highlightedIdxProp,\n onActivate: handleActivate,\n onHighlight: onHighlightMenuItem,\n onOpenMenu,\n onCloseMenu,\n });\n\n const appliedFocusVisible = childMenuShowing == undefined ? focusVisible : -1;\n\n useLayoutEffect(() => {\n if (childMenuShowing === undefined && activatedByKeyboard) {\n root.current?.focus();\n }\n }, [activatedByKeyboard, childMenuShowing]);\n\n const getActiveDescendant = () =>\n highlightedIndex === undefined || highlightedIndex === -1\n ? undefined\n : mapIdxToId.get(highlightedIndex);\n\n function renderContent() {\n const propsCommonToAllListItems = {\n ...listItemProps,\n role: \"menuitem\",\n };\n\n const maybeIcon = (\n childElement: ReactElement,\n withIcon: boolean,\n iconName?: string\n ) =>\n withIcon\n ? [\n <span\n className=\"vuuIconContainer\"\n data-icon={iconName}\n key=\"icon\"\n />,\n ].concat(childElement)\n : childElement;\n\n function addClonedChild(\n list: ReactElement[],\n child: ReactElement,\n idx: number,\n withIcon: boolean\n ) {\n const {\n children,\n className,\n \"data-icon\": iconName,\n id: itemId,\n hasSeparator,\n label,\n ...props\n } = child.props;\n const hasSubMenu = isMenuItemGroup(child);\n const subMenuShowing = hasSubMenu && childMenuShowing === itemId;\n const ariaControls = subMenuShowing ? `${id}-${itemId}` : undefined;\n\n const ariaLabel =\n label ?? typeof children === \"string\" ? children : undefined;\n\n list.push(\n <MenuItem\n {...props}\n {...propsCommonToAllListItems}\n {...getMenuItemProps(\n itemId,\n idx,\n child.key ?? itemId,\n highlightedIndex,\n appliedFocusVisible,\n className,\n hasSeparator\n )}\n aria-controls={ariaControls}\n aria-haspopup={hasSubMenu || undefined}\n aria-expanded={subMenuShowing || undefined}\n aria-label={ariaLabel}\n >\n {hasSubMenu\n ? maybeIcon(label ?? children, withIcon, iconName)\n : maybeIcon(children, withIcon, iconName)}\n </MenuItem>\n );\n // mapIdxToId.set(idx, itemId);\n }\n\n const listItems: ReactElement[] = [];\n\n if (children.length > 0) {\n const withIcon = children.some(hasIcon);\n children.forEach((child, idx) => {\n addClonedChild(listItems, child, idx, withIcon);\n });\n }\n\n return listItems;\n }\n\n return (\n <div\n {...props}\n {...listProps}\n aria-activedescendant={getActiveDescendant()}\n className={cx(classBase, className, {\n [`${classBase}-childMenuShowing`]: childMenuShowing !== undefined,\n })}\n data-root={isRoot || undefined}\n id={id}\n ref={root}\n role=\"menu\"\n >\n {renderContent()}\n </div>\n );\n};\n\nconst getMenuItemProps = (\n itemId: string,\n idx: number,\n key: string,\n highlightedIdx: number,\n focusVisible: number,\n className: string,\n hasSeparator: boolean\n) => ({\n id: `menuitem-${itemId}`,\n key: key ?? idx,\n \"data-index\": idx,\n className: cx(\"vuuMenuItem\", className, {\n \"vuuMenuItem-separator\": hasSeparator,\n vuuHighlighted: idx === highlightedIdx,\n focusVisible: focusVisible === idx,\n }),\n});\n\nMenuList.displayName = \"MenuList\";\n"],"names":["children","className","props"],"mappings":"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"}
1
+ {"version":3,"file":"MenuList.js","sources":["../../src/menu/MenuList.tsx"],"sourcesContent":["import cx from \"clsx\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport React, {\n FC,\n HTMLAttributes,\n ReactElement,\n ReactNode,\n useLayoutEffect,\n useMemo,\n useRef,\n} from \"react\";\n//TODO do we want this dependency ?\nimport { useId } from \"@vuu-ui/vuu-utils\";\nimport {\n MenuCloseHandler,\n useKeyboardNavigation,\n} from \"./use-keyboard-navigation\";\n\nimport menuListCss from \"./MenuList.css\";\n\nconst classBase = \"vuuMenuList\";\n\nexport const Separator = () => <li className=\"vuuMenuItem-divider\" />;\n\nexport const isMenuItemGroup = (child: ReactElement) =>\n child.type === MenuItemGroup || !!child.props[\"data-group\"];\n\nexport interface MenuItemGroupProps {\n children:\n | ReactElement<MenuItemProps>[]\n | [ReactElement<MenuItemLabelProps>, ...ReactElement<MenuItemProps>[]];\n label?: string;\n}\n\nexport interface MenuItemProps extends HTMLAttributes<HTMLDivElement> {\n action?: string;\n idx?: number;\n options?: unknown;\n}\n\n// Purely used as markers, props will be extracted\nexport const MenuItemGroup: FC<MenuItemGroupProps> = () => null;\n// eslint-disable-next-line no-unused-vars\nexport const MenuItem = ({\n children,\n idx,\n options,\n ...props\n}: MenuItemProps) => {\n return <div {...props}>{children}</div>;\n};\n\nexport interface MenuItemLabelProps {\n children: ReactNode;\n}\nconst MenuItemLabel = ({ children }: { children: ReactNode }) => (\n <>{children}</>\n);\nMenuItemLabel.displayName = \"MenuItemLabel\";\nMenuItem.Label = MenuItemLabel;\n\nconst getDisplayName = (item: ReactNode) =>\n React.isValidElement(item) &&\n typeof item.type !== \"string\" &&\n \"displayName\" in item.type\n ? item.type.displayName\n : undefined;\n\nexport const isMenuItemLabel = (\n item: ReactNode,\n): item is ReactElement<MenuItemLabelProps> =>\n getDisplayName(item) === \"MenuItemLabel\";\n\nconst hasIcon = (child: ReactElement) => child.props[\"data-icon\"];\n\nexport type MenuOpenHandler = (\n menuItemEl: HTMLElement,\n immediate?: boolean,\n) => void;\nexport interface MenuListProps extends HTMLAttributes<HTMLDivElement> {\n activatedByKeyboard?: boolean;\n children: ReactElement[];\n childMenuShowing?: string;\n defaultHighlightedIdx?: number;\n highlightedIdx?: number;\n isRoot?: boolean;\n listItemProps?: Partial<MenuItemProps>;\n onActivate?: (menuId: string) => void;\n onCloseMenu: MenuCloseHandler;\n openMenu?: MenuOpenHandler;\n onHighlightMenuItem?: (idx: number) => void;\n}\n\nexport const MenuList = ({\n activatedByKeyboard,\n childMenuShowing,\n children,\n className,\n defaultHighlightedIdx,\n highlightedIdx: highlightedIdxProp,\n id: idProp,\n isRoot,\n listItemProps,\n onHighlightMenuItem,\n onActivate,\n onCloseMenu,\n openMenu: onOpenMenu,\n ...props\n}: MenuListProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-menu-list\",\n css: menuListCss,\n window: targetWindow,\n });\n\n const id = useId(idProp);\n const root = useRef<HTMLDivElement>(null);\n\n // The id generation be,ongs in useIttemsWithIds\n const mapIdxToId = useMemo(() => new Map(), []);\n\n const handleActivate = (idx: number) => {\n const el = root.current?.querySelector(`:scope > [data-index='${idx}']`);\n el?.id && onActivate?.(el.id);\n };\n\n const { focusVisible, highlightedIndex, listProps } = useKeyboardNavigation({\n count: React.Children.count(children),\n defaultHighlightedIdx,\n highlightedIndex: highlightedIdxProp,\n onActivate: handleActivate,\n onHighlight: onHighlightMenuItem,\n onOpenMenu,\n onCloseMenu,\n });\n\n const appliedFocusVisible = childMenuShowing == undefined ? focusVisible : -1;\n\n useLayoutEffect(() => {\n if (childMenuShowing === undefined && activatedByKeyboard) {\n root.current?.focus();\n }\n }, [activatedByKeyboard, childMenuShowing]);\n\n const getActiveDescendant = () =>\n highlightedIndex === undefined || highlightedIndex === -1\n ? undefined\n : mapIdxToId.get(highlightedIndex);\n\n function renderContent() {\n const propsCommonToAllListItems = {\n ...listItemProps,\n role: \"menuitem\",\n };\n\n const maybeIcon = (\n childElement: ReactElement,\n withIcon: boolean,\n iconName?: string,\n ) =>\n withIcon\n ? [\n <span\n className=\"vuuIconContainer\"\n data-icon={iconName}\n key=\"icon\"\n />,\n ].concat(childElement)\n : childElement;\n\n function addClonedChild(\n list: ReactElement[],\n child: ReactElement,\n idx: number,\n withIcon: boolean,\n ) {\n const {\n children,\n className,\n \"data-icon\": iconName,\n id: itemId,\n hasSeparator,\n label,\n ...props\n } = child.props;\n const hasSubMenu = isMenuItemGroup(child);\n const subMenuShowing = hasSubMenu && childMenuShowing === itemId;\n const ariaControls = subMenuShowing ? `${id}-${itemId}` : undefined;\n\n const ariaLabel =\n (label ?? typeof children === \"string\") ? children : undefined;\n\n list.push(\n <MenuItem\n {...props}\n {...propsCommonToAllListItems}\n {...getMenuItemProps(\n itemId,\n idx,\n child.key ?? itemId,\n highlightedIndex,\n appliedFocusVisible,\n className,\n hasSeparator,\n )}\n aria-controls={ariaControls}\n aria-haspopup={hasSubMenu || undefined}\n aria-expanded={subMenuShowing || undefined}\n aria-label={ariaLabel}\n >\n {hasSubMenu\n ? maybeIcon(label ?? children, withIcon, iconName)\n : maybeIcon(children, withIcon, iconName)}\n </MenuItem>,\n );\n // mapIdxToId.set(idx, itemId);\n }\n\n const listItems: ReactElement[] = [];\n\n if (children.length > 0) {\n const withIcon = children.some(hasIcon);\n children.forEach((child, idx) => {\n addClonedChild(listItems, child, idx, withIcon);\n });\n }\n\n return listItems;\n }\n\n return (\n <div\n {...props}\n {...listProps}\n aria-activedescendant={getActiveDescendant()}\n className={cx(classBase, className, {\n [`${classBase}-childMenuShowing`]: childMenuShowing !== undefined,\n })}\n data-root={isRoot || undefined}\n id={id}\n ref={root}\n role=\"menu\"\n >\n {renderContent()}\n </div>\n );\n};\n\nconst getMenuItemProps = (\n itemId: string,\n idx: number,\n key: string,\n highlightedIdx: number,\n focusVisible: number,\n className: string,\n hasSeparator: boolean,\n) => ({\n id: `menuitem-${itemId}`,\n key: key ?? idx,\n \"data-index\": idx,\n className: cx(\"vuuMenuItem\", className, {\n \"vuuMenuItem-separator\": hasSeparator,\n vuuHighlighted: idx === highlightedIdx,\n focusVisible: focusVisible === idx,\n }),\n});\n\nMenuList.displayName = \"MenuList\";\n"],"names":["children","className","props"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"context-menu-provider.js","sources":["../../src/menu/context-menu-provider.tsx"],"sourcesContent":["import type {\n ContextMenuContextType,\n MenuActionHandler,\n MenuBuilder,\n} from \"@vuu-ui/vuu-data-types\";\nimport { createContext, ReactNode, useCallback, useMemo } from \"react\";\n\nexport const ContextMenuContext = createContext<ContextMenuContextType | null>(\n null\n);\n\nexport interface ContextMenuConfiguration {\n menuActionHandler?: MenuActionHandler;\n menuBuilder: MenuBuilder;\n}\n\nexport interface ContextMenuProviderProps extends ContextMenuConfiguration {\n children: ReactNode;\n label?: string;\n}\n\ninterface ProviderProps extends ContextMenuProviderProps {\n context: ContextMenuContextType | null;\n}\n\nconst Provider = ({\n children,\n context,\n menuActionHandler,\n menuBuilder,\n}: ProviderProps) => {\n const menuBuilders = useMemo(() => {\n if (context?.menuBuilders && menuBuilder) {\n return context.menuBuilders.concat(menuBuilder);\n } else if (menuBuilder) {\n return [menuBuilder];\n } else {\n return context?.menuBuilders || [];\n }\n }, [context, menuBuilder]);\n\n const handleMenuAction = useCallback(\n (reason) => {\n if (menuActionHandler?.(reason)) {\n return true;\n }\n\n if (context?.menuActionHandler?.(reason)) {\n return true;\n }\n },\n [context, menuActionHandler]\n );\n\n return (\n <ContextMenuContext.Provider\n value={{\n menuActionHandler: handleMenuAction,\n menuBuilders,\n }}\n >\n {children}\n </ContextMenuContext.Provider>\n );\n};\n\n// Need an option for local menu to override higher-level menu, rather than extend\nexport const ContextMenuProvider = ({\n children,\n label,\n menuActionHandler,\n menuBuilder,\n}: ContextMenuProviderProps) => {\n return (\n <ContextMenuContext.Consumer>\n {(parentContext) => (\n <Provider\n context={parentContext}\n label={label}\n menuActionHandler={menuActionHandler}\n menuBuilder={menuBuilder}\n >\n {children}\n </Provider>\n )}\n </ContextMenuContext.Consumer>\n );\n};\n"],"names":[],"mappings":";;;AAOO,MAAM,kBAAqB,GAAA,aAAA;AAAA,EAChC,IAAA;AACF,EAAA;AAgBA,MAAM,WAAW,CAAC;AAAA,EAChB,QAAA;AAAA,EACA,OAAA;AAAA,EACA,iBAAA;AAAA,EACA,WAAA;AACF,CAAqB,KAAA;AACnB,EAAM,MAAA,YAAA,GAAe,QAAQ,MAAM;AACjC,IAAI,IAAA,OAAA,EAAS,gBAAgB,WAAa,EAAA;AACxC,MAAO,OAAA,OAAA,CAAQ,YAAa,CAAA,MAAA,CAAO,WAAW,CAAA,CAAA;AAAA,eACrC,WAAa,EAAA;AACtB,MAAA,OAAO,CAAC,WAAW,CAAA,CAAA;AAAA,KACd,MAAA;AACL,MAAO,OAAA,OAAA,EAAS,gBAAgB,EAAC,CAAA;AAAA,KACnC;AAAA,GACC,EAAA,CAAC,OAAS,EAAA,WAAW,CAAC,CAAA,CAAA;AAEzB,EAAA,MAAM,gBAAmB,GAAA,WAAA;AAAA,IACvB,CAAC,MAAW,KAAA;AACV,MAAI,IAAA,iBAAA,GAAoB,MAAM,CAAG,EAAA;AAC/B,QAAO,OAAA,IAAA,CAAA;AAAA,OACT;AAEA,MAAI,IAAA,OAAA,EAAS,iBAAoB,GAAA,MAAM,CAAG,EAAA;AACxC,QAAO,OAAA,IAAA,CAAA;AAAA,OACT;AAAA,KACF;AAAA,IACA,CAAC,SAAS,iBAAiB,CAAA;AAAA,GAC7B,CAAA;AAEA,EACE,uBAAA,GAAA;AAAA,IAAC,kBAAmB,CAAA,QAAA;AAAA,IAAnB;AAAA,MACC,KAAO,EAAA;AAAA,QACL,iBAAmB,EAAA,gBAAA;AAAA,QACnB,YAAA;AAAA,OACF;AAAA,MAEC,QAAA;AAAA,KAAA;AAAA,GACH,CAAA;AAEJ,CAAA,CAAA;AAGO,MAAM,sBAAsB,CAAC;AAAA,EAClC,QAAA;AAAA,EACA,KAAA;AAAA,EACA,iBAAA;AAAA,EACA,WAAA;AACF,CAAgC,KAAA;AAC9B,EAAA,uBACG,GAAA,CAAA,kBAAA,CAAmB,QAAnB,EAAA,EACE,WAAC,aACA,qBAAA,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,OAAS,EAAA,aAAA;AAAA,MACT,KAAA;AAAA,MACA,iBAAA;AAAA,MACA,WAAA;AAAA,MAEC,QAAA;AAAA,KAAA;AAAA,GAGP,EAAA,CAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"context-menu-provider.js","sources":["../../src/menu/context-menu-provider.tsx"],"sourcesContent":["import type {\n ContextMenuContextType,\n MenuActionHandler,\n MenuBuilder,\n} from \"@vuu-ui/vuu-data-types\";\nimport { createContext, ReactNode, useCallback, useMemo } from \"react\";\n\nexport const ContextMenuContext = createContext<ContextMenuContextType | null>(\n null,\n);\n\nexport interface ContextMenuConfiguration {\n menuActionHandler?: MenuActionHandler;\n menuBuilder: MenuBuilder;\n}\n\nexport interface ContextMenuProviderProps extends ContextMenuConfiguration {\n children: ReactNode;\n label?: string;\n}\n\ninterface ProviderProps extends ContextMenuProviderProps {\n context: ContextMenuContextType | null;\n}\n\nconst Provider = ({\n children,\n context,\n menuActionHandler,\n menuBuilder,\n}: ProviderProps) => {\n const menuBuilders = useMemo(() => {\n if (context?.menuBuilders && menuBuilder) {\n return context.menuBuilders.concat(menuBuilder);\n } else if (menuBuilder) {\n return [menuBuilder];\n } else {\n return context?.menuBuilders || [];\n }\n }, [context, menuBuilder]);\n\n const handleMenuAction = useCallback(\n (reason) => {\n if (menuActionHandler?.(reason)) {\n return true;\n }\n\n if (context?.menuActionHandler?.(reason)) {\n return true;\n }\n },\n [context, menuActionHandler],\n );\n\n return (\n <ContextMenuContext.Provider\n value={{\n menuActionHandler: handleMenuAction,\n menuBuilders,\n }}\n >\n {children}\n </ContextMenuContext.Provider>\n );\n};\n\n// Need an option for local menu to override higher-level menu, rather than extend\nexport const ContextMenuProvider = ({\n children,\n label,\n menuActionHandler,\n menuBuilder,\n}: ContextMenuProviderProps) => {\n return (\n <ContextMenuContext.Consumer>\n {(parentContext) => (\n <Provider\n context={parentContext}\n label={label}\n menuActionHandler={menuActionHandler}\n menuBuilder={menuBuilder}\n >\n {children}\n </Provider>\n )}\n </ContextMenuContext.Consumer>\n );\n};\n"],"names":[],"mappings":";;;AAOO,MAAM,kBAAqB,GAAA,aAAA;AAAA,EAChC,IAAA;AACF,EAAA;AAgBA,MAAM,WAAW,CAAC;AAAA,EAChB,QAAA;AAAA,EACA,OAAA;AAAA,EACA,iBAAA;AAAA,EACA,WAAA;AACF,CAAqB,KAAA;AACnB,EAAM,MAAA,YAAA,GAAe,QAAQ,MAAM;AACjC,IAAI,IAAA,OAAA,EAAS,gBAAgB,WAAa,EAAA;AACxC,MAAO,OAAA,OAAA,CAAQ,YAAa,CAAA,MAAA,CAAO,WAAW,CAAA,CAAA;AAAA,eACrC,WAAa,EAAA;AACtB,MAAA,OAAO,CAAC,WAAW,CAAA,CAAA;AAAA,KACd,MAAA;AACL,MAAO,OAAA,OAAA,EAAS,gBAAgB,EAAC,CAAA;AAAA,KACnC;AAAA,GACC,EAAA,CAAC,OAAS,EAAA,WAAW,CAAC,CAAA,CAAA;AAEzB,EAAA,MAAM,gBAAmB,GAAA,WAAA;AAAA,IACvB,CAAC,MAAW,KAAA;AACV,MAAI,IAAA,iBAAA,GAAoB,MAAM,CAAG,EAAA;AAC/B,QAAO,OAAA,IAAA,CAAA;AAAA,OACT;AAEA,MAAI,IAAA,OAAA,EAAS,iBAAoB,GAAA,MAAM,CAAG,EAAA;AACxC,QAAO,OAAA,IAAA,CAAA;AAAA,OACT;AAAA,KACF;AAAA,IACA,CAAC,SAAS,iBAAiB,CAAA;AAAA,GAC7B,CAAA;AAEA,EACE,uBAAA,GAAA;AAAA,IAAC,kBAAmB,CAAA,QAAA;AAAA,IAAnB;AAAA,MACC,KAAO,EAAA;AAAA,QACL,iBAAmB,EAAA,gBAAA;AAAA,QACnB,YAAA;AAAA,OACF;AAAA,MAEC,QAAA;AAAA,KAAA;AAAA,GACH,CAAA;AAEJ,CAAA,CAAA;AAGO,MAAM,sBAAsB,CAAC;AAAA,EAClC,QAAA;AAAA,EACA,KAAA;AAAA,EACA,iBAAA;AAAA,EACA,WAAA;AACF,CAAgC,KAAA;AAC9B,EAAA,uBACG,GAAA,CAAA,kBAAA,CAAmB,QAAnB,EAAA,EACE,WAAC,aACA,qBAAA,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,OAAS,EAAA,aAAA;AAAA,MACT,KAAA;AAAA,MACA,iBAAA;AAAA,MACA,WAAA;AAAA,MAEC,QAAA;AAAA,KAAA;AAAA,GAGP,EAAA,CAAA,CAAA;AAEJ;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-keyboard-navigation.js","sources":["../../src/menu/use-keyboard-navigation.ts"],"sourcesContent":["import {\n FocusEvent,\n KeyboardEvent,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { hasPopup, isRoot } from \"./utils\";\nimport { isNavigationKey } from \"./key-code\";\nimport { isValidNumber } from \"@vuu-ui/vuu-utils\";\nimport { MenuOpenHandler } from \"./MenuList\";\n\nexport type MenuCloseReason = \"tab-away\" | \"close-child-menu\";\n\nexport type MenuCloseHandler = (\n evt: KeyboardEvent,\n reason: MenuCloseReason\n) => void;\n\nexport interface KeyboardNavigationProps {\n autoHighlightFirstItem?: boolean;\n count: number;\n defaultHighlightedIdx?: number;\n highlightedIndex?: number;\n onActivate: (idx: number) => void;\n onHighlight?: (idx: number) => void;\n onCloseMenu: MenuCloseHandler;\n onOpenMenu?: MenuOpenHandler;\n}\n\nexport interface KeyboardHookListProps {\n // onBlur: (evt: FocusEvent) => void;\n onFocus: (evt: FocusEvent) => void;\n onKeyDown: (evt: KeyboardEvent) => void;\n onMouseDownCapture: () => void;\n onMouseMove: () => void;\n onMouseLeave: () => void;\n}\n\nexport interface NavigationHookResult {\n focusVisible: number;\n controlledHighlighting: boolean;\n highlightedIndex: number;\n setHighlightedIndex: (idx: number) => void;\n // keyboardNavigation: RefObject<boolean>;\n listProps: KeyboardHookListProps;\n setIgnoreFocus: (ignoreFocus: boolean) => void;\n}\n\n// we need a way to set highlightedIdx when selection changes\nexport const useKeyboardNavigation = ({\n autoHighlightFirstItem = false,\n count,\n defaultHighlightedIdx,\n highlightedIndex: highlightedIndexProp,\n onActivate,\n onHighlight,\n // onKeyDown,\n onCloseMenu,\n onOpenMenu,\n}: KeyboardNavigationProps): NavigationHookResult => {\n if (\n isValidNumber(highlightedIndexProp) &&\n isValidNumber(defaultHighlightedIdx)\n ) {\n throw Error(\n \"useKeyboardNavigation do not pass values for both highlightedIndex and defaultHighlightedIdx\"\n );\n }\n\n const controlledHighlighting = isValidNumber(highlightedIndexProp);\n const highlightedIndexRef = useRef(\n defaultHighlightedIdx ??\n highlightedIndexProp ??\n (autoHighlightFirstItem ? 0 : -1)\n );\n const [, forceRender] = useState<unknown>(null);\n\n const setHighlightedIdx = useCallback(\n (idx) => {\n highlightedIndexRef.current = idx;\n onHighlight?.(idx);\n forceRender({});\n },\n [onHighlight]\n );\n\n const setHighlightedIndex = useCallback(\n (idx) => {\n if (idx !== highlightedIndexRef.current) {\n if (!controlledHighlighting) {\n setHighlightedIdx(idx);\n }\n }\n },\n [controlledHighlighting, setHighlightedIdx]\n );\n\n // does this belong here or should it be a method passed in?\n const keyBoardNavigation = useRef(true);\n const ignoreFocus = useRef(false);\n const setIgnoreFocus = (value: boolean) => (ignoreFocus.current = value);\n\n const highlightedIndex = controlledHighlighting\n ? highlightedIndexProp\n : highlightedIndexRef.current;\n\n const navigateChildldItems = useCallback(\n (e: KeyboardEvent) => {\n const nextIdx = nextItemIdx(count, e.key, highlightedIndexRef.current);\n if (nextIdx !== highlightedIndexRef.current) {\n setHighlightedIndex(nextIdx);\n }\n },\n [count, setHighlightedIndex]\n );\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n if (isNavigationKey(e)) {\n e.preventDefault();\n e.stopPropagation();\n keyBoardNavigation.current = true;\n navigateChildldItems(e);\n } else if (\n (e.key === \"ArrowRight\" || e.key === \"Enter\") &&\n hasPopup(e.target as HTMLElement, highlightedIndex)\n ) {\n const menuEl = e.target as HTMLElement;\n const menuItemEl = menuEl.querySelector(\n `:scope > [data-index='${highlightedIndex}']`\n ) as HTMLElement;\n\n if (menuItemEl) {\n onOpenMenu?.(menuItemEl, true);\n }\n } else if (e.key === \"ArrowLeft\" && !isRoot(e.target as HTMLElement)) {\n onCloseMenu(e, \"close-child-menu\");\n } else if (e.key === \"Enter\") {\n e.preventDefault();\n e.stopPropagation();\n onActivate && onActivate(highlightedIndex);\n } else if (e.key === \"Tab\") {\n onCloseMenu(e, \"tab-away\");\n }\n },\n [\n highlightedIndex,\n navigateChildldItems,\n onActivate,\n onCloseMenu,\n onOpenMenu,\n ]\n );\n\n const listProps: KeyboardHookListProps = useMemo(\n () => ({\n onFocus: () => {\n if (highlightedIndex === -1) {\n setHighlightedIdx(0);\n }\n },\n onKeyDown: handleKeyDown,\n onMouseDownCapture: () => {\n keyBoardNavigation.current = false;\n setIgnoreFocus(true);\n },\n\n // onMouseEnter would seem less expensive but it misses some cases\n onMouseMove: () => {\n if (keyBoardNavigation.current) {\n keyBoardNavigation.current = false;\n }\n },\n onMouseLeave: () => {\n // label === 'ParsedInput' && console.log(`%c[useKeyboardNavigationHook]<${label}> onMouseLeave`,'color:brown')\n keyBoardNavigation.current = true;\n setIgnoreFocus(false);\n setHighlightedIndex(-1);\n },\n }),\n [handleKeyDown, highlightedIndex, setHighlightedIdx, setHighlightedIndex]\n );\n\n return {\n focusVisible: keyBoardNavigation.current ? highlightedIndex : -1,\n controlledHighlighting,\n highlightedIndex,\n setHighlightedIndex: setHighlightedIndex,\n // keyBoardNavigation,\n listProps,\n setIgnoreFocus,\n };\n};\n\n// need to be able to accommodate disabled items\nfunction nextItemIdx(count: number, key: string, idx: number) {\n if (key === \"ArrowUp\") {\n if (idx > 0) {\n return idx - 1;\n } else {\n return idx;\n }\n } else {\n if (idx === null) {\n return 0;\n } else if (idx === count - 1) {\n return idx;\n } else {\n return idx + 1;\n }\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-keyboard-navigation.js","sources":["../../src/menu/use-keyboard-navigation.ts"],"sourcesContent":["import {\n FocusEvent,\n KeyboardEvent,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { hasPopup, isRoot } from \"./utils\";\nimport { isNavigationKey } from \"./key-code\";\nimport { isValidNumber } from \"@vuu-ui/vuu-utils\";\nimport { MenuOpenHandler } from \"./MenuList\";\n\nexport type MenuCloseReason = \"tab-away\" | \"close-child-menu\";\n\nexport type MenuCloseHandler = (\n evt: KeyboardEvent,\n reason: MenuCloseReason,\n) => void;\n\nexport interface KeyboardNavigationProps {\n autoHighlightFirstItem?: boolean;\n count: number;\n defaultHighlightedIdx?: number;\n highlightedIndex?: number;\n onActivate: (idx: number) => void;\n onHighlight?: (idx: number) => void;\n onCloseMenu: MenuCloseHandler;\n onOpenMenu?: MenuOpenHandler;\n}\n\nexport interface KeyboardHookListProps {\n // onBlur: (evt: FocusEvent) => void;\n onFocus: (evt: FocusEvent) => void;\n onKeyDown: (evt: KeyboardEvent) => void;\n onMouseDownCapture: () => void;\n onMouseMove: () => void;\n onMouseLeave: () => void;\n}\n\nexport interface NavigationHookResult {\n focusVisible: number;\n controlledHighlighting: boolean;\n highlightedIndex: number;\n setHighlightedIndex: (idx: number) => void;\n // keyboardNavigation: RefObject<boolean>;\n listProps: KeyboardHookListProps;\n setIgnoreFocus: (ignoreFocus: boolean) => void;\n}\n\n// we need a way to set highlightedIdx when selection changes\nexport const useKeyboardNavigation = ({\n autoHighlightFirstItem = false,\n count,\n defaultHighlightedIdx,\n highlightedIndex: highlightedIndexProp,\n onActivate,\n onHighlight,\n // onKeyDown,\n onCloseMenu,\n onOpenMenu,\n}: KeyboardNavigationProps): NavigationHookResult => {\n if (\n isValidNumber(highlightedIndexProp) &&\n isValidNumber(defaultHighlightedIdx)\n ) {\n throw Error(\n \"useKeyboardNavigation do not pass values for both highlightedIndex and defaultHighlightedIdx\",\n );\n }\n\n const controlledHighlighting = isValidNumber(highlightedIndexProp);\n const highlightedIndexRef = useRef(\n defaultHighlightedIdx ??\n highlightedIndexProp ??\n (autoHighlightFirstItem ? 0 : -1),\n );\n const [, forceRender] = useState<unknown>(null);\n\n const setHighlightedIdx = useCallback(\n (idx) => {\n highlightedIndexRef.current = idx;\n onHighlight?.(idx);\n forceRender({});\n },\n [onHighlight],\n );\n\n const setHighlightedIndex = useCallback(\n (idx) => {\n if (idx !== highlightedIndexRef.current) {\n if (!controlledHighlighting) {\n setHighlightedIdx(idx);\n }\n }\n },\n [controlledHighlighting, setHighlightedIdx],\n );\n\n // does this belong here or should it be a method passed in?\n const keyBoardNavigation = useRef(true);\n const ignoreFocus = useRef(false);\n const setIgnoreFocus = (value: boolean) => (ignoreFocus.current = value);\n\n const highlightedIndex = controlledHighlighting\n ? highlightedIndexProp\n : highlightedIndexRef.current;\n\n const navigateChildldItems = useCallback(\n (e: KeyboardEvent) => {\n const nextIdx = nextItemIdx(count, e.key, highlightedIndexRef.current);\n if (nextIdx !== highlightedIndexRef.current) {\n setHighlightedIndex(nextIdx);\n }\n },\n [count, setHighlightedIndex],\n );\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n if (isNavigationKey(e)) {\n e.preventDefault();\n e.stopPropagation();\n keyBoardNavigation.current = true;\n navigateChildldItems(e);\n } else if (\n (e.key === \"ArrowRight\" || e.key === \"Enter\") &&\n hasPopup(e.target as HTMLElement, highlightedIndex)\n ) {\n const menuEl = e.target as HTMLElement;\n const menuItemEl = menuEl.querySelector(\n `:scope > [data-index='${highlightedIndex}']`,\n ) as HTMLElement;\n\n if (menuItemEl) {\n onOpenMenu?.(menuItemEl, true);\n }\n } else if (e.key === \"ArrowLeft\" && !isRoot(e.target as HTMLElement)) {\n onCloseMenu(e, \"close-child-menu\");\n } else if (e.key === \"Enter\") {\n e.preventDefault();\n e.stopPropagation();\n onActivate && onActivate(highlightedIndex);\n } else if (e.key === \"Tab\") {\n onCloseMenu(e, \"tab-away\");\n }\n },\n [\n highlightedIndex,\n navigateChildldItems,\n onActivate,\n onCloseMenu,\n onOpenMenu,\n ],\n );\n\n const listProps: KeyboardHookListProps = useMemo(\n () => ({\n onFocus: () => {\n if (highlightedIndex === -1) {\n setHighlightedIdx(0);\n }\n },\n onKeyDown: handleKeyDown,\n onMouseDownCapture: () => {\n keyBoardNavigation.current = false;\n setIgnoreFocus(true);\n },\n\n // onMouseEnter would seem less expensive but it misses some cases\n onMouseMove: () => {\n if (keyBoardNavigation.current) {\n keyBoardNavigation.current = false;\n }\n },\n onMouseLeave: () => {\n // label === 'ParsedInput' && console.log(`%c[useKeyboardNavigationHook]<${label}> onMouseLeave`,'color:brown')\n keyBoardNavigation.current = true;\n setIgnoreFocus(false);\n setHighlightedIndex(-1);\n },\n }),\n [handleKeyDown, highlightedIndex, setHighlightedIdx, setHighlightedIndex],\n );\n\n return {\n focusVisible: keyBoardNavigation.current ? highlightedIndex : -1,\n controlledHighlighting,\n highlightedIndex,\n setHighlightedIndex: setHighlightedIndex,\n // keyBoardNavigation,\n listProps,\n setIgnoreFocus,\n };\n};\n\n// need to be able to accommodate disabled items\nfunction nextItemIdx(count: number, key: string, idx: number) {\n if (key === \"ArrowUp\") {\n if (idx > 0) {\n return idx - 1;\n } else {\n return idx;\n }\n } else {\n if (idx === null) {\n return 0;\n } else if (idx === count - 1) {\n return idx;\n } else {\n return idx + 1;\n }\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useContextMenu.js","sources":["../../src/menu/useContextMenu.tsx"],"sourcesContent":["import {\n ContextMenuItemDescriptor,\n MenuActionHandler,\n MenuBuilder,\n} from \"@vuu-ui/vuu-data-types\";\nimport {\n isGroupMenuItemDescriptor,\n useThemeAttributes,\n} from \"@vuu-ui/vuu-utils\";\nimport { cloneElement, useCallback, useContext, useMemo } from \"react\";\nimport {\n MenuActionClosePopup,\n PopupCloseReason,\n PopupService,\n reasonIsMenuAction,\n} from \"../popup\";\nimport { ContextMenu, ContextMenuProps } from \"./ContextMenu\";\nimport { MenuItem, MenuItemGroup } from \"./MenuList\";\nimport { ContextMenuContext } from \"./context-menu-provider\";\n\nexport type ContextMenuOptions = {\n [key: string]: unknown;\n contextMenu?: JSX.Element;\n ContextMenuProps?: Partial<ContextMenuProps> & {\n className?: string;\n };\n controlledComponentId?: string;\n};\n\nexport type EventLike = {\n clientX: number;\n clientY: number;\n preventDefault?: () => void;\n stopPropagation?: () => void;\n};\n\nexport type ShowContextMenu = (\n e: EventLike,\n location: string,\n options: ContextMenuOptions\n) => void;\n\n// The argument allows a top-level menuBuilder to operate outside the Context\nexport const useContextMenu = (\n menuBuilder?: MenuBuilder,\n menuActionHandler?: MenuActionHandler\n): [ShowContextMenu, () => void] => {\n const ctx = useContext(ContextMenuContext);\n\n const [themeClass, densityClass, dataMode] = useThemeAttributes();\n const themeAttributes = useMemo(\n () => ({\n themeClass,\n densityClass,\n dataMode,\n }),\n [dataMode, densityClass, themeClass]\n );\n\n const buildMenuOptions = useCallback(\n (menuBuilders: MenuBuilder[], location, options) => {\n let results: ContextMenuItemDescriptor[] = [];\n for (const menuBuilder of menuBuilders) {\n // Maybe we should leave the concatenation to the menuBuilder, then it can control menuItem order\n results = results.concat(menuBuilder(location, options));\n }\n return results;\n },\n []\n );\n\n const handleShowContextMenu = useCallback<ShowContextMenu>(\n (e, location, { ContextMenuProps, contextMenu, ...options }) => {\n e.stopPropagation?.();\n e.preventDefault?.();\n\n if (contextMenu) {\n return showContextMenuComponent(\n {\n x: e.clientX,\n y: e.clientY,\n },\n contextMenu\n );\n }\n\n const menuBuilders: MenuBuilder[] = [];\n if (menuBuilder) {\n menuBuilders.push(menuBuilder);\n }\n if (\n ctx &&\n Array.isArray(ctx?.menuBuilders) &&\n ctx.menuBuilders.length > 0\n ) {\n menuBuilders.push(...ctx.menuBuilders);\n }\n\n if (menuBuilders.length > 0) {\n const menuItemDescriptors = buildMenuOptions(\n menuBuilders,\n location,\n options\n );\n\n // const menuHandler = menuActionHandler ?? ctx?.menuActionHandler;\n const menuHandler: MenuActionHandler = (\n action: MenuActionClosePopup\n ) => {\n if (menuActionHandler?.(action) === true) {\n return true;\n } else {\n return ctx?.menuActionHandler(action);\n }\n };\n\n if (menuItemDescriptors.length && menuHandler) {\n // because showPopup is going to be used to render the context menu, it will not\n // have access to the ContextMenuContext. Pass the theme attributes here\n showContextMenu(e, menuItemDescriptors, menuHandler, {\n PortalProps: {\n themeAttributes,\n },\n ...ContextMenuProps,\n });\n }\n } else {\n console.warn(\n \"useContextMenu, no menuBuilders configured. These should be supplied via the ContextMenuProvider(s)\"\n );\n }\n },\n [buildMenuOptions, ctx, menuActionHandler, menuBuilder, themeAttributes]\n );\n\n const hideContextMenu = useCallback(() => {\n console.log(\"hide context menu\");\n }, []);\n\n return [handleShowContextMenu, hideContextMenu];\n};\n\nconst NO_OPTIONS = {};\n\nconst showContextMenuComponent = (\n position: { x: number; y: number },\n contextMenu: JSX.Element\n) => {\n PopupService.showPopup({\n focus: true,\n left: 0,\n top: 0,\n component: cloneElement(contextMenu, { position }),\n });\n};\n\nconst showContextMenu = (\n e: EventLike,\n menuDescriptors: ContextMenuItemDescriptor[],\n handleContextMenuAction: MenuActionHandler,\n {\n position: positionProp,\n ...contextMenuProps\n }: ContextMenuOptions[\"ContextMenuProps\"] = NO_OPTIONS\n) => {\n const menuItems = (menuDescriptors: ContextMenuItemDescriptor[]) => {\n const fromDescriptor = (menuItem: ContextMenuItemDescriptor, i: number) =>\n isGroupMenuItemDescriptor(menuItem) ? (\n <MenuItemGroup key={i} label={menuItem.label}>\n {menuItem.children.map(fromDescriptor)}\n </MenuItemGroup>\n ) : (\n <MenuItem\n key={i}\n action={menuItem.action}\n className={menuItem.className}\n data-icon={menuItem.icon}\n options={menuItem.options}\n >\n {menuItem.label}\n </MenuItem>\n );\n\n return menuDescriptors.map(fromDescriptor);\n };\n\n const handleClose = (reason?: PopupCloseReason) => {\n if (reasonIsMenuAction(reason)) {\n if (reason?.closedBy === \"popup-service\") {\n return;\n }\n handleContextMenuAction(reason);\n // TODO this results in onClose being called twice on component\n // cant simply be removed, some refactoring work needed\n PopupService.hidePopup(reason);\n }\n contextMenuProps?.onClose?.(reason);\n };\n\n const position = positionProp ?? {\n x: e.clientX,\n y: e.clientY,\n };\n\n const component = (\n <ContextMenu\n {...contextMenuProps}\n onClose={handleClose}\n position={position}\n >\n {menuItems(menuDescriptors)}\n </ContextMenu>\n );\n PopupService.showPopup({ left: 0, top: 0, component, focus: true });\n};\n"],"names":["menuBuilder","ContextMenuProps","menuDescriptors"],"mappings":"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"}
1
+ {"version":3,"file":"useContextMenu.js","sources":["../../src/menu/useContextMenu.tsx"],"sourcesContent":["import {\n ContextMenuItemDescriptor,\n MenuActionHandler,\n MenuBuilder,\n} from \"@vuu-ui/vuu-data-types\";\nimport {\n isGroupMenuItemDescriptor,\n useThemeAttributes,\n} from \"@vuu-ui/vuu-utils\";\nimport { cloneElement, useCallback, useContext, useMemo } from \"react\";\nimport {\n MenuActionClosePopup,\n PopupCloseReason,\n PopupService,\n reasonIsMenuAction,\n} from \"../popup\";\nimport { ContextMenu, ContextMenuProps } from \"./ContextMenu\";\nimport { MenuItem, MenuItemGroup } from \"./MenuList\";\nimport { ContextMenuContext } from \"./context-menu-provider\";\n\nexport type ContextMenuOptions = {\n [key: string]: unknown;\n contextMenu?: JSX.Element;\n ContextMenuProps?: Partial<ContextMenuProps> & {\n className?: string;\n };\n controlledComponentId?: string;\n};\n\nexport type EventLike = {\n clientX: number;\n clientY: number;\n preventDefault?: () => void;\n stopPropagation?: () => void;\n};\n\nexport type ShowContextMenu = (\n e: EventLike,\n location: string,\n options: ContextMenuOptions,\n) => void;\n\n// The argument allows a top-level menuBuilder to operate outside the Context\nexport const useContextMenu = (\n menuBuilder?: MenuBuilder,\n menuActionHandler?: MenuActionHandler,\n): [ShowContextMenu, () => void] => {\n const ctx = useContext(ContextMenuContext);\n\n const [themeClass, densityClass, dataMode] = useThemeAttributes();\n const themeAttributes = useMemo(\n () => ({\n themeClass,\n densityClass,\n dataMode,\n }),\n [dataMode, densityClass, themeClass],\n );\n\n const buildMenuOptions = useCallback(\n (menuBuilders: MenuBuilder[], location, options) => {\n let results: ContextMenuItemDescriptor[] = [];\n for (const menuBuilder of menuBuilders) {\n // Maybe we should leave the concatenation to the menuBuilder, then it can control menuItem order\n results = results.concat(menuBuilder(location, options));\n }\n return results;\n },\n [],\n );\n\n const handleShowContextMenu = useCallback<ShowContextMenu>(\n (e, location, { ContextMenuProps, contextMenu, ...options }) => {\n e.stopPropagation?.();\n e.preventDefault?.();\n\n if (contextMenu) {\n return showContextMenuComponent(\n {\n x: e.clientX,\n y: e.clientY,\n },\n contextMenu,\n );\n }\n\n const menuBuilders: MenuBuilder[] = [];\n if (menuBuilder) {\n menuBuilders.push(menuBuilder);\n }\n if (\n ctx &&\n Array.isArray(ctx?.menuBuilders) &&\n ctx.menuBuilders.length > 0\n ) {\n menuBuilders.push(...ctx.menuBuilders);\n }\n\n if (menuBuilders.length > 0) {\n const menuItemDescriptors = buildMenuOptions(\n menuBuilders,\n location,\n options,\n );\n\n // const menuHandler = menuActionHandler ?? ctx?.menuActionHandler;\n const menuHandler: MenuActionHandler = (\n action: MenuActionClosePopup,\n ) => {\n if (menuActionHandler?.(action) === true) {\n return true;\n } else {\n return ctx?.menuActionHandler(action);\n }\n };\n\n if (menuItemDescriptors.length && menuHandler) {\n // because showPopup is going to be used to render the context menu, it will not\n // have access to the ContextMenuContext. Pass the theme attributes here\n showContextMenu(e, menuItemDescriptors, menuHandler, {\n PortalProps: {\n themeAttributes,\n },\n ...ContextMenuProps,\n });\n }\n } else {\n console.warn(\n \"useContextMenu, no menuBuilders configured. These should be supplied via the ContextMenuProvider(s)\",\n );\n }\n },\n [buildMenuOptions, ctx, menuActionHandler, menuBuilder, themeAttributes],\n );\n\n const hideContextMenu = useCallback(() => {\n console.log(\"hide context menu\");\n }, []);\n\n return [handleShowContextMenu, hideContextMenu];\n};\n\nconst NO_OPTIONS = {};\n\nconst showContextMenuComponent = (\n position: { x: number; y: number },\n contextMenu: JSX.Element,\n) => {\n PopupService.showPopup({\n focus: true,\n left: 0,\n top: 0,\n component: cloneElement(contextMenu, { position }),\n });\n};\n\nconst showContextMenu = (\n e: EventLike,\n menuDescriptors: ContextMenuItemDescriptor[],\n handleContextMenuAction: MenuActionHandler,\n {\n position: positionProp,\n ...contextMenuProps\n }: ContextMenuOptions[\"ContextMenuProps\"] = NO_OPTIONS,\n) => {\n const menuItems = (menuDescriptors: ContextMenuItemDescriptor[]) => {\n const fromDescriptor = (menuItem: ContextMenuItemDescriptor, i: number) =>\n isGroupMenuItemDescriptor(menuItem) ? (\n <MenuItemGroup key={i} label={menuItem.label}>\n {menuItem.children.map(fromDescriptor)}\n </MenuItemGroup>\n ) : (\n <MenuItem\n key={i}\n action={menuItem.action}\n className={menuItem.className}\n data-icon={menuItem.icon}\n options={menuItem.options}\n >\n {menuItem.label}\n </MenuItem>\n );\n\n return menuDescriptors.map(fromDescriptor);\n };\n\n const handleClose = (reason?: PopupCloseReason) => {\n if (reasonIsMenuAction(reason)) {\n if (reason?.closedBy === \"popup-service\") {\n return;\n }\n handleContextMenuAction(reason);\n // TODO this results in onClose being called twice on component\n // cant simply be removed, some refactoring work needed\n PopupService.hidePopup(reason);\n }\n contextMenuProps?.onClose?.(reason);\n };\n\n const position = positionProp ?? {\n x: e.clientX,\n y: e.clientY,\n };\n\n const component = (\n <ContextMenu\n {...contextMenuProps}\n onClose={handleClose}\n position={position}\n >\n {menuItems(menuDescriptors)}\n </ContextMenu>\n );\n PopupService.showPopup({ left: 0, top: 0, component, focus: true });\n};\n"],"names":["menuBuilder","ContextMenuProps","menuDescriptors"],"mappings":"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"}
@@ -19,9 +19,12 @@ const NotificationsCenter = ({
19
19
  id: getUniqueId()
20
20
  };
21
21
  setNotifications((prev) => prev.concat(newNotification));
22
- setTimeout(() => {
23
- setNotifications((prev) => prev.filter((n) => n !== newNotification));
24
- }, toastDisplayDuration + horizontalTransitionDuration * 2);
22
+ setTimeout(
23
+ () => {
24
+ setNotifications((prev) => prev.filter((n) => n !== newNotification));
25
+ },
26
+ toastDisplayDuration + horizontalTransitionDuration * 2
27
+ );
25
28
  });
26
29
  }, [notificationsContext]);
27
30
  return /* @__PURE__ */ jsx(Fragment, { children: notifications.map((notification, i) => /* @__PURE__ */ jsx(
@@ -1 +1 @@
1
- {"version":3,"file":"NotificationsCenter.js","sources":["../../src/notifications/NotificationsCenter.tsx"],"sourcesContent":["import { useMemo, useState } from \"react\";\nimport { NotificationsContext } from \"./NotificationsProvider\";\nimport { getUniqueId } from \"@vuu-ui/vuu-utils\";\nimport { ToastNotification } from \"./ToastNotification\";\nimport { Notification } from \"./notificationTypes\";\n\nexport interface NotificationsCenterProps {\n notificationsContext: NotificationsContext;\n}\n\n// animation times in milliseconds\nconst toastOffsetTop = 60;\nconst toastDisplayDuration = 6000;\nconst horizontalTransitionDuration = 1000;\n\n// toast size in pixels\nconst toastHeight = 56;\nconst toastContainerContentGap = 10;\n// rightPadding is used together with the toastWidth to compute the toast position\n// at the beginning and at the end of the animation\n\nexport const NotificationsCenter = ({\n notificationsContext,\n}: NotificationsCenterProps) => {\n const [notifications, setNotifications] = useState<Notification[]>([]);\n\n useMemo(() => {\n notificationsContext.setNotify((notification) => {\n const newNotification: Notification = {\n ...notification,\n id: getUniqueId(),\n };\n setNotifications((prev) => prev.concat(newNotification));\n setTimeout(() => {\n setNotifications((prev) => prev.filter((n) => n !== newNotification));\n }, toastDisplayDuration + horizontalTransitionDuration * 2);\n });\n }, [notificationsContext]);\n\n return (\n <>\n {notifications.map((notification, i) => (\n <ToastNotification\n top={toastOffsetTop + (toastHeight + toastContainerContentGap) * i}\n notification={notification}\n key={notification.id}\n />\n ))}\n </>\n );\n};\n"],"names":[],"mappings":";;;;;AAWA,MAAM,cAAiB,GAAA,EAAA,CAAA;AACvB,MAAM,oBAAuB,GAAA,GAAA,CAAA;AAC7B,MAAM,4BAA+B,GAAA,GAAA,CAAA;AAGrC,MAAM,WAAc,GAAA,EAAA,CAAA;AACpB,MAAM,wBAA2B,GAAA,EAAA,CAAA;AAI1B,MAAM,sBAAsB,CAAC;AAAA,EAClC,oBAAA;AACF,CAAgC,KAAA;AAC9B,EAAA,MAAM,CAAC,aAAe,EAAA,gBAAgB,CAAI,GAAA,QAAA,CAAyB,EAAE,CAAA,CAAA;AAErE,EAAA,OAAA,CAAQ,MAAM;AACZ,IAAqB,oBAAA,CAAA,SAAA,CAAU,CAAC,YAAiB,KAAA;AAC/C,MAAA,MAAM,eAAgC,GAAA;AAAA,QACpC,GAAG,YAAA;AAAA,QACH,IAAI,WAAY,EAAA;AAAA,OAClB,CAAA;AACA,MAAA,gBAAA,CAAiB,CAAC,IAAA,KAAS,IAAK,CAAA,MAAA,CAAO,eAAe,CAAC,CAAA,CAAA;AACvD,MAAA,UAAA,CAAW,MAAM;AACf,QAAiB,gBAAA,CAAA,CAAC,SAAS,IAAK,CAAA,MAAA,CAAO,CAAC,CAAM,KAAA,CAAA,KAAM,eAAe,CAAC,CAAA,CAAA;AAAA,OACtE,EAAG,oBAAuB,GAAA,4BAAA,GAA+B,CAAC,CAAA,CAAA;AAAA,KAC3D,CAAA,CAAA;AAAA,GACH,EAAG,CAAC,oBAAoB,CAAC,CAAA,CAAA;AAEzB,EAAA,uBAEK,GAAA,CAAA,QAAA,EAAA,EAAA,QAAA,EAAA,aAAA,CAAc,GAAI,CAAA,CAAC,cAAc,CAChC,qBAAA,GAAA;AAAA,IAAC,iBAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,cAAkB,GAAA,CAAA,WAAA,GAAc,wBAA4B,IAAA,CAAA;AAAA,MACjE,YAAA;AAAA,KAAA;AAAA,IACK,YAAa,CAAA,EAAA;AAAA,GAErB,CACH,EAAA,CAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"NotificationsCenter.js","sources":["../../src/notifications/NotificationsCenter.tsx"],"sourcesContent":["import { useMemo, useState } from \"react\";\nimport { NotificationsContext } from \"./NotificationsProvider\";\nimport { getUniqueId } from \"@vuu-ui/vuu-utils\";\nimport { ToastNotification } from \"./ToastNotification\";\nimport { Notification } from \"./notificationTypes\";\n\nexport interface NotificationsCenterProps {\n notificationsContext: NotificationsContext;\n}\n\n// animation times in milliseconds\nconst toastOffsetTop = 60;\nconst toastDisplayDuration = 6000;\nconst horizontalTransitionDuration = 1000;\n\n// toast size in pixels\nconst toastHeight = 56;\nconst toastContainerContentGap = 10;\n// rightPadding is used together with the toastWidth to compute the toast position\n// at the beginning and at the end of the animation\n\nexport const NotificationsCenter = ({\n notificationsContext,\n}: NotificationsCenterProps) => {\n const [notifications, setNotifications] = useState<Notification[]>([]);\n\n useMemo(() => {\n notificationsContext.setNotify((notification) => {\n const newNotification: Notification = {\n ...notification,\n id: getUniqueId(),\n };\n setNotifications((prev) => prev.concat(newNotification));\n setTimeout(\n () => {\n setNotifications((prev) => prev.filter((n) => n !== newNotification));\n },\n toastDisplayDuration + horizontalTransitionDuration * 2,\n );\n });\n }, [notificationsContext]);\n\n return (\n <>\n {notifications.map((notification, i) => (\n <ToastNotification\n top={toastOffsetTop + (toastHeight + toastContainerContentGap) * i}\n notification={notification}\n key={notification.id}\n />\n ))}\n </>\n );\n};\n"],"names":[],"mappings":";;;;;AAWA,MAAM,cAAiB,GAAA,EAAA,CAAA;AACvB,MAAM,oBAAuB,GAAA,GAAA,CAAA;AAC7B,MAAM,4BAA+B,GAAA,GAAA,CAAA;AAGrC,MAAM,WAAc,GAAA,EAAA,CAAA;AACpB,MAAM,wBAA2B,GAAA,EAAA,CAAA;AAI1B,MAAM,sBAAsB,CAAC;AAAA,EAClC,oBAAA;AACF,CAAgC,KAAA;AAC9B,EAAA,MAAM,CAAC,aAAe,EAAA,gBAAgB,CAAI,GAAA,QAAA,CAAyB,EAAE,CAAA,CAAA;AAErE,EAAA,OAAA,CAAQ,MAAM;AACZ,IAAqB,oBAAA,CAAA,SAAA,CAAU,CAAC,YAAiB,KAAA;AAC/C,MAAA,MAAM,eAAgC,GAAA;AAAA,QACpC,GAAG,YAAA;AAAA,QACH,IAAI,WAAY,EAAA;AAAA,OAClB,CAAA;AACA,MAAA,gBAAA,CAAiB,CAAC,IAAA,KAAS,IAAK,CAAA,MAAA,CAAO,eAAe,CAAC,CAAA,CAAA;AACvD,MAAA,UAAA;AAAA,QACE,MAAM;AACJ,UAAiB,gBAAA,CAAA,CAAC,SAAS,IAAK,CAAA,MAAA,CAAO,CAAC,CAAM,KAAA,CAAA,KAAM,eAAe,CAAC,CAAA,CAAA;AAAA,SACtE;AAAA,QACA,uBAAuB,4BAA+B,GAAA,CAAA;AAAA,OACxD,CAAA;AAAA,KACD,CAAA,CAAA;AAAA,GACH,EAAG,CAAC,oBAAoB,CAAC,CAAA,CAAA;AAEzB,EAAA,uBAEK,GAAA,CAAA,QAAA,EAAA,EAAA,QAAA,EAAA,aAAA,CAAc,GAAI,CAAA,CAAC,cAAc,CAChC,qBAAA,GAAA;AAAA,IAAC,iBAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,cAAkB,GAAA,CAAA,WAAA,GAAc,wBAA4B,IAAA,CAAA;AAAA,MACjE,YAAA;AAAA,KAAA;AAAA,IACK,YAAa,CAAA,EAAA;AAAA,GAErB,CACH,EAAA,CAAA,CAAA;AAEJ;;;;"}
@@ -2,24 +2,13 @@ import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import React, { useContext } from 'react';
3
3
  import { NotificationsCenter } from './NotificationsCenter.js';
4
4
 
5
- var __accessCheck = (obj, member, msg) => {
6
- if (!member.has(obj))
7
- throw TypeError("Cannot " + msg);
8
- };
9
- var __privateGet = (obj, member, getter) => {
10
- __accessCheck(obj, member, "read from private field");
11
- return getter ? getter.call(obj) : member.get(obj);
12
- };
13
- var __privateAdd = (obj, member, value) => {
14
- if (member.has(obj))
15
- throw TypeError("Cannot add the same private member more than once");
16
- member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
17
- };
18
- var __privateSet = (obj, member, value, setter) => {
19
- __accessCheck(obj, member, "write to private field");
20
- setter ? setter.call(obj, value) : member.set(obj, value);
21
- return value;
5
+ var __typeError = (msg) => {
6
+ throw TypeError(msg);
22
7
  };
8
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
9
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
10
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
11
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
23
12
  var _notify;
24
13
  class NotificationsContextObject {
25
14
  constructor() {
@@ -1 +1 @@
1
- {"version":3,"file":"NotificationsProvider.js","sources":["../../src/notifications/NotificationsProvider.tsx"],"sourcesContent":["import React, { useContext } from \"react\";\nimport { NotificationsCenter } from \"./NotificationsCenter\";\nimport { Notification } from \"./notificationTypes\";\n\nexport type DispatchNotification = (\n notification: Omit<Notification, \"id\">\n) => void;\n\nexport type NotificationsContext = {\n notify: DispatchNotification;\n setNotify: (dispatcher: DispatchNotification) => void;\n};\n\n/*\n The Context is not exposed outside this module, only the notify\n prop can be accessed via the useNotifications hook.\n The NotificationsCenter receives the full context object and\n sets the notify method. State management around dispatched\n notifications is handled entirely within the NotificationsCenter,\n avoiding rerendering our children when notifications are \n dispatched.\n*/\nclass NotificationsContextObject implements NotificationsContext {\n #notify: DispatchNotification = () =>\n console.log(\"have you forgotten to provide a NotificationsCenter?\");\n // We want the public notify method to be stable, setNotify call should not trigger re-renders\n notify: DispatchNotification = (notification) => this.#notify(notification);\n setNotify = (dispatcher: DispatchNotification) => {\n this.#notify = dispatcher;\n };\n}\n\nconst NotificationsContext = React.createContext<NotificationsContext>(\n new NotificationsContextObject()\n);\n\nexport const NotificationsProvider = (props: {\n children: JSX.Element | JSX.Element[];\n}) => {\n const context = useContext(NotificationsContext);\n return (\n <NotificationsContext.Provider value={context}>\n <NotificationsCenter notificationsContext={context} />\n {props.children}\n </NotificationsContext.Provider>\n );\n};\n\nexport const useNotifications = () => {\n const { notify } = useContext(NotificationsContext);\n return notify;\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,IAAA,OAAA,CAAA;AAsBA,MAAM,0BAA2D,CAAA;AAAA,EAAjE,WAAA,GAAA;AACE,IAAgC,YAAA,CAAA,IAAA,EAAA,OAAA,EAAA,MAC9B,OAAQ,CAAA,GAAA,CAAI,sDAAsD,CAAA,CAAA,CAAA;AAEpE;AAAA,IAAA,IAAA,CAAA,MAAA,GAA+B,CAAC,YAAA,KAAiB,YAAK,CAAA,IAAA,EAAA,OAAA,CAAA,CAAL,IAAa,CAAA,IAAA,EAAA,YAAA,CAAA,CAAA;AAC9D,IAAA,IAAA,CAAA,SAAA,GAAY,CAAC,UAAqC,KAAA;AAChD,MAAA,YAAA,CAAA,IAAA,EAAK,OAAU,EAAA,UAAA,CAAA,CAAA;AAAA,KACjB,CAAA;AAAA,GAAA;AACF,CAAA;AAPE,OAAA,GAAA,IAAA,OAAA,EAAA,CAAA;AASF,MAAM,uBAAuB,KAAM,CAAA,aAAA;AAAA,EACjC,IAAI,0BAA2B,EAAA;AACjC,CAAA,CAAA;AAEa,MAAA,qBAAA,GAAwB,CAAC,KAEhC,KAAA;AACJ,EAAM,MAAA,OAAA,GAAU,WAAW,oBAAoB,CAAA,CAAA;AAC/C,EAAA,uBACG,IAAA,CAAA,oBAAA,CAAqB,QAArB,EAAA,EAA8B,OAAO,OACpC,EAAA,QAAA,EAAA;AAAA,oBAAC,GAAA,CAAA,mBAAA,EAAA,EAAoB,sBAAsB,OAAS,EAAA,CAAA;AAAA,IACnD,KAAM,CAAA,QAAA;AAAA,GACT,EAAA,CAAA,CAAA;AAEJ,EAAA;AAEO,MAAM,mBAAmB,MAAM;AACpC,EAAA,MAAM,EAAE,MAAA,EAAW,GAAA,UAAA,CAAW,oBAAoB,CAAA,CAAA;AAClD,EAAO,OAAA,MAAA,CAAA;AACT;;;;"}
1
+ {"version":3,"file":"NotificationsProvider.js","sources":["../../src/notifications/NotificationsProvider.tsx"],"sourcesContent":["import React, { useContext } from \"react\";\nimport { NotificationsCenter } from \"./NotificationsCenter\";\nimport { Notification } from \"./notificationTypes\";\n\nexport type DispatchNotification = (\n notification: Omit<Notification, \"id\">\n) => void;\n\nexport type NotificationsContext = {\n notify: DispatchNotification;\n setNotify: (dispatcher: DispatchNotification) => void;\n};\n\n/*\n The Context is not exposed outside this module, only the notify\n prop can be accessed via the useNotifications hook.\n The NotificationsCenter receives the full context object and\n sets the notify method. State management around dispatched\n notifications is handled entirely within the NotificationsCenter,\n avoiding rerendering our children when notifications are \n dispatched.\n*/\nclass NotificationsContextObject implements NotificationsContext {\n #notify: DispatchNotification = () =>\n console.log(\"have you forgotten to provide a NotificationsCenter?\");\n // We want the public notify method to be stable, setNotify call should not trigger re-renders\n notify: DispatchNotification = (notification) => this.#notify(notification);\n setNotify = (dispatcher: DispatchNotification) => {\n this.#notify = dispatcher;\n };\n}\n\nconst NotificationsContext = React.createContext<NotificationsContext>(\n new NotificationsContextObject()\n);\n\nexport const NotificationsProvider = (props: {\n children: JSX.Element | JSX.Element[];\n}) => {\n const context = useContext(NotificationsContext);\n return (\n <NotificationsContext.Provider value={context}>\n <NotificationsCenter notificationsContext={context} />\n {props.children}\n </NotificationsContext.Provider>\n );\n};\n\nexport const useNotifications = () => {\n const { notify } = useContext(NotificationsContext);\n return notify;\n};\n"],"names":[],"mappings":";;;;;;;;;;;AAAA,IAAA,OAAA,CAAA;AAsBA,MAAM,0BAA2D,CAAA;AAAA,EAAjE,WAAA,GAAA;AACE,IAAgC,YAAA,CAAA,IAAA,EAAA,OAAA,EAAA,MAC9B,OAAQ,CAAA,GAAA,CAAI,sDAAsD,CAAA,CAAA,CAAA;AAEpE;AAAA,IAAA,IAAA,CAAA,MAAA,GAA+B,CAAC,YAAA,KAAiB,YAAK,CAAA,IAAA,EAAA,OAAA,CAAA,CAAL,IAAa,CAAA,IAAA,EAAA,YAAA,CAAA,CAAA;AAC9D,IAAA,IAAA,CAAA,SAAA,GAAY,CAAC,UAAqC,KAAA;AAChD,MAAA,YAAA,CAAA,IAAA,EAAK,OAAU,EAAA,UAAA,CAAA,CAAA;AAAA,KACjB,CAAA;AAAA,GAAA;AACF,CAAA;AAPE,OAAA,GAAA,IAAA,OAAA,EAAA,CAAA;AASF,MAAM,uBAAuB,KAAM,CAAA,aAAA;AAAA,EACjC,IAAI,0BAA2B,EAAA;AACjC,CAAA,CAAA;AAEa,MAAA,qBAAA,GAAwB,CAAC,KAEhC,KAAA;AACJ,EAAM,MAAA,OAAA,GAAU,WAAW,oBAAoB,CAAA,CAAA;AAC/C,EAAA,uBACG,IAAA,CAAA,oBAAA,CAAqB,QAArB,EAAA,EAA8B,OAAO,OACpC,EAAA,QAAA,EAAA;AAAA,oBAAC,GAAA,CAAA,mBAAA,EAAA,EAAoB,sBAAsB,OAAS,EAAA,CAAA;AAAA,IACnD,KAAM,CAAA,QAAA;AAAA,GACT,EAAA,CAAA,CAAA;AAEJ,EAAA;AAEO,MAAM,mBAAmB,MAAM;AACpC,EAAA,MAAM,EAAE,MAAA,EAAW,GAAA,UAAA,CAAW,oBAAoB,CAAA,CAAA;AAClD,EAAO,OAAA,MAAA,CAAA;AACT;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ToastNotification.js","sources":["../../src/notifications/ToastNotification.tsx"],"sourcesContent":["import { Icon } from \"@vuu-ui/vuu-ui-controls\";\nimport cx from \"clsx\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { useEffect, useState } from \"react\";\nimport { Portal } from \"../portal\";\nimport type { Notification } from \"./notificationTypes\";\n\nimport toastNotificationCss from \"./ToastNotification.css\";\n\nconst toastWidth = 300;\nconst toastContainerRightPadding = 50;\nconst toastDisplayDuration = 6000;\nconst horizontalTransitionDuration = 1000;\nconst toastHeight = 56;\nconst verticalTransitionDuration = 300;\n\nexport type ToastNotificationProps = {\n top: number;\n notification: Notification;\n animated?: boolean;\n};\n\nconst classBase = \"vuuToastNotification\";\n\nconst icon = {\n error: \"error\",\n info: \"info-circle\",\n success: \"tick\",\n warning: \"warn-triangle\",\n};\n\nexport const ToastNotification = (props: ToastNotificationProps) => {\n const { top, notification, animated = true } = props;\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-toast-notification\",\n css: toastNotificationCss,\n window: targetWindow,\n });\n\n const [right, setRight] = useState(-toastWidth - toastContainerRightPadding);\n\n useEffect(() => {\n setTimeout(() => setRight(toastContainerRightPadding));\n\n if (animated) {\n setTimeout(\n () => setRight(-toastWidth - toastContainerRightPadding),\n toastDisplayDuration + horizontalTransitionDuration\n );\n }\n }, [animated]);\n\n return (\n <Portal>\n <div\n className={cx(classBase, `${classBase}-${notification.type}`)}\n style={{\n height: toastHeight,\n right,\n width: toastWidth,\n top,\n transition: animated\n ? `right ${horizontalTransitionDuration}ms, top ${verticalTransitionDuration}ms `\n : \"none\",\n }}\n >\n <Icon name={icon[notification.type]} />\n <div className={`${classBase}-toastContent`}>\n <strong className={`${classBase}-toastHeader`}>\n {notification.header}\n </strong>\n <div>{notification.body}</div>\n </div>\n </div>\n </Portal>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;AAUA,MAAM,UAAa,GAAA,GAAA,CAAA;AACnB,MAAM,0BAA6B,GAAA,EAAA,CAAA;AACnC,MAAM,oBAAuB,GAAA,GAAA,CAAA;AAC7B,MAAM,4BAA+B,GAAA,GAAA,CAAA;AACrC,MAAM,WAAc,GAAA,EAAA,CAAA;AACpB,MAAM,0BAA6B,GAAA,GAAA,CAAA;AAQnC,MAAM,SAAY,GAAA,sBAAA,CAAA;AAElB,MAAM,IAAO,GAAA;AAAA,EACX,KAAO,EAAA,OAAA;AAAA,EACP,IAAM,EAAA,aAAA;AAAA,EACN,OAAS,EAAA,MAAA;AAAA,EACT,OAAS,EAAA,eAAA;AACX,CAAA,CAAA;AAEa,MAAA,iBAAA,GAAoB,CAAC,KAAkC,KAAA;AAClE,EAAA,MAAM,EAAE,GAAA,EAAK,YAAc,EAAA,QAAA,GAAW,MAAS,GAAA,KAAA,CAAA;AAC/C,EAAA,MAAM,eAAe,SAAU,EAAA,CAAA;AAC/B,EAAyB,wBAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,wBAAA;AAAA,IACR,GAAK,EAAA,oBAAA;AAAA,IACL,MAAQ,EAAA,YAAA;AAAA,GACT,CAAA,CAAA;AAED,EAAA,MAAM,CAAC,KAAO,EAAA,QAAQ,IAAI,QAAS,CAAA,CAAC,aAAa,0BAA0B,CAAA,CAAA;AAE3E,EAAA,SAAA,CAAU,MAAM;AACd,IAAW,UAAA,CAAA,MAAM,QAAS,CAAA,0BAA0B,CAAC,CAAA,CAAA;AAErD,IAAA,IAAI,QAAU,EAAA;AACZ,MAAA,UAAA;AAAA,QACE,MAAM,QAAA,CAAS,CAAC,UAAA,GAAa,0BAA0B,CAAA;AAAA,QACvD,oBAAuB,GAAA,4BAAA;AAAA,OACzB,CAAA;AAAA,KACF;AAAA,GACF,EAAG,CAAC,QAAQ,CAAC,CAAA,CAAA;AAEb,EAAA,2BACG,MACC,EAAA,EAAA,QAAA,kBAAA,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,GAAG,SAAW,EAAA,CAAA,EAAG,SAAS,CAAI,CAAA,EAAA,YAAA,CAAa,IAAI,CAAE,CAAA,CAAA;AAAA,MAC5D,KAAO,EAAA;AAAA,QACL,MAAQ,EAAA,WAAA;AAAA,QACR,KAAA;AAAA,QACA,KAAO,EAAA,UAAA;AAAA,QACP,GAAA;AAAA,QACA,YAAY,QACR,GAAA,CAAA,MAAA,EAAS,4BAA4B,CAAA,QAAA,EAAW,0BAA0B,CAC1E,GAAA,CAAA,GAAA,MAAA;AAAA,OACN;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,IAAK,EAAA,EAAA,IAAA,EAAM,IAAK,CAAA,YAAA,CAAa,IAAI,CAAG,EAAA,CAAA;AAAA,wBACpC,IAAA,CAAA,KAAA,EAAA,EAAI,SAAW,EAAA,CAAA,EAAG,SAAS,CAC1B,aAAA,CAAA,EAAA,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,YAAO,SAAW,EAAA,CAAA,EAAG,SAAS,CAAA,YAAA,CAAA,EAC5B,uBAAa,MAChB,EAAA,CAAA;AAAA,0BACA,GAAA,CAAC,KAAK,EAAA,EAAA,QAAA,EAAA,YAAA,CAAa,IAAK,EAAA,CAAA;AAAA,SAC1B,EAAA,CAAA;AAAA,OAAA;AAAA,KAAA;AAAA,GAEJ,EAAA,CAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"ToastNotification.js","sources":["../../src/notifications/ToastNotification.tsx"],"sourcesContent":["import { Icon } from \"@vuu-ui/vuu-ui-controls\";\nimport cx from \"clsx\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { useEffect, useState } from \"react\";\nimport { Portal } from \"../portal\";\nimport type { Notification } from \"./notificationTypes\";\n\nimport toastNotificationCss from \"./ToastNotification.css\";\n\nconst toastWidth = 300;\nconst toastContainerRightPadding = 50;\nconst toastDisplayDuration = 6000;\nconst horizontalTransitionDuration = 1000;\nconst toastHeight = 56;\nconst verticalTransitionDuration = 300;\n\nexport type ToastNotificationProps = {\n top: number;\n notification: Notification;\n animated?: boolean;\n};\n\nconst classBase = \"vuuToastNotification\";\n\nconst icon = {\n error: \"error\",\n info: \"info-circle\",\n success: \"tick\",\n warning: \"warn-triangle\",\n};\n\nexport const ToastNotification = (props: ToastNotificationProps) => {\n const { top, notification, animated = true } = props;\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-toast-notification\",\n css: toastNotificationCss,\n window: targetWindow,\n });\n\n const [right, setRight] = useState(-toastWidth - toastContainerRightPadding);\n\n useEffect(() => {\n setTimeout(() => setRight(toastContainerRightPadding));\n\n if (animated) {\n setTimeout(\n () => setRight(-toastWidth - toastContainerRightPadding),\n toastDisplayDuration + horizontalTransitionDuration,\n );\n }\n }, [animated]);\n\n return (\n <Portal>\n <div\n className={cx(classBase, `${classBase}-${notification.type}`)}\n style={{\n height: toastHeight,\n right,\n width: toastWidth,\n top,\n transition: animated\n ? `right ${horizontalTransitionDuration}ms, top ${verticalTransitionDuration}ms `\n : \"none\",\n }}\n >\n <Icon name={icon[notification.type]} />\n <div className={`${classBase}-toastContent`}>\n <strong className={`${classBase}-toastHeader`}>\n {notification.header}\n </strong>\n <div>{notification.body}</div>\n </div>\n </div>\n </Portal>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;AAUA,MAAM,UAAa,GAAA,GAAA,CAAA;AACnB,MAAM,0BAA6B,GAAA,EAAA,CAAA;AACnC,MAAM,oBAAuB,GAAA,GAAA,CAAA;AAC7B,MAAM,4BAA+B,GAAA,GAAA,CAAA;AACrC,MAAM,WAAc,GAAA,EAAA,CAAA;AACpB,MAAM,0BAA6B,GAAA,GAAA,CAAA;AAQnC,MAAM,SAAY,GAAA,sBAAA,CAAA;AAElB,MAAM,IAAO,GAAA;AAAA,EACX,KAAO,EAAA,OAAA;AAAA,EACP,IAAM,EAAA,aAAA;AAAA,EACN,OAAS,EAAA,MAAA;AAAA,EACT,OAAS,EAAA,eAAA;AACX,CAAA,CAAA;AAEa,MAAA,iBAAA,GAAoB,CAAC,KAAkC,KAAA;AAClE,EAAA,MAAM,EAAE,GAAA,EAAK,YAAc,EAAA,QAAA,GAAW,MAAS,GAAA,KAAA,CAAA;AAC/C,EAAA,MAAM,eAAe,SAAU,EAAA,CAAA;AAC/B,EAAyB,wBAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,wBAAA;AAAA,IACR,GAAK,EAAA,oBAAA;AAAA,IACL,MAAQ,EAAA,YAAA;AAAA,GACT,CAAA,CAAA;AAED,EAAA,MAAM,CAAC,KAAO,EAAA,QAAQ,IAAI,QAAS,CAAA,CAAC,aAAa,0BAA0B,CAAA,CAAA;AAE3E,EAAA,SAAA,CAAU,MAAM;AACd,IAAW,UAAA,CAAA,MAAM,QAAS,CAAA,0BAA0B,CAAC,CAAA,CAAA;AAErD,IAAA,IAAI,QAAU,EAAA;AACZ,MAAA,UAAA;AAAA,QACE,MAAM,QAAA,CAAS,CAAC,UAAA,GAAa,0BAA0B,CAAA;AAAA,QACvD,oBAAuB,GAAA,4BAAA;AAAA,OACzB,CAAA;AAAA,KACF;AAAA,GACF,EAAG,CAAC,QAAQ,CAAC,CAAA,CAAA;AAEb,EAAA,2BACG,MACC,EAAA,EAAA,QAAA,kBAAA,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,GAAG,SAAW,EAAA,CAAA,EAAG,SAAS,CAAI,CAAA,EAAA,YAAA,CAAa,IAAI,CAAE,CAAA,CAAA;AAAA,MAC5D,KAAO,EAAA;AAAA,QACL,MAAQ,EAAA,WAAA;AAAA,QACR,KAAA;AAAA,QACA,KAAO,EAAA,UAAA;AAAA,QACP,GAAA;AAAA,QACA,YAAY,QACR,GAAA,CAAA,MAAA,EAAS,4BAA4B,CAAA,QAAA,EAAW,0BAA0B,CAC1E,GAAA,CAAA,GAAA,MAAA;AAAA,OACN;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,IAAK,EAAA,EAAA,IAAA,EAAM,IAAK,CAAA,YAAA,CAAa,IAAI,CAAG,EAAA,CAAA;AAAA,wBACpC,IAAA,CAAA,KAAA,EAAA,EAAI,SAAW,EAAA,CAAA,EAAG,SAAS,CAC1B,aAAA,CAAA,EAAA,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,YAAO,SAAW,EAAA,CAAA,EAAG,SAAS,CAAA,YAAA,CAAA,EAC5B,uBAAa,MAChB,EAAA,CAAA;AAAA,0BACA,GAAA,CAAC,KAAK,EAAA,EAAA,QAAA,EAAA,YAAA,CAAa,IAAK,EAAA,CAAA;AAAA,SAC1B,EAAA,CAAA;AAAA,OAAA;AAAA,KAAA;AAAA,GAEJ,EAAA,CAAA,CAAA;AAEJ;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Portal.js","sources":["../../src/portal/Portal.tsx"],"sourcesContent":["import { ThemeAttributes, useThemeAttributes } from \"@vuu-ui/vuu-utils\";\nimport { ReactNode, useLayoutEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\n\nimport portalCss from \"./Portal.css\";\n\nexport interface PortalProps {\n /**\n * The children to render into the `container`.\n */\n children?: ReactNode;\n /**\n * An HTML element, component instance, or function that returns either.\n * The `container` will have the portal children appended to it.\n *\n * By default, it uses the body of the top-level document object,\n * so it's simply `document.body` most of the time.\n */\n container?: Element | (() => Element | null) | null;\n /**\n * Id of element into which portal will be rendered. If this node does not exist on the document,\n * it will be created for you. If more than one value is provided, the first element found will\n * be used.\n */\n id?: string | string[];\n /**\n * Callback invoked immediately after render (in layoutEffect). Can be\n * used to check position vis-a-vis viewport and adjust if out of bounds\n */\n onRender?: () => void;\n /**\n * Allow conditional rendering of this Portal, if false, will render nothing.\n * Defaults to true\n */\n open?: boolean;\n /**\n * ThemeAttributes can be passed in for cases where ContextMenu is\n * rendered via popup-service showPopup, outside the Context hierarchy.\n */\n themeAttributes?: ThemeAttributes;\n}\n\nfunction getContainer(container: PortalProps[\"container\"]) {\n return typeof container === \"function\" ? container() : container;\n}\n\nconst DEFAULT_ID = [\"vuu-dialog-portal-root\", \"vuu-portal-root\"];\n\nconst getFirstAvailableElementById = (id: string | string[]) => {\n if (Array.isArray(id)) {\n for (const i of id) {\n const element = document.getElementById(i);\n if (element) {\n return element;\n }\n }\n } else {\n return document.getElementById(id);\n }\n return null;\n};\n\n/**\n * Portals provide a first-class way to render children into a DOM node\n * that exists outside the DOM hierarchy of the parent component.\n */\nexport const Portal = ({\n children,\n container: containerProp = document.body,\n id = DEFAULT_ID,\n onRender,\n open = true,\n themeAttributes,\n}: PortalProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-portal\",\n css: portalCss,\n window: targetWindow,\n });\n\n const [mounted, setMounted] = useState(false);\n const portalRef = useRef<HTMLElement | null>(null);\n const container = getContainer(containerProp) ?? document.body;\n const [themeClass, densityClass, dataMode] =\n useThemeAttributes(themeAttributes);\n\n useLayoutEffect(() => {\n const root = getFirstAvailableElementById(id);\n if (root) {\n portalRef.current = root;\n } else {\n portalRef.current = document.createElement(\"div\");\n portalRef.current.id =\n typeof id === \"string\"\n ? id\n : id.length > 0\n ? (id.at(-1) as string)\n : \"vuu-portal-root\";\n }\n const el = portalRef.current;\n if (!container.contains(el)) {\n container.appendChild(el);\n }\n el.classList.add(themeClass, densityClass);\n el.dataset.mode = dataMode;\n setMounted(true);\n }, [id, container, themeClass, densityClass, dataMode]);\n\n useLayoutEffect(() => {\n requestAnimationFrame(() => {\n onRender?.();\n });\n }, [onRender]);\n\n if (open && mounted && portalRef.current && children) {\n return createPortal(children, portalRef.current);\n }\n\n return null;\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Portal.js","sources":["../../src/portal/Portal.tsx"],"sourcesContent":["import { ThemeAttributes, useThemeAttributes } from \"@vuu-ui/vuu-utils\";\nimport { ReactNode, useLayoutEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\n\nimport portalCss from \"./Portal.css\";\n\nexport interface PortalProps {\n /**\n * The children to render into the `container`.\n */\n children?: ReactNode;\n /**\n * An HTML element, component instance, or function that returns either.\n * The `container` will have the portal children appended to it.\n *\n * By default, it uses the body of the top-level document object,\n * so it's simply `document.body` most of the time.\n */\n container?: Element | (() => Element | null) | null;\n /**\n * Id of element into which portal will be rendered. If this node does not exist on the document,\n * it will be created for you. If more than one value is provided, the first element found will\n * be used.\n */\n id?: string | string[];\n /**\n * Callback invoked immediately after render (in layoutEffect). Can be\n * used to check position vis-a-vis viewport and adjust if out of bounds\n */\n onRender?: () => void;\n /**\n * Allow conditional rendering of this Portal, if false, will render nothing.\n * Defaults to true\n */\n open?: boolean;\n /**\n * ThemeAttributes can be passed in for cases where ContextMenu is\n * rendered via popup-service showPopup, outside the Context hierarchy.\n */\n themeAttributes?: ThemeAttributes;\n}\n\nfunction getContainer(container: PortalProps[\"container\"]) {\n return typeof container === \"function\" ? container() : container;\n}\n\nconst DEFAULT_ID = [\"vuu-dialog-portal-root\", \"vuu-portal-root\"];\n\nconst getFirstAvailableElementById = (id: string | string[]) => {\n if (Array.isArray(id)) {\n for (const i of id) {\n const element = document.getElementById(i);\n if (element) {\n return element;\n }\n }\n } else {\n return document.getElementById(id);\n }\n return null;\n};\n\n/**\n * Portals provide a first-class way to render children into a DOM node\n * that exists outside the DOM hierarchy of the parent component.\n */\nexport const Portal = ({\n children,\n container: containerProp = document.body,\n id = DEFAULT_ID,\n onRender,\n open = true,\n themeAttributes,\n}: PortalProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-portal\",\n css: portalCss,\n window: targetWindow,\n });\n\n const [mounted, setMounted] = useState(false);\n const portalRef = useRef<HTMLElement | null>(null);\n const container = getContainer(containerProp) ?? document.body;\n const [themeClass, densityClass, dataMode] =\n useThemeAttributes(themeAttributes);\n\n useLayoutEffect(() => {\n const root = getFirstAvailableElementById(id);\n if (root) {\n portalRef.current = root;\n } else {\n portalRef.current = document.createElement(\"div\");\n portalRef.current.id =\n typeof id === \"string\"\n ? id\n : id.length > 0\n ? (id.at(-1) as string)\n : \"vuu-portal-root\";\n }\n const el = portalRef.current;\n if (!container.contains(el)) {\n container.appendChild(el);\n }\n el.classList.add(themeClass, densityClass);\n el.dataset.mode = dataMode;\n setMounted(true);\n }, [id, container, themeClass, densityClass, dataMode]);\n\n useLayoutEffect(() => {\n requestAnimationFrame(() => {\n onRender?.();\n });\n }, [onRender]);\n\n if (open && mounted && portalRef.current && children) {\n return createPortal(children, portalRef.current);\n }\n\n return null;\n};\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useTooltip.js","sources":["../../src/tooltip/useTooltip.ts"],"sourcesContent":["import { queryClosest, useId } from \"@vuu-ui/vuu-utils\";\nimport { MouseEvent, ReactNode, useCallback, useRef, useState } from \"react\";\nimport { TooltipProps } from \"./Tooltip\";\nimport { TooltipPlacement } from \"./useTooltipAnchoredPosition\";\n\nexport interface TooltipHookProps {\n anchorQuery?: string;\n id: string;\n placement?: TooltipPlacement | TooltipPlacement[];\n tooltipContent: ReactNode;\n}\n\nexport const useTooltip = ({\n anchorQuery = \"*\",\n id: idProp,\n placement = [\"right\", \"above\", \"below\"],\n tooltipContent,\n}: TooltipHookProps) => {\n const hideTooltipRef = useRef<() => void>();\n const isHoveringRef = useRef(false);\n const anchorElementRef = useRef<HTMLElement | null>(null);\n const mouseEnterTimerRef = useRef<number | undefined>();\n const mouseLeaveTimerRef = useRef<number | undefined>();\n const [tooltipProps, setTooltipProps] = useState<TooltipProps | undefined>();\n\n const id = useId(idProp);\n\n const escapeListener = useCallback((evt: KeyboardEvent) => {\n if (evt.key === \"Escape\") {\n hideTooltipRef.current?.();\n }\n }, []);\n\n hideTooltipRef.current = useCallback(() => {\n setTooltipProps(undefined);\n document.removeEventListener(\"keydown\", escapeListener);\n }, [escapeListener]);\n\n const handleMouseEnterTooltip = useCallback(() => {\n window.clearTimeout(mouseLeaveTimerRef.current);\n }, []);\n\n const handleMouseLeaveTooltip = useCallback(() => {\n hideTooltipRef.current?.();\n }, []);\n\n const hideTooltip = useCallback((defer = 0) => {\n if (mouseEnterTimerRef.current) {\n window.clearTimeout(mouseEnterTimerRef.current);\n mouseEnterTimerRef.current = undefined;\n } else if (hideTooltipRef.current) {\n if (defer === 0) {\n hideTooltipRef.current();\n } else {\n mouseLeaveTimerRef.current = window.setTimeout(\n hideTooltipRef.current,\n defer\n );\n }\n }\n }, []);\n\n const showTooltip = useCallback(\n (ref = anchorElementRef) => {\n const { current: anchorEl } = ref;\n if (anchorEl) {\n setTooltipProps({\n anchorElement: ref,\n children: tooltipContent,\n id: `${id}-tooltip`,\n onMouseEnter: handleMouseEnterTooltip,\n onMouseLeave: handleMouseLeaveTooltip,\n placement: placement,\n });\n // register ESC listener\n document.addEventListener(\"keydown\", escapeListener);\n }\n mouseEnterTimerRef.current = undefined;\n hideTooltip(isHoveringRef.current ? 3000 : 1000);\n },\n [\n escapeListener,\n handleMouseEnterTooltip,\n handleMouseLeaveTooltip,\n hideTooltip,\n id,\n placement,\n tooltipContent,\n ]\n );\n\n const handleMouseEnter = useCallback(\n (evt: MouseEvent) => {\n isHoveringRef.current = true;\n const el = queryClosest(evt.target, anchorQuery);\n if (el) {\n console.log(`el ${el.classList}`);\n anchorElementRef.current = el;\n mouseEnterTimerRef.current = window.setTimeout(showTooltip, 800);\n }\n },\n [anchorQuery, showTooltip]\n );\n\n const handleMouseLeave = useCallback(() => {\n isHoveringRef.current = false;\n hideTooltip(200);\n }, [hideTooltip]);\n\n const anchorProps = {\n \"aria-describedby\": `${id}-tooltip`,\n onMouseEnter: handleMouseEnter,\n onMouseLeave: handleMouseLeave,\n };\n\n return {\n anchorProps,\n hideTooltip,\n showTooltip,\n tooltipProps,\n };\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useTooltip.js","sources":["../../src/tooltip/useTooltip.ts"],"sourcesContent":["import { queryClosest, useId } from \"@vuu-ui/vuu-utils\";\nimport { MouseEvent, ReactNode, useCallback, useRef, useState } from \"react\";\nimport { TooltipProps } from \"./Tooltip\";\nimport { TooltipPlacement } from \"./useTooltipAnchoredPosition\";\n\nexport interface TooltipHookProps {\n anchorQuery?: string;\n id: string;\n placement?: TooltipPlacement | TooltipPlacement[];\n tooltipContent: ReactNode;\n}\n\nexport const useTooltip = ({\n anchorQuery = \"*\",\n id: idProp,\n placement = [\"right\", \"above\", \"below\"],\n tooltipContent,\n}: TooltipHookProps) => {\n const hideTooltipRef = useRef<() => void>();\n const isHoveringRef = useRef(false);\n const anchorElementRef = useRef<HTMLElement | null>(null);\n const mouseEnterTimerRef = useRef<number | undefined>();\n const mouseLeaveTimerRef = useRef<number | undefined>();\n const [tooltipProps, setTooltipProps] = useState<TooltipProps | undefined>();\n\n const id = useId(idProp);\n\n const escapeListener = useCallback((evt: KeyboardEvent) => {\n if (evt.key === \"Escape\") {\n hideTooltipRef.current?.();\n }\n }, []);\n\n hideTooltipRef.current = useCallback(() => {\n setTooltipProps(undefined);\n document.removeEventListener(\"keydown\", escapeListener);\n }, [escapeListener]);\n\n const handleMouseEnterTooltip = useCallback(() => {\n window.clearTimeout(mouseLeaveTimerRef.current);\n }, []);\n\n const handleMouseLeaveTooltip = useCallback(() => {\n hideTooltipRef.current?.();\n }, []);\n\n const hideTooltip = useCallback((defer = 0) => {\n if (mouseEnterTimerRef.current) {\n window.clearTimeout(mouseEnterTimerRef.current);\n mouseEnterTimerRef.current = undefined;\n } else if (hideTooltipRef.current) {\n if (defer === 0) {\n hideTooltipRef.current();\n } else {\n mouseLeaveTimerRef.current = window.setTimeout(\n hideTooltipRef.current,\n defer,\n );\n }\n }\n }, []);\n\n const showTooltip = useCallback(\n (ref = anchorElementRef) => {\n const { current: anchorEl } = ref;\n if (anchorEl) {\n setTooltipProps({\n anchorElement: ref,\n children: tooltipContent,\n id: `${id}-tooltip`,\n onMouseEnter: handleMouseEnterTooltip,\n onMouseLeave: handleMouseLeaveTooltip,\n placement: placement,\n });\n // register ESC listener\n document.addEventListener(\"keydown\", escapeListener);\n }\n mouseEnterTimerRef.current = undefined;\n hideTooltip(isHoveringRef.current ? 3000 : 1000);\n },\n [\n escapeListener,\n handleMouseEnterTooltip,\n handleMouseLeaveTooltip,\n hideTooltip,\n id,\n placement,\n tooltipContent,\n ],\n );\n\n const handleMouseEnter = useCallback(\n (evt: MouseEvent) => {\n isHoveringRef.current = true;\n const el = queryClosest(evt.target, anchorQuery);\n if (el) {\n console.log(`el ${el.classList}`);\n anchorElementRef.current = el;\n mouseEnterTimerRef.current = window.setTimeout(showTooltip, 800);\n }\n },\n [anchorQuery, showTooltip],\n );\n\n const handleMouseLeave = useCallback(() => {\n isHoveringRef.current = false;\n hideTooltip(200);\n }, [hideTooltip]);\n\n const anchorProps = {\n \"aria-describedby\": `${id}-tooltip`,\n onMouseEnter: handleMouseEnter,\n onMouseLeave: handleMouseLeave,\n };\n\n return {\n anchorProps,\n hideTooltip,\n showTooltip,\n tooltipProps,\n };\n};\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
- "version": "0.8.81",
2
+ "version": "0.8.83",
3
3
  "description": "VUU popup components - Context Menu, Dialog etc",
4
4
  "author": "heswell",
5
5
  "license": "Apache-2.0",
6
6
  "dependencies": {
7
- "@salt-ds/core": "1.27.1",
7
+ "@salt-ds/core": "1.34.0",
8
8
  "@salt-ds/styles": "0.2.1",
9
9
  "@salt-ds/window": "0.1.1",
10
- "@vuu-ui/vuu-data-types": "0.8.81",
11
- "@vuu-ui/vuu-layout": "0.8.81",
12
- "@vuu-ui/vuu-utils": "0.8.81",
13
- "@vuu-ui/vuu-ui-controls": "0.8.81"
10
+ "@vuu-ui/vuu-data-types": "0.8.83",
11
+ "@vuu-ui/vuu-layout": "0.8.83",
12
+ "@vuu-ui/vuu-utils": "0.8.83",
13
+ "@vuu-ui/vuu-ui-controls": "0.8.83"
14
14
  },
15
15
  "peerDependencies": {
16
16
  "clsx": "^2.0.0",