@vuu-ui/vuu-popups 0.8.87 → 0.8.88
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.
- package/cjs/menu/ContextMenu.js.map +1 -1
- package/cjs/menu/MenuList.js.map +1 -1
- package/cjs/menu/context-menu-provider.js.map +1 -1
- package/cjs/menu/use-keyboard-navigation.js.map +1 -1
- package/cjs/menu/useContextMenu.js.map +1 -1
- package/cjs/notifications/NotificationsCenter.js.map +1 -1
- package/cjs/notifications/ToastNotification.js.map +1 -1
- package/cjs/popup-menu/PopupMenu.js.map +1 -1
- package/cjs/portal/Portal.js.map +1 -1
- package/cjs/prompt/Prompt.js.map +1 -1
- package/cjs/tooltip/useTooltip.js.map +1 -1
- package/esm/menu/ContextMenu.js.map +1 -1
- package/esm/menu/MenuList.js.map +1 -1
- package/esm/menu/context-menu-provider.js.map +1 -1
- package/esm/menu/use-keyboard-navigation.js.map +1 -1
- package/esm/menu/useContextMenu.js.map +1 -1
- package/esm/notifications/NotificationsCenter.js.map +1 -1
- package/esm/notifications/ToastNotification.js.map +1 -1
- package/esm/popup-menu/PopupMenu.js.map +1 -1
- package/esm/portal/Portal.js.map +1 -1
- package/esm/prompt/Prompt.js.map +1 -1
- package/esm/tooltip/useTooltip.js.map +1 -1
- package/package.json +5 -5
- package/types/menu/context-menu-provider.d.ts +1 -1
- package/types/menu/use-keyboard-navigation.d.ts +1 -1
- package/types/notifications/NotificationsCenter.d.ts +1 -1
- package/types/portal/Portal.d.ts +1 -1
- package/types/tooltip/useTooltip.d.ts +1 -1
|
@@ -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
|
|
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":";;;;;;;;;;;;;AAiBA,MAAM,OAAO,MAAM,KAAA,CAAA,CAAA;AAEZ,MAAM,cAAc,CAAC;AAAA,EAC1B,WAAAA,EAAAA,YAAAA;AAAA,EACA,mBAAA;AAAA,EACA,QAAU,EAAA,YAAA;AAAA,EACV,SAAA;AAAA,EACA,EAAI,EAAA,MAAA;AAAA,EACJ,UAAU,MAAM,KAAA,CAAA;AAAA,EAChB,QAAW,GAAA,EAAE,CAAG,EAAA,CAAA,EAAG,GAAG,CAAE,EAAA;AAAA,EACxB,KAAA;AAAA,EACA,GAAG,aAAA;AACL,CAAwB,KAAA;AACtB,EAAM,MAAA,EAAA,GAAKC,eAAM,MAAM,CAAA,CAAA;AACvB,EAAM,MAAA,YAAA,GAAeC,aAAoC,IAAI,CAAA,CAAA;AAC7D,EAAA,MAAM,CAAC,KAAO,EAAA,OAAO,CAAI,GAAAC,uCAAA,CAAoB,cAAc,EAAE,CAAA,CAAA;AAC7D,EAAM,MAAA,sBAAA,GAAyBD,aAAO,mBAAmB,CAAA,CAAA;AACzD,EAAM,MAAA,oBAAA,GAAuBE,kBAAY,MAAM;AAC7C,IAAA,sBAAA,CAAuB,OAAU,GAAA,KAAA,CAAA;AAAA,GACnC,EAAG,EAAE,CAAA,CAAA;AAEL,EAAA,MAAM,cAAiB,GAAAA,iBAAA;AAAA,IACrB,CAAC,UAAuB,KAAA;AACtB,MAAM,MAAA,QAAA,GAAW,UAAW,CAAA,KAAA,CAAM,CAAC,CAAA,CAAA;AACnC,MAAA,MAAM,EAAE,MAAA,EAAQ,OAAQ,EAAA,GAAI,QAAQ,QAAQ,CAAA,CAAA;AAC5C,MAAA,YAAA,CAAa,QAAQ,EAAE,CAAA,CAAA;AACvB,MAAQ,OAAA,CAAA;AAAA,QACN,IAAM,EAAA,aAAA;AAAA,QACN,MAAQ,EAAA,MAAA;AAAA,QACR,OAAA;AAAA,OACD,CAAA,CAAA;AAAA,KACH;AAAA,IACA,CAAC,OAAS,EAAA,EAAA,EAAI,OAAO,CAAA;AAAA,GACvB,CAAA;AAEA,EAAM,MAAA;AAAA,IACJ,SAAA;AAAA,IACA,aAAA;AAAA,IACA,QAAU,EAAA,UAAA;AAAA,IACV,SAAA;AAAA,IACA,YAAA;AAAA,MACEC,qBAAW,CAAA;AAAA;AAAA,IAEb,EAAA,EAAI,GAAG,EAAE,CAAA,CAAA;AAAA,IACT,UAAY,EAAA,cAAA;AAAA,IACZ,gBAAkB,EAAA,oBAAA;AAAA,IAClB,QAAA;AAAA,GACD,CAAA,CAAA;AACD,EAAA,YAAA,CAAa,OAAU,GAAA,SAAA,CAAA;AAEvB,EAAA,MAAM,eAAkB,GAAAD,iBAAA;AAAA,IACtB,CAAC,KAAK,MAAW,KAAA;AACf,MAAA,sBAAA,CAAuB,OAAU,GAAA,IAAA,CAAA;AACjC,MAAU,SAAA,EAAA,CAAA;AACV,MAAA,IAAI,WAAW,UAAY,EAAA;AAGzB,QAAQ,OAAA,CAAA;AAAA,UACN,KAAO,EAAA,GAAA;AAAA,UACP,IAAM,EAAA,UAAA;AAAA,SACP,CAAA,CAAA;AAAA,OACH;AAAA,KACF;AAAA,IACA,CAAC,WAAW,OAAO,CAAA;AAAA,GACrB,CAAA;AAEA,EAAA,MAAM,0BAA0B,MAAM;AAAA,GAEtC,CAAA;AAEA,EAAM,MAAA,QAAA,GAAW,UAAU,MAAS,GAAA,CAAA,CAAA;AAEpC,EAAM,MAAA,cAAA,GAAiB,CAAC,CAAc,KAAA;AACpC,IAAA,IAAI,KAAK,QAAU,EAAA;AACjB,MAAO,OAAA,KAAA,CAAA,CAAA;AAAA,KACF,MAAA;AACL,MAAA,MAAM,EAAE,EAAAE,EAAAA,GAAAA,EAAO,GAAA,SAAA,CAAU,IAAI,CAAC,CAAA,CAAA;AAC9B,MAAOA,OAAAA,GAAAA,CAAAA;AAAA,KACT;AAAA,GACF,CAAA;AAEA,EACE,uBAAAC,cAAA,CAAAC,mBAAA,EAAA,EACG,QAAU,EAAA,SAAA,CAAA,GAAA,CAAI,CAAC,EAAE,EAAI,EAAA,MAAA,EAAQ,IAAM,EAAA,GAAA,EAAO,EAAA,CAAA,EAAG,GAAQ,KAAA;AACpD,IAAM,MAAA,WAAA,GAAc,eAAe,CAAC,CAAA,CAAA;AACpC,IAAA,2CACGC,aAAQ,EAAA,EAAA,GAAGT,cAAa,GAAK,EAAA,CAAA,EAAG,UAAU,YACzC,EAAA,kBAAAO,cAAA;AAAA,MAACG,oBAAA;AAAA,MAAA;AAAA,QACC,aAAe,EAAA,EAAE,OAAS,EAAA,QAAA,CAAS,IAAK,EAAA;AAAA,QACxC,SAAU,EAAA,UAAA;AAAA,QACV,QAAA,EAAU,EAAE,IAAA,EAAM,GAAI,EAAA;AAAA,QAEtB,QAAA,kBAAAC,mBAAA;AAAA,UAACC,iBAAA;AAAA,UAAA;AAAA,YACE,GAAG,aAAA;AAAA,YACJ,qBAAqB,sBAAuB,CAAA,OAAA;AAAA,YAC5C,gBAAkB,EAAA,WAAA;AAAA,YAClB,SAAA;AAAA,YACA,EAAI,EAAA,MAAA;AAAA,YACJ,QAAQ,CAAM,KAAA,CAAA;AAAA,YACd,GAAK,EAAA,CAAA;AAAA,YACL,aAAA;AAAA,YACA,UAAY,EAAA,cAAA;AAAA,YACZ,mBAAqB,EAAA,uBAAA;AAAA,YACrB,WAAa,EAAA,eAAA;AAAA,YACb,QAAU,EAAA,UAAA;AAAA,YACV,KAAA;AAAA,YACA,QAAU,EAAA,CAAA,KAAM,GAAI,CAAA,MAAA,GAAS,IAAI,CAAI,GAAA,KAAA,CAAA;AAAA,WAAA;AAAA,UAEpC,MAAM,MAAM,CAAA;AAAA,SACf;AAAA,OAAA;AAAA,KAEJ,CAAA,CAAA;AAAA,GAEH,CACH,EAAA,CAAA,CAAA;AAEJ,EAAA;AAEA,WAAA,CAAY,WAAc,GAAA,aAAA;;;;"}
|
package/cjs/menu/MenuList.js.map
CHANGED
|
@@ -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":";;;;;;;;;;;AAqBA,MAAM,SAAY,GAAA,aAAA,CAAA;AAEX,MAAM,SAAY,GAAA,sBAAOA,cAAA,CAAA,IAAA,EAAA,EAAG,WAAU,qBAAsB,EAAA,EAAA;AAEtD,MAAA,eAAA,GAAkB,CAAC,KAAA,KAC9B,KAAM,CAAA,IAAA,KAAS,iBAAiB,CAAC,CAAC,KAAM,CAAA,KAAA,CAAM,YAAY,EAAA;AAgBrD,MAAM,gBAAwC,MAAM,KAAA;AAEpD,MAAM,WAAW,CAAC;AAAA,EACvB,QAAA;AAAA,EACA,GAAA;AAAA,EACA,OAAA;AAAA,EACA,GAAG,KAAA;AACL,CAAqB,KAAA;AACnB,EAAA,uBAAQA,cAAA,CAAA,KAAA,EAAA,EAAK,GAAG,KAAA,EAAQ,QAAS,EAAA,CAAA,CAAA;AACnC,EAAA;AAKA,MAAM,gBAAgB,CAAC,EAAE,QAAS,EAAA,2DAC7B,QAAS,EAAA,CAAA,CAAA;AAEd,aAAA,CAAc,WAAc,GAAA,eAAA,CAAA;AAC5B,QAAA,CAAS,KAAQ,GAAA,aAAA,CAAA;AAEjB,MAAM,iBAAiB,CAAC,IAAA,KACtB,KAAM,CAAA,cAAA,CAAe,IAAI,CACzB,IAAA,OAAO,IAAK,CAAA,IAAA,KAAS,YACrB,aAAiB,IAAA,IAAA,CAAK,IAClB,GAAA,IAAA,CAAK,KAAK,WACV,GAAA,KAAA,CAAA,CAAA;AAEC,MAAM,eAAkB,GAAA,CAC7B,IAEA,KAAA,cAAA,CAAe,IAAI,CAAM,KAAA,gBAAA;AAE3B,MAAM,OAAU,GAAA,CAAC,KAAwB,KAAA,KAAA,CAAM,MAAM,WAAW,CAAA,CAAA;AAoBzD,MAAM,WAAW,CAAC;AAAA,EACvB,mBAAA;AAAA,EACA,gBAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,qBAAA;AAAA,EACA,cAAgB,EAAA,kBAAA;AAAA,EAChB,EAAI,EAAA,MAAA;AAAA,EACJ,MAAA;AAAA,EACA,aAAA;AAAA,EACA,mBAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA;AAAA,EACA,QAAU,EAAA,UAAA;AAAA,EACV,GAAG,KAAA;AACL,CAAqB,KAAA;AACnB,EAAA,MAAM,eAAeC,gBAAU,EAAA,CAAA;AAC/B,EAAyBC,+BAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,eAAA;AAAA,IACR,GAAK,EAAAC,UAAA;AAAA,IACL,MAAQ,EAAA,YAAA;AAAA,GACT,CAAA,CAAA;AAED,EAAM,MAAA,EAAA,GAAKC,eAAM,MAAM,CAAA,CAAA;AACvB,EAAM,MAAA,IAAA,GAAOC,aAAuB,IAAI,CAAA,CAAA;AAGxC,EAAA,MAAM,aAAaC,aAAQ,CAAA,0BAAU,GAAI,EAAA,EAAG,EAAE,CAAA,CAAA;AAE9C,EAAM,MAAA,cAAA,GAAiB,CAAC,GAAgB,KAAA;AACtC,IAAA,MAAM,KAAK,IAAK,CAAA,OAAA,EAAS,aAAc,CAAA,CAAA,sBAAA,EAAyB,GAAG,CAAI,EAAA,CAAA,CAAA,CAAA;AACvE,IAAI,EAAA,EAAA,EAAA,IAAM,UAAa,GAAA,EAAA,CAAG,EAAE,CAAA,CAAA;AAAA,GAC9B,CAAA;AAEA,EAAA,MAAM,EAAE,YAAA,EAAc,gBAAkB,EAAA,SAAA,KAAcC,2CAAsB,CAAA;AAAA,IAC1E,KAAO,EAAA,KAAA,CAAM,QAAS,CAAA,KAAA,CAAM,QAAQ,CAAA;AAAA,IACpC,qBAAA;AAAA,IACA,gBAAkB,EAAA,kBAAA;AAAA,IAClB,UAAY,EAAA,cAAA;AAAA,IACZ,WAAa,EAAA,mBAAA;AAAA,IACb,UAAA;AAAA,IACA,WAAA;AAAA,GACD,CAAA,CAAA;AAED,EAAM,MAAA,mBAAA,GAAsB,gBAAoB,IAAA,KAAA,CAAA,GAAY,YAAe,GAAA,CAAA,CAAA,CAAA;AAE3E,EAAAC,qBAAA,CAAgB,MAAM;AACpB,IAAI,IAAA,gBAAA,KAAqB,UAAa,mBAAqB,EAAA;AACzD,MAAA,IAAA,CAAK,SAAS,KAAM,EAAA,CAAA;AAAA,KACtB;AAAA,GACC,EAAA,CAAC,mBAAqB,EAAA,gBAAgB,CAAC,CAAA,CAAA;AAE1C,EAAM,MAAA,mBAAA,GAAsB,MAC1B,gBAAqB,KAAA,KAAA,CAAA,IAAa,qBAAqB,CACnD,CAAA,GAAA,KAAA,CAAA,GACA,UAAW,CAAA,GAAA,CAAI,gBAAgB,CAAA,CAAA;AAErC,EAAA,SAAS,aAAgB,GAAA;AACvB,IAAA,MAAM,yBAA4B,GAAA;AAAA,MAChC,GAAG,aAAA;AAAA,MACH,IAAM,EAAA,UAAA;AAAA,KACR,CAAA;AAEA,IAAA,MAAM,SAAY,GAAA,CAChB,YACA,EAAA,QAAA,EACA,aAEA,QACI,GAAA;AAAA,sBACER,cAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,SAAU,EAAA,kBAAA;AAAA,UACV,WAAW,EAAA,QAAA;AAAA,SAAA;AAAA,QACP,MAAA;AAAA,OACN;AAAA,KACF,CAAE,MAAO,CAAA,YAAY,CACrB,GAAA,YAAA,CAAA;AAEN,IAAA,SAAS,cACP,CAAA,IAAA,EACA,KACA,EAAA,GAAA,EACA,QACA,EAAA;AACA,MAAM,MAAA;AAAA,QACJ,QAAAS,EAAAA,SAAAA;AAAA,QACA,SAAAC,EAAAA,UAAAA;AAAA,QACA,WAAa,EAAA,QAAA;AAAA,QACb,EAAI,EAAA,MAAA;AAAA,QACJ,YAAA;AAAA,QACA,KAAA;AAAA,QACA,GAAGC,MAAAA;AAAA,UACD,KAAM,CAAA,KAAA,CAAA;AACV,MAAM,MAAA,UAAA,GAAa,gBAAgB,KAAK,CAAA,CAAA;AACxC,MAAM,MAAA,cAAA,GAAiB,cAAc,gBAAqB,KAAA,MAAA,CAAA;AAC1D,MAAA,MAAM,eAAe,cAAiB,GAAA,CAAA,EAAG,EAAE,CAAA,CAAA,EAAI,MAAM,CAAK,CAAA,GAAA,KAAA,CAAA,CAAA;AAE1D,MAAA,MAAM,SACH,GAAA,KAAA,IAAS,OAAOF,SAAAA,KAAa,WAAYA,SAAW,GAAA,KAAA,CAAA,CAAA;AAEvD,MAAK,IAAA,CAAA,IAAA;AAAA,wBACHT,cAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACE,GAAGW,MAAAA;AAAA,YACH,GAAG,yBAAA;AAAA,YACH,GAAG,gBAAA;AAAA,cACF,MAAA;AAAA,cACA,GAAA;AAAA,cACA,MAAM,GAAO,IAAA,MAAA;AAAA,cACb,gBAAA;AAAA,cACA,mBAAA;AAAA,cACAD,UAAAA;AAAA,cACA,YAAA;AAAA,aACF;AAAA,YACA,eAAe,EAAA,YAAA;AAAA,YACf,iBAAe,UAAc,IAAA,KAAA,CAAA;AAAA,YAC7B,iBAAe,cAAkB,IAAA,KAAA,CAAA;AAAA,YACjC,YAAY,EAAA,SAAA;AAAA,YAEX,QAAA,EAAA,UAAA,GACG,SAAU,CAAA,KAAA,IAASD,SAAU,EAAA,QAAA,EAAU,QAAQ,CAC/C,GAAA,SAAA,CAAUA,SAAU,EAAA,QAAA,EAAU,QAAQ,CAAA;AAAA,WAAA;AAAA,SAC5C;AAAA,OACF,CAAA;AAAA,KAEF;AAEA,IAAA,MAAM,YAA4B,EAAC,CAAA;AAEnC,IAAI,IAAA,QAAA,CAAS,SAAS,CAAG,EAAA;AACvB,MAAM,MAAA,QAAA,GAAW,QAAS,CAAA,IAAA,CAAK,OAAO,CAAA,CAAA;AACtC,MAAS,QAAA,CAAA,OAAA,CAAQ,CAAC,KAAA,EAAO,GAAQ,KAAA;AAC/B,QAAe,cAAA,CAAA,SAAA,EAAW,KAAO,EAAA,GAAA,EAAK,QAAQ,CAAA,CAAA;AAAA,OAC/C,CAAA,CAAA;AAAA,KACH;AAEA,IAAO,OAAA,SAAA,CAAA;AAAA,GACT;AAEA,EACE,uBAAAT,cAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACE,GAAG,KAAA;AAAA,MACH,GAAG,SAAA;AAAA,MACJ,yBAAuB,mBAAoB,EAAA;AAAA,MAC3C,SAAA,EAAW,EAAG,CAAA,SAAA,EAAW,SAAW,EAAA;AAAA,QAClC,CAAC,CAAA,EAAG,SAAS,CAAA,iBAAA,CAAmB,GAAG,gBAAqB,KAAA,KAAA,CAAA;AAAA,OACzD,CAAA;AAAA,MACD,aAAW,MAAU,IAAA,KAAA,CAAA;AAAA,MACrB,EAAA;AAAA,MACA,GAAK,EAAA,IAAA;AAAA,MACL,IAAK,EAAA,MAAA;AAAA,MAEJ,QAAc,EAAA,aAAA,EAAA;AAAA,KAAA;AAAA,GACjB,CAAA;AAEJ,EAAA;AAEA,MAAM,gBAAA,GAAmB,CACvB,MACA,EAAA,GAAA,EACA,KACA,cACA,EAAA,YAAA,EACA,WACA,YACI,MAAA;AAAA,EACJ,EAAA,EAAI,YAAY,MAAM,CAAA,CAAA;AAAA,EACtB,KAAK,GAAO,IAAA,GAAA;AAAA,EACZ,YAAc,EAAA,GAAA;AAAA,EACd,SAAA,EAAW,EAAG,CAAA,aAAA,EAAe,SAAW,EAAA;AAAA,IACtC,uBAAyB,EAAA,YAAA;AAAA,IACzB,gBAAgB,GAAQ,KAAA,cAAA;AAAA,IACxB,cAAc,YAAiB,KAAA,GAAA;AAAA,GAChC,CAAA;AACH,CAAA,CAAA,CAAA;AAEA,QAAA,CAAS,WAAc,GAAA,UAAA;;;;;;;;;"}
|
|
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
|
|
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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"}
|
|
@@ -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
|
|
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;;;;"}
|
|
@@ -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\"
|
|
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":"PopupMenu.js","sources":["../../src/popup-menu/PopupMenu.tsx"],"sourcesContent":["import { MenuActionHandler, MenuBuilder } from \"@vuu-ui/vuu-data-types\";\nimport { Icon, IconButton } from \"@vuu-ui/vuu-ui-controls\";\nimport { useId } from \"@vuu-ui/vuu-utils\";\nimport { Button, ButtonProps } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport cx from \"clsx\";\nimport { HTMLAttributes, RefObject } from \"react\";\nimport { PopupPlacement } from \"../popup/Popup\";\nimport { PopupCloseReason } from \"../popup/popup-service\";\nimport { usePopupMenu } from \"./usePopupMenu\";\n\nimport popupMenuCss from \"./PopupMenu.css\";\n\nconst classBase = \"vuuPopupMenu\";\n\nexport type MenuCloseHandler = (reason?: PopupCloseReason) => void;\n\nexport interface PopupMenuProps extends HTMLAttributes<HTMLButtonElement> {\n anchorElement?: RefObject<HTMLElement>;\n disabled?: boolean;\n icon?: string;\n label?: string;\n menuActionHandler?: MenuActionHandler;\n menuBuilder?: MenuBuilder;\n menuClassName?: string;\n menuLocation?: string;\n menuOptions?: { [key: string]: unknown };\n onMenuClose?: MenuCloseHandler;\n onMenuOpen?: () => void;\n popupPlacement?: PopupPlacement;\n variant?: ButtonProps[\"variant\"];\n}\n\nexport const PopupMenu = ({\n anchorElement,\n className,\n disabled = false,\n label,\n icon = label ? \"chevron-down\" : \"more-vert\",\n id: idProp,\n menuActionHandler,\n menuBuilder,\n menuClassName,\n menuLocation = \"header\",\n menuOptions,\n onMenuClose,\n onMenuOpen,\n popupPlacement = \"below-right\",\n tabIndex = 0,\n variant = \"secondary\",\n ...htmlAttributes\n}: PopupMenuProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-popup-menu\",\n css: popupMenuCss,\n window: targetWindow
|
|
1
|
+
{"version":3,"file":"PopupMenu.js","sources":["../../src/popup-menu/PopupMenu.tsx"],"sourcesContent":["import { MenuActionHandler, MenuBuilder } from \"@vuu-ui/vuu-data-types\";\nimport { Icon, IconButton } from \"@vuu-ui/vuu-ui-controls\";\nimport { useId } from \"@vuu-ui/vuu-utils\";\nimport { Button, ButtonProps } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport cx from \"clsx\";\nimport { HTMLAttributes, RefObject } from \"react\";\nimport { PopupPlacement } from \"../popup/Popup\";\nimport { PopupCloseReason } from \"../popup/popup-service\";\nimport { usePopupMenu } from \"./usePopupMenu\";\n\nimport popupMenuCss from \"./PopupMenu.css\";\n\nconst classBase = \"vuuPopupMenu\";\n\nexport type MenuCloseHandler = (reason?: PopupCloseReason) => void;\n\nexport interface PopupMenuProps extends HTMLAttributes<HTMLButtonElement> {\n anchorElement?: RefObject<HTMLElement>;\n disabled?: boolean;\n icon?: string;\n label?: string;\n menuActionHandler?: MenuActionHandler;\n menuBuilder?: MenuBuilder;\n menuClassName?: string;\n menuLocation?: string;\n menuOptions?: { [key: string]: unknown };\n onMenuClose?: MenuCloseHandler;\n onMenuOpen?: () => void;\n popupPlacement?: PopupPlacement;\n variant?: ButtonProps[\"variant\"];\n}\n\nexport const PopupMenu = ({\n anchorElement,\n className,\n disabled = false,\n label,\n icon = label ? \"chevron-down\" : \"more-vert\",\n id: idProp,\n menuActionHandler,\n menuBuilder,\n menuClassName,\n menuLocation = \"header\",\n menuOptions,\n onMenuClose,\n onMenuOpen,\n popupPlacement = \"below-right\",\n tabIndex = 0,\n variant = \"secondary\",\n ...htmlAttributes\n}: PopupMenuProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-popup-menu\",\n css: popupMenuCss,\n window: targetWindow,\n });\n\n const id = useId(idProp);\n\n const { ariaAttributes, buttonProps, menuOpen, rootRef } = usePopupMenu({\n anchorElement,\n id,\n menuActionHandler,\n menuBuilder,\n menuClassName,\n menuLocation,\n onMenuClose,\n onMenuOpen,\n menuOptions,\n popupPlacement,\n tabIndex,\n });\n\n if (label) {\n return (\n <Button\n {...htmlAttributes}\n {...ariaAttributes}\n {...buttonProps}\n className={cx(classBase, className, `${classBase}-withCaption`, {\n \"saltButton-active\": menuOpen,\n })}\n disabled={disabled}\n ref={rootRef}\n variant=\"secondary\"\n >\n {icon ? <Icon name={icon} /> : null}\n {label}\n </Button>\n );\n } else if (icon) {\n return (\n <IconButton\n {...htmlAttributes}\n {...ariaAttributes}\n {...buttonProps}\n className={cx(classBase, className, {\n \"saltButton-active\": menuOpen,\n })}\n disabled={disabled}\n icon={icon}\n ref={rootRef}\n variant={variant}\n />\n );\n } else {\n console.error(\"PopupMenu must have a label or an icon (or both)\");\n return null;\n }\n};\n"],"names":["useWindow","useComponentCssInjection","popupMenuCss","useId","usePopupMenu","jsxs","Button","jsx","Icon","IconButton"],"mappings":";;;;;;;;;;;;AAcA,MAAM,SAAY,GAAA,cAAA,CAAA;AAoBX,MAAM,YAAY,CAAC;AAAA,EACxB,aAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAW,GAAA,KAAA;AAAA,EACX,KAAA;AAAA,EACA,IAAA,GAAO,QAAQ,cAAiB,GAAA,WAAA;AAAA,EAChC,EAAI,EAAA,MAAA;AAAA,EACJ,iBAAA;AAAA,EACA,WAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAe,GAAA,QAAA;AAAA,EACf,WAAA;AAAA,EACA,WAAA;AAAA,EACA,UAAA;AAAA,EACA,cAAiB,GAAA,aAAA;AAAA,EACjB,QAAW,GAAA,CAAA;AAAA,EACX,OAAU,GAAA,WAAA;AAAA,EACV,GAAG,cAAA;AACL,CAAsB,KAAA;AACpB,EAAA,MAAM,eAAeA,gBAAU,EAAA,CAAA;AAC/B,EAAyBC,+BAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,gBAAA;AAAA,IACR,GAAK,EAAAC,WAAA;AAAA,IACL,MAAQ,EAAA,YAAA;AAAA,GACT,CAAA,CAAA;AAED,EAAM,MAAA,EAAA,GAAKC,eAAM,MAAM,CAAA,CAAA;AAEvB,EAAA,MAAM,EAAE,cAAgB,EAAA,WAAA,EAAa,QAAU,EAAA,OAAA,KAAYC,yBAAa,CAAA;AAAA,IACtE,aAAA;AAAA,IACA,EAAA;AAAA,IACA,iBAAA;AAAA,IACA,WAAA;AAAA,IACA,aAAA;AAAA,IACA,YAAA;AAAA,IACA,WAAA;AAAA,IACA,UAAA;AAAA,IACA,WAAA;AAAA,IACA,cAAA;AAAA,IACA,QAAA;AAAA,GACD,CAAA,CAAA;AAED,EAAA,IAAI,KAAO,EAAA;AACT,IACE,uBAAAC,eAAA;AAAA,MAACC,WAAA;AAAA,MAAA;AAAA,QACE,GAAG,cAAA;AAAA,QACH,GAAG,cAAA;AAAA,QACH,GAAG,WAAA;AAAA,QACJ,WAAW,EAAG,CAAA,SAAA,EAAW,SAAW,EAAA,CAAA,EAAG,SAAS,CAAgB,YAAA,CAAA,EAAA;AAAA,UAC9D,mBAAqB,EAAA,QAAA;AAAA,SACtB,CAAA;AAAA,QACD,QAAA;AAAA,QACA,GAAK,EAAA,OAAA;AAAA,QACL,OAAQ,EAAA,WAAA;AAAA,QAEP,QAAA,EAAA;AAAA,UAAA,IAAA,mBAAQC,cAAA,CAAAC,kBAAA,EAAA,EAAK,IAAM,EAAA,IAAA,EAAM,CAAK,GAAA,IAAA;AAAA,UAC9B,KAAA;AAAA,SAAA;AAAA,OAAA;AAAA,KACH,CAAA;AAAA,aAEO,IAAM,EAAA;AACf,IACE,uBAAAD,cAAA;AAAA,MAACE,wBAAA;AAAA,MAAA;AAAA,QACE,GAAG,cAAA;AAAA,QACH,GAAG,cAAA;AAAA,QACH,GAAG,WAAA;AAAA,QACJ,SAAA,EAAW,EAAG,CAAA,SAAA,EAAW,SAAW,EAAA;AAAA,UAClC,mBAAqB,EAAA,QAAA;AAAA,SACtB,CAAA;AAAA,QACD,QAAA;AAAA,QACA,IAAA;AAAA,QACA,GAAK,EAAA,OAAA;AAAA,QACL,OAAA;AAAA,OAAA;AAAA,KACF,CAAA;AAAA,GAEG,MAAA;AACL,IAAA,OAAA,CAAQ,MAAM,kDAAkD,CAAA,CAAA;AAChE,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AACF;;;;"}
|
package/cjs/portal/Portal.js.map
CHANGED
|
@@ -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
|
|
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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"}
|
package/cjs/prompt/Prompt.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Prompt.js","sources":["../../src/prompt/Prompt.tsx"],"sourcesContent":["import { useThemeAttributes } from \"@vuu-ui/vuu-utils\";\nimport { Button } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport cx from \"clsx\";\nimport { HTMLAttributes, useLayoutEffect, useRef } from \"react\";\nimport { PopupComponentProps, useAnchoredPosition } from \"../popup\";\n\nimport propmtCss from \"./Prompt.css\";\n\nconst classBase = \"vuuPrompt\";\n\nconst AnchorBody = { current: document.body };\n\nconst EMPTY_PROPS = {};\n\nexport interface PromptProps extends HTMLAttributes<HTMLDialogElement> {\n PopupProps?: Partial<PopupComponentProps>;\n cancelButtonLabel?: string;\n confirmButtonLabel?: string;\n onCancel: () => void;\n onConfirm: () => void;\n icon?: string;\n text: string;\n variant?: \"warn\" | \"error\" | \"info\";\n}\n\nexport const Prompt = ({\n PopupProps = EMPTY_PROPS,\n cancelButtonLabel = \"Cancel\",\n confirmButtonLabel = \"Confirm\",\n icon,\n onCancel,\n onConfirm,\n style,\n text,\n title,\n variant = \"info\",\n ...htmlAttributes\n}: PromptProps) => {\n const {\n anchorElement = AnchorBody,\n offsetLeft = 0,\n offsetTop = 0,\n placement = \"below\"
|
|
1
|
+
{"version":3,"file":"Prompt.js","sources":["../../src/prompt/Prompt.tsx"],"sourcesContent":["import { useThemeAttributes } from \"@vuu-ui/vuu-utils\";\nimport { Button } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport cx from \"clsx\";\nimport { HTMLAttributes, useLayoutEffect, useRef } from \"react\";\nimport { PopupComponentProps, useAnchoredPosition } from \"../popup\";\n\nimport propmtCss from \"./Prompt.css\";\n\nconst classBase = \"vuuPrompt\";\n\nconst AnchorBody = { current: document.body };\n\nconst EMPTY_PROPS = {};\n\nexport interface PromptProps extends HTMLAttributes<HTMLDialogElement> {\n PopupProps?: Partial<PopupComponentProps>;\n cancelButtonLabel?: string;\n confirmButtonLabel?: string;\n onCancel: () => void;\n onConfirm: () => void;\n icon?: string;\n text: string;\n variant?: \"warn\" | \"error\" | \"info\";\n}\n\nexport const Prompt = ({\n PopupProps = EMPTY_PROPS,\n cancelButtonLabel = \"Cancel\",\n confirmButtonLabel = \"Confirm\",\n icon,\n onCancel,\n onConfirm,\n style,\n text,\n title,\n variant = \"info\",\n ...htmlAttributes\n}: PromptProps) => {\n const {\n anchorElement = AnchorBody,\n offsetLeft = 0,\n offsetTop = 0,\n placement = \"below\",\n } = PopupProps;\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-prompt\",\n css: propmtCss,\n window: targetWindow,\n });\n\n const [themeClass, _, dataMode] = useThemeAttributes();\n const { position } = useAnchoredPosition({\n anchorElement,\n offsetLeft,\n offsetTop,\n placement,\n });\n const rootRef = useRef<HTMLDialogElement>(null);\n const confirmRef = useRef<HTMLButtonElement>(null);\n\n useLayoutEffect(() => {\n if (rootRef.current) {\n rootRef.current.showModal();\n if (confirmRef.current) {\n confirmRef.current.focus();\n }\n if (placement.endsWith(\"center\")) {\n const { width } = rootRef.current.getBoundingClientRect();\n rootRef.current.style.marginLeft = `-${width / 2}px`;\n }\n }\n }, [placement]);\n\n return (\n <dialog\n {...htmlAttributes}\n className={cx(classBase, `${classBase}-${variant}`, themeClass)}\n data-mode={dataMode}\n ref={rootRef}\n style={{ ...style, ...position }}\n >\n <form className={`${classBase}-form`}>\n <div className={`${classBase}-header`} data-icon={icon}>\n {title}\n </div>\n <div className={`${classBase}-text`}>{text}</div>\n <div className={`${classBase}-buttonBar`}>\n <Button onClick={onCancel} variant=\"secondary\">\n {cancelButtonLabel}\n </Button>\n <Button onClick={onConfirm} ref={confirmRef} value=\"default\">\n {confirmButtonLabel}\n </Button>\n </div>\n </form>\n </dialog>\n );\n};\n"],"names":["useWindow","useComponentCssInjection","propmtCss","useThemeAttributes","useAnchoredPosition","useRef","useLayoutEffect","jsx","jsxs","Button"],"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
|
|
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
|
|
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":";;;;;;;;;;;AAiBA,MAAM,OAAO,MAAM,KAAA,CAAA,CAAA;AAEZ,MAAM,cAAc,CAAC;AAAA,EAC1B,WAAAA,EAAAA,YAAAA;AAAA,EACA,mBAAA;AAAA,EACA,QAAU,EAAA,YAAA;AAAA,EACV,SAAA;AAAA,EACA,EAAI,EAAA,MAAA;AAAA,EACJ,UAAU,MAAM,KAAA,CAAA;AAAA,EAChB,QAAW,GAAA,EAAE,CAAG,EAAA,CAAA,EAAG,GAAG,CAAE,EAAA;AAAA,EACxB,KAAA;AAAA,EACA,GAAG,aAAA;AACL,CAAwB,KAAA;AACtB,EAAM,MAAA,EAAA,GAAK,MAAM,MAAM,CAAA,CAAA;AACvB,EAAM,MAAA,YAAA,GAAe,OAAoC,IAAI,CAAA,CAAA;AAC7D,EAAA,MAAM,CAAC,KAAO,EAAA,OAAO,CAAI,GAAA,mBAAA,CAAoB,cAAc,EAAE,CAAA,CAAA;AAC7D,EAAM,MAAA,sBAAA,GAAyB,OAAO,mBAAmB,CAAA,CAAA;AACzD,EAAM,MAAA,oBAAA,GAAuB,YAAY,MAAM;AAC7C,IAAA,sBAAA,CAAuB,OAAU,GAAA,KAAA,CAAA;AAAA,GACnC,EAAG,EAAE,CAAA,CAAA;AAEL,EAAA,MAAM,cAAiB,GAAA,WAAA;AAAA,IACrB,CAAC,UAAuB,KAAA;AACtB,MAAM,MAAA,QAAA,GAAW,UAAW,CAAA,KAAA,CAAM,CAAC,CAAA,CAAA;AACnC,MAAA,MAAM,EAAE,MAAA,EAAQ,OAAQ,EAAA,GAAI,QAAQ,QAAQ,CAAA,CAAA;AAC5C,MAAA,YAAA,CAAa,QAAQ,EAAE,CAAA,CAAA;AACvB,MAAQ,OAAA,CAAA;AAAA,QACN,IAAM,EAAA,aAAA;AAAA,QACN,MAAQ,EAAA,MAAA;AAAA,QACR,OAAA;AAAA,OACD,CAAA,CAAA;AAAA,KACH;AAAA,IACA,CAAC,OAAS,EAAA,EAAA,EAAI,OAAO,CAAA;AAAA,GACvB,CAAA;AAEA,EAAM,MAAA;AAAA,IACJ,SAAA;AAAA,IACA,aAAA;AAAA,IACA,QAAU,EAAA,UAAA;AAAA,IACV,SAAA;AAAA,IACA,YAAA;AAAA,MACE,UAAW,CAAA;AAAA;AAAA,IAEb,EAAA,EAAI,GAAG,EAAE,CAAA,CAAA;AAAA,IACT,UAAY,EAAA,cAAA;AAAA,IACZ,gBAAkB,EAAA,oBAAA;AAAA,IAClB,QAAA;AAAA,GACD,CAAA,CAAA;AACD,EAAA,YAAA,CAAa,OAAU,GAAA,SAAA,CAAA;AAEvB,EAAA,MAAM,eAAkB,GAAA,WAAA;AAAA,IACtB,CAAC,KAAK,MAAW,KAAA;AACf,MAAA,sBAAA,CAAuB,OAAU,GAAA,IAAA,CAAA;AACjC,MAAU,SAAA,EAAA,CAAA;AACV,MAAA,IAAI,WAAW,UAAY,EAAA;AAGzB,QAAQ,OAAA,CAAA;AAAA,UACN,KAAO,EAAA,GAAA;AAAA,UACP,IAAM,EAAA,UAAA;AAAA,SACP,CAAA,CAAA;AAAA,OACH;AAAA,KACF;AAAA,IACA,CAAC,WAAW,OAAO,CAAA;AAAA,GACrB,CAAA;AAEA,EAAA,MAAM,0BAA0B,MAAM;AAAA,GAEtC,CAAA;AAEA,EAAM,MAAA,QAAA,GAAW,UAAU,MAAS,GAAA,CAAA,CAAA;AAEpC,EAAM,MAAA,cAAA,GAAiB,CAAC,CAAc,KAAA;AACpC,IAAA,IAAI,KAAK,QAAU,EAAA;AACjB,MAAO,OAAA,KAAA,CAAA,CAAA;AAAA,KACF,MAAA;AACL,MAAA,MAAM,EAAE,EAAAC,EAAAA,GAAAA,EAAO,GAAA,SAAA,CAAU,IAAI,CAAC,CAAA,CAAA;AAC9B,MAAOA,OAAAA,GAAAA,CAAAA;AAAA,KACT;AAAA,GACF,CAAA;AAEA,EACE,uBAAA,GAAA,CAAA,QAAA,EAAA,EACG,QAAU,EAAA,SAAA,CAAA,GAAA,CAAI,CAAC,EAAE,EAAI,EAAA,MAAA,EAAQ,IAAM,EAAA,GAAA,EAAO,EAAA,CAAA,EAAG,GAAQ,KAAA;AACpD,IAAM,MAAA,WAAA,GAAc,eAAe,CAAC,CAAA,CAAA;AACpC,IAAA,qCACG,MAAQ,EAAA,EAAA,GAAGD,cAAa,GAAK,EAAA,CAAA,EAAG,UAAU,YACzC,EAAA,kBAAA,GAAA;AAAA,MAAC,cAAA;AAAA,MAAA;AAAA,QACC,aAAe,EAAA,EAAE,OAAS,EAAA,QAAA,CAAS,IAAK,EAAA;AAAA,QACxC,SAAU,EAAA,UAAA;AAAA,QACV,QAAA,EAAU,EAAE,IAAA,EAAM,GAAI,EAAA;AAAA,QAEtB,QAAA,kBAAA,aAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACE,GAAG,aAAA;AAAA,YACJ,qBAAqB,sBAAuB,CAAA,OAAA;AAAA,YAC5C,gBAAkB,EAAA,WAAA;AAAA,YAClB,SAAA;AAAA,YACA,EAAI,EAAA,MAAA;AAAA,YACJ,QAAQ,CAAM,KAAA,CAAA;AAAA,YACd,GAAK,EAAA,CAAA;AAAA,YACL,aAAA;AAAA,YACA,UAAY,EAAA,cAAA;AAAA,YACZ,mBAAqB,EAAA,uBAAA;AAAA,YACrB,WAAa,EAAA,eAAA;AAAA,YACb,QAAU,EAAA,UAAA;AAAA,YACV,KAAA;AAAA,YACA,QAAU,EAAA,CAAA,KAAM,GAAI,CAAA,MAAA,GAAS,IAAI,CAAI,GAAA,KAAA,CAAA;AAAA,WAAA;AAAA,UAEpC,MAAM,MAAM,CAAA;AAAA,SACf;AAAA,OAAA;AAAA,KAEJ,CAAA,CAAA;AAAA,GAEH,CACH,EAAA,CAAA,CAAA;AAEJ,EAAA;AAEA,WAAA,CAAY,WAAc,GAAA,aAAA;;;;"}
|
package/esm/menu/MenuList.js.map
CHANGED
|
@@ -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
|
|
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":";;;;;AAmDO,MAAM,wBAAwB,CAAC;AAAA,EACpC,sBAAyB,GAAA,KAAA;AAAA,EACzB,KAAA;AAAA,EACA,qBAAA;AAAA,EACA,gBAAkB,EAAA,oBAAA;AAAA,EAClB,UAAA;AAAA,EACA,WAAA;AAAA;AAAA,EAEA,WAAA;AAAA,EACA,UAAA;AACF,CAAqD,KAAA;AACnD,EAAA,IACE,aAAc,CAAA,oBAAoB,CAClC,IAAA,aAAA,CAAc,qBAAqB,CACnC,EAAA;AACA,IAAM,MAAA,KAAA;AAAA,MACJ,8FAAA;AAAA,KACF,CAAA;AAAA,GACF;AAEA,EAAM,MAAA,sBAAA,GAAyB,cAAc,oBAAoB,CAAA,CAAA;AACjE,EAAA,MAAM,mBAAsB,GAAA,MAAA;AAAA,IAC1B,qBAAA,IACE,oBACC,KAAA,sBAAA,GAAyB,CAAI,GAAA,CAAA,CAAA,CAAA;AAAA,GAClC,CAAA;AACA,EAAA,MAAM,GAAG,WAAW,CAAA,GAAI,SAAkB,IAAI,CAAA,CAAA;AAE9C,EAAA,MAAM,iBAAoB,GAAA,WAAA;AAAA,IACxB,CAAC,GAAQ,KAAA;AACP,MAAA,mBAAA,CAAoB,OAAU,GAAA,GAAA,CAAA;AAC9B,MAAA,WAAA,GAAc,GAAG,CAAA,CAAA;AACjB,MAAA,WAAA,CAAY,EAAE,CAAA,CAAA;AAAA,KAChB;AAAA,IACA,CAAC,WAAW,CAAA;AAAA,GACd,CAAA;AAEA,EAAA,MAAM,mBAAsB,GAAA,WAAA;AAAA,IAC1B,CAAC,GAAQ,KAAA;AACP,MAAI,IAAA,GAAA,KAAQ,oBAAoB,OAAS,EAAA;AACvC,QAAA,IAAI,CAAC,sBAAwB,EAAA;AAC3B,UAAA,iBAAA,CAAkB,GAAG,CAAA,CAAA;AAAA,SACvB;AAAA,OACF;AAAA,KACF;AAAA,IACA,CAAC,wBAAwB,iBAAiB,CAAA;AAAA,GAC5C,CAAA;AAGA,EAAM,MAAA,kBAAA,GAAqB,OAAO,IAAI,CAAA,CAAA;AACtC,EAAM,MAAA,WAAA,GAAc,OAAO,KAAK,CAAA,CAAA;AAChC,EAAA,MAAM,cAAiB,GAAA,CAAC,KAAoB,KAAA,WAAA,CAAY,OAAU,GAAA,KAAA,CAAA;AAElE,EAAM,MAAA,gBAAA,GAAmB,sBACrB,GAAA,oBAAA,GACA,mBAAoB,CAAA,OAAA,CAAA;AAExB,EAAA,MAAM,oBAAuB,GAAA,WAAA;AAAA,IAC3B,CAAC,CAAqB,KAAA;AACpB,MAAA,MAAM,UAAU,WAAY,CAAA,KAAA,EAAO,CAAE,CAAA,GAAA,EAAK,oBAAoB,OAAO,CAAA,CAAA;AACrE,MAAI,IAAA,OAAA,KAAY,oBAAoB,OAAS,EAAA;AAC3C,QAAA,mBAAA,CAAoB,OAAO,CAAA,CAAA;AAAA,OAC7B;AAAA,KACF;AAAA,IACA,CAAC,OAAO,mBAAmB,CAAA;AAAA,GAC7B,CAAA;AAEA,EAAA,MAAM,aAAgB,GAAA,WAAA;AAAA,IACpB,CAAC,CAAqB,KAAA;AACpB,MAAI,IAAA,eAAA,CAAgB,CAAC,CAAG,EAAA;AACtB,QAAA,CAAA,CAAE,cAAe,EAAA,CAAA;AACjB,QAAA,CAAA,CAAE,eAAgB,EAAA,CAAA;AAClB,QAAA,kBAAA,CAAmB,OAAU,GAAA,IAAA,CAAA;AAC7B,QAAA,oBAAA,CAAqB,CAAC,CAAA,CAAA;AAAA,OACxB,MAAA,IAAA,CACG,CAAE,CAAA,GAAA,KAAQ,YAAgB,IAAA,CAAA,CAAE,GAAQ,KAAA,OAAA,KACrC,QAAS,CAAA,CAAA,CAAE,MAAuB,EAAA,gBAAgB,CAClD,EAAA;AACA,QAAA,MAAM,SAAS,CAAE,CAAA,MAAA,CAAA;AACjB,QAAA,MAAM,aAAa,MAAO,CAAA,aAAA;AAAA,UACxB,yBAAyB,gBAAgB,CAAA,EAAA,CAAA;AAAA,SAC3C,CAAA;AAEA,QAAA,IAAI,UAAY,EAAA;AACd,UAAA,UAAA,GAAa,YAAY,IAAI,CAAA,CAAA;AAAA,SAC/B;AAAA,OACF,MAAA,IAAW,EAAE,GAAQ,KAAA,WAAA,IAAe,CAAC,MAAO,CAAA,CAAA,CAAE,MAAqB,CAAG,EAAA;AACpE,QAAA,WAAA,CAAY,GAAG,kBAAkB,CAAA,CAAA;AAAA,OACnC,MAAA,IAAW,CAAE,CAAA,GAAA,KAAQ,OAAS,EAAA;AAC5B,QAAA,CAAA,CAAE,cAAe,EAAA,CAAA;AACjB,QAAA,CAAA,CAAE,eAAgB,EAAA,CAAA;AAClB,QAAA,UAAA,IAAc,WAAW,gBAAgB,CAAA,CAAA;AAAA,OAC3C,MAAA,IAAW,CAAE,CAAA,GAAA,KAAQ,KAAO,EAAA;AAC1B,QAAA,WAAA,CAAY,GAAG,UAAU,CAAA,CAAA;AAAA,OAC3B;AAAA,KACF;AAAA,IACA;AAAA,MACE,gBAAA;AAAA,MACA,oBAAA;AAAA,MACA,UAAA;AAAA,MACA,WAAA;AAAA,MACA,UAAA;AAAA,KACF;AAAA,GACF,CAAA;AAEA,EAAA,MAAM,SAAmC,GAAA,OAAA;AAAA,IACvC,OAAO;AAAA,MACL,SAAS,MAAM;AACb,QAAA,IAAI,qBAAqB,CAAI,CAAA,EAAA;AAC3B,UAAA,iBAAA,CAAkB,CAAC,CAAA,CAAA;AAAA,SACrB;AAAA,OACF;AAAA,MACA,SAAW,EAAA,aAAA;AAAA,MACX,oBAAoB,MAAM;AACxB,QAAA,kBAAA,CAAmB,OAAU,GAAA,KAAA,CAAA;AAC7B,QAAA,cAAA,CAAe,IAAI,CAAA,CAAA;AAAA,OACrB;AAAA;AAAA,MAGA,aAAa,MAAM;AACjB,QAAA,IAAI,mBAAmB,OAAS,EAAA;AAC9B,UAAA,kBAAA,CAAmB,OAAU,GAAA,KAAA,CAAA;AAAA,SAC/B;AAAA,OACF;AAAA,MACA,cAAc,MAAM;AAElB,QAAA,kBAAA,CAAmB,OAAU,GAAA,IAAA,CAAA;AAC7B,QAAA,cAAA,CAAe,KAAK,CAAA,CAAA;AACpB,QAAA,mBAAA,CAAoB,CAAE,CAAA,CAAA,CAAA;AAAA,OACxB;AAAA,KACF,CAAA;AAAA,IACA,CAAC,aAAA,EAAe,gBAAkB,EAAA,iBAAA,EAAmB,mBAAmB,CAAA;AAAA,GAC1E,CAAA;AAEA,EAAO,OAAA;AAAA,IACL,YAAA,EAAc,kBAAmB,CAAA,OAAA,GAAU,gBAAmB,GAAA,CAAA,CAAA;AAAA,IAC9D,sBAAA;AAAA,IACA,gBAAA;AAAA,IACA,mBAAA;AAAA;AAAA,IAEA,SAAA;AAAA,IACA,cAAA;AAAA,GACF,CAAA;AACF,EAAA;AAGA,SAAS,WAAA,CAAY,KAAe,EAAA,GAAA,EAAa,GAAa,EAAA;AAC5D,EAAA,IAAI,QAAQ,SAAW,EAAA;AACrB,IAAA,IAAI,MAAM,CAAG,EAAA;AACX,MAAA,OAAO,GAAM,GAAA,CAAA,CAAA;AAAA,KACR,MAAA;AACL,MAAO,OAAA,GAAA,CAAA;AAAA,KACT;AAAA,GACK,MAAA;AACL,IAAA,IAAI,QAAQ,IAAM,EAAA;AAChB,MAAO,OAAA,CAAA,CAAA;AAAA,KACT,MAAA,IAAW,GAAQ,KAAA,KAAA,GAAQ,CAAG,EAAA;AAC5B,MAAO,OAAA,GAAA,CAAA;AAAA,KACF,MAAA;AACL,MAAA,OAAO,GAAM,GAAA,CAAA,CAAA;AAAA,KACf;AAAA,GACF;AACF;;;;"}
|
|
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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"}
|
|
@@ -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
|
|
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;;;;"}
|
|
@@ -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\"
|
|
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":"PopupMenu.js","sources":["../../src/popup-menu/PopupMenu.tsx"],"sourcesContent":["import { MenuActionHandler, MenuBuilder } from \"@vuu-ui/vuu-data-types\";\nimport { Icon, IconButton } from \"@vuu-ui/vuu-ui-controls\";\nimport { useId } from \"@vuu-ui/vuu-utils\";\nimport { Button, ButtonProps } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport cx from \"clsx\";\nimport { HTMLAttributes, RefObject } from \"react\";\nimport { PopupPlacement } from \"../popup/Popup\";\nimport { PopupCloseReason } from \"../popup/popup-service\";\nimport { usePopupMenu } from \"./usePopupMenu\";\n\nimport popupMenuCss from \"./PopupMenu.css\";\n\nconst classBase = \"vuuPopupMenu\";\n\nexport type MenuCloseHandler = (reason?: PopupCloseReason) => void;\n\nexport interface PopupMenuProps extends HTMLAttributes<HTMLButtonElement> {\n anchorElement?: RefObject<HTMLElement>;\n disabled?: boolean;\n icon?: string;\n label?: string;\n menuActionHandler?: MenuActionHandler;\n menuBuilder?: MenuBuilder;\n menuClassName?: string;\n menuLocation?: string;\n menuOptions?: { [key: string]: unknown };\n onMenuClose?: MenuCloseHandler;\n onMenuOpen?: () => void;\n popupPlacement?: PopupPlacement;\n variant?: ButtonProps[\"variant\"];\n}\n\nexport const PopupMenu = ({\n anchorElement,\n className,\n disabled = false,\n label,\n icon = label ? \"chevron-down\" : \"more-vert\",\n id: idProp,\n menuActionHandler,\n menuBuilder,\n menuClassName,\n menuLocation = \"header\",\n menuOptions,\n onMenuClose,\n onMenuOpen,\n popupPlacement = \"below-right\",\n tabIndex = 0,\n variant = \"secondary\",\n ...htmlAttributes\n}: PopupMenuProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-popup-menu\",\n css: popupMenuCss,\n window: targetWindow
|
|
1
|
+
{"version":3,"file":"PopupMenu.js","sources":["../../src/popup-menu/PopupMenu.tsx"],"sourcesContent":["import { MenuActionHandler, MenuBuilder } from \"@vuu-ui/vuu-data-types\";\nimport { Icon, IconButton } from \"@vuu-ui/vuu-ui-controls\";\nimport { useId } from \"@vuu-ui/vuu-utils\";\nimport { Button, ButtonProps } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport cx from \"clsx\";\nimport { HTMLAttributes, RefObject } from \"react\";\nimport { PopupPlacement } from \"../popup/Popup\";\nimport { PopupCloseReason } from \"../popup/popup-service\";\nimport { usePopupMenu } from \"./usePopupMenu\";\n\nimport popupMenuCss from \"./PopupMenu.css\";\n\nconst classBase = \"vuuPopupMenu\";\n\nexport type MenuCloseHandler = (reason?: PopupCloseReason) => void;\n\nexport interface PopupMenuProps extends HTMLAttributes<HTMLButtonElement> {\n anchorElement?: RefObject<HTMLElement>;\n disabled?: boolean;\n icon?: string;\n label?: string;\n menuActionHandler?: MenuActionHandler;\n menuBuilder?: MenuBuilder;\n menuClassName?: string;\n menuLocation?: string;\n menuOptions?: { [key: string]: unknown };\n onMenuClose?: MenuCloseHandler;\n onMenuOpen?: () => void;\n popupPlacement?: PopupPlacement;\n variant?: ButtonProps[\"variant\"];\n}\n\nexport const PopupMenu = ({\n anchorElement,\n className,\n disabled = false,\n label,\n icon = label ? \"chevron-down\" : \"more-vert\",\n id: idProp,\n menuActionHandler,\n menuBuilder,\n menuClassName,\n menuLocation = \"header\",\n menuOptions,\n onMenuClose,\n onMenuOpen,\n popupPlacement = \"below-right\",\n tabIndex = 0,\n variant = \"secondary\",\n ...htmlAttributes\n}: PopupMenuProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-popup-menu\",\n css: popupMenuCss,\n window: targetWindow,\n });\n\n const id = useId(idProp);\n\n const { ariaAttributes, buttonProps, menuOpen, rootRef } = usePopupMenu({\n anchorElement,\n id,\n menuActionHandler,\n menuBuilder,\n menuClassName,\n menuLocation,\n onMenuClose,\n onMenuOpen,\n menuOptions,\n popupPlacement,\n tabIndex,\n });\n\n if (label) {\n return (\n <Button\n {...htmlAttributes}\n {...ariaAttributes}\n {...buttonProps}\n className={cx(classBase, className, `${classBase}-withCaption`, {\n \"saltButton-active\": menuOpen,\n })}\n disabled={disabled}\n ref={rootRef}\n variant=\"secondary\"\n >\n {icon ? <Icon name={icon} /> : null}\n {label}\n </Button>\n );\n } else if (icon) {\n return (\n <IconButton\n {...htmlAttributes}\n {...ariaAttributes}\n {...buttonProps}\n className={cx(classBase, className, {\n \"saltButton-active\": menuOpen,\n })}\n disabled={disabled}\n icon={icon}\n ref={rootRef}\n variant={variant}\n />\n );\n } else {\n console.error(\"PopupMenu must have a label or an icon (or both)\");\n return null;\n }\n};\n"],"names":[],"mappings":";;;;;;;;;;AAcA,MAAM,SAAY,GAAA,cAAA,CAAA;AAoBX,MAAM,YAAY,CAAC;AAAA,EACxB,aAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAW,GAAA,KAAA;AAAA,EACX,KAAA;AAAA,EACA,IAAA,GAAO,QAAQ,cAAiB,GAAA,WAAA;AAAA,EAChC,EAAI,EAAA,MAAA;AAAA,EACJ,iBAAA;AAAA,EACA,WAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAe,GAAA,QAAA;AAAA,EACf,WAAA;AAAA,EACA,WAAA;AAAA,EACA,UAAA;AAAA,EACA,cAAiB,GAAA,aAAA;AAAA,EACjB,QAAW,GAAA,CAAA;AAAA,EACX,OAAU,GAAA,WAAA;AAAA,EACV,GAAG,cAAA;AACL,CAAsB,KAAA;AACpB,EAAA,MAAM,eAAe,SAAU,EAAA,CAAA;AAC/B,EAAyB,wBAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,gBAAA;AAAA,IACR,GAAK,EAAA,YAAA;AAAA,IACL,MAAQ,EAAA,YAAA;AAAA,GACT,CAAA,CAAA;AAED,EAAM,MAAA,EAAA,GAAK,MAAM,MAAM,CAAA,CAAA;AAEvB,EAAA,MAAM,EAAE,cAAgB,EAAA,WAAA,EAAa,QAAU,EAAA,OAAA,KAAY,YAAa,CAAA;AAAA,IACtE,aAAA;AAAA,IACA,EAAA;AAAA,IACA,iBAAA;AAAA,IACA,WAAA;AAAA,IACA,aAAA;AAAA,IACA,YAAA;AAAA,IACA,WAAA;AAAA,IACA,UAAA;AAAA,IACA,WAAA;AAAA,IACA,cAAA;AAAA,IACA,QAAA;AAAA,GACD,CAAA,CAAA;AAED,EAAA,IAAI,KAAO,EAAA;AACT,IACE,uBAAA,IAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACE,GAAG,cAAA;AAAA,QACH,GAAG,cAAA;AAAA,QACH,GAAG,WAAA;AAAA,QACJ,WAAW,EAAG,CAAA,SAAA,EAAW,SAAW,EAAA,CAAA,EAAG,SAAS,CAAgB,YAAA,CAAA,EAAA;AAAA,UAC9D,mBAAqB,EAAA,QAAA;AAAA,SACtB,CAAA;AAAA,QACD,QAAA;AAAA,QACA,GAAK,EAAA,OAAA;AAAA,QACL,OAAQ,EAAA,WAAA;AAAA,QAEP,QAAA,EAAA;AAAA,UAAA,IAAA,mBAAQ,GAAA,CAAA,IAAA,EAAA,EAAK,IAAM,EAAA,IAAA,EAAM,CAAK,GAAA,IAAA;AAAA,UAC9B,KAAA;AAAA,SAAA;AAAA,OAAA;AAAA,KACH,CAAA;AAAA,aAEO,IAAM,EAAA;AACf,IACE,uBAAA,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACE,GAAG,cAAA;AAAA,QACH,GAAG,cAAA;AAAA,QACH,GAAG,WAAA;AAAA,QACJ,SAAA,EAAW,EAAG,CAAA,SAAA,EAAW,SAAW,EAAA;AAAA,UAClC,mBAAqB,EAAA,QAAA;AAAA,SACtB,CAAA;AAAA,QACD,QAAA;AAAA,QACA,IAAA;AAAA,QACA,GAAK,EAAA,OAAA;AAAA,QACL,OAAA;AAAA,OAAA;AAAA,KACF,CAAA;AAAA,GAEG,MAAA;AACL,IAAA,OAAA,CAAQ,MAAM,kDAAkD,CAAA,CAAA;AAChE,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AACF;;;;"}
|
package/esm/portal/Portal.js.map
CHANGED
|
@@ -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
|
|
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":";;;;;;;AA4CA,SAAS,aAAa,SAAqC,EAAA;AACzD,EAAA,OAAO,OAAO,SAAA,KAAc,UAAa,GAAA,SAAA,EAAc,GAAA,SAAA,CAAA;AACzD,CAAA;AAEA,MAAM,UAAA,GAAa,CAAC,wBAAA,EAA0B,iBAAiB,CAAA,CAAA;AAE/D,MAAM,4BAAA,GAA+B,CAAC,EAA0B,KAAA;AAC9D,EAAI,IAAA,KAAA,CAAM,OAAQ,CAAA,EAAE,CAAG,EAAA;AACrB,IAAA,KAAA,MAAW,KAAK,EAAI,EAAA;AAClB,MAAM,MAAA,OAAA,GAAU,QAAS,CAAA,cAAA,CAAe,CAAC,CAAA,CAAA;AACzC,MAAA,IAAI,OAAS,EAAA;AACX,QAAO,OAAA,OAAA,CAAA;AAAA,OACT;AAAA,KACF;AAAA,GACK,MAAA;AACL,IAAO,OAAA,QAAA,CAAS,eAAe,EAAE,CAAA,CAAA;AAAA,GACnC;AACA,EAAO,OAAA,IAAA,CAAA;AACT,CAAA,CAAA;AAMO,MAAM,SAAS,CAAC;AAAA,EACrB,QAAA;AAAA,EACA,SAAA,EAAW,gBAAgB,QAAS,CAAA,IAAA;AAAA,EACpC,EAAK,GAAA,UAAA;AAAA,EACL,QAAA;AAAA,EACA,IAAO,GAAA,IAAA;AAAA,EACP,eAAA;AACF,CAAmB,KAAA;AACjB,EAAA,MAAM,eAAe,SAAU,EAAA,CAAA;AAC/B,EAAyB,wBAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,YAAA;AAAA,IACR,GAAK,EAAA,SAAA;AAAA,IACL,MAAQ,EAAA,YAAA;AAAA,GACT,CAAA,CAAA;AAED,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,KAAK,CAAA,CAAA;AAC5C,EAAM,MAAA,SAAA,GAAY,OAA2B,IAAI,CAAA,CAAA;AACjD,EAAA,MAAM,SAAY,GAAA,YAAA,CAAa,aAAa,CAAA,IAAK,QAAS,CAAA,IAAA,CAAA;AAC1D,EAAA,MAAM,CAAC,UAAY,EAAA,YAAA,EAAc,QAAQ,CAAA,GACvC,mBAAmB,eAAe,CAAA,CAAA;AAEpC,EAAA,eAAA,CAAgB,MAAM;AACpB,IAAM,MAAA,IAAA,GAAO,6BAA6B,EAAE,CAAA,CAAA;AAC5C,IAAA,IAAI,IAAM,EAAA;AACR,MAAA,SAAA,CAAU,OAAU,GAAA,IAAA,CAAA;AAAA,KACf,MAAA;AACL,MAAU,SAAA,CAAA,OAAA,GAAU,QAAS,CAAA,aAAA,CAAc,KAAK,CAAA,CAAA;AAChD,MAAA,SAAA,CAAU,OAAQ,CAAA,EAAA,GAChB,OAAO,EAAA,KAAO,QACV,GAAA,EAAA,GACA,EAAG,CAAA,MAAA,GAAS,CACT,GAAA,EAAA,CAAG,EAAG,CAAA,CAAA,CAAE,CACT,GAAA,iBAAA,CAAA;AAAA,KACV;AACA,IAAA,MAAM,KAAK,SAAU,CAAA,OAAA,CAAA;AACrB,IAAA,IAAI,CAAC,SAAA,CAAU,QAAS,CAAA,EAAE,CAAG,EAAA;AAC3B,MAAA,SAAA,CAAU,YAAY,EAAE,CAAA,CAAA;AAAA,KAC1B;AACA,IAAG,EAAA,CAAA,SAAA,CAAU,GAAI,CAAA,UAAA,EAAY,YAAY,CAAA,CAAA;AACzC,IAAA,EAAA,CAAG,QAAQ,IAAO,GAAA,QAAA,CAAA;AAClB,IAAA,UAAA,CAAW,IAAI,CAAA,CAAA;AAAA,KACd,CAAC,EAAA,EAAI,WAAW,UAAY,EAAA,YAAA,EAAc,QAAQ,CAAC,CAAA,CAAA;AAEtD,EAAA,eAAA,CAAgB,MAAM;AACpB,IAAA,qBAAA,CAAsB,MAAM;AAC1B,MAAW,QAAA,IAAA,CAAA;AAAA,KACZ,CAAA,CAAA;AAAA,GACH,EAAG,CAAC,QAAQ,CAAC,CAAA,CAAA;AAEb,EAAA,IAAI,IAAQ,IAAA,OAAA,IAAW,SAAU,CAAA,OAAA,IAAW,QAAU,EAAA;AACpD,IAAO,OAAA,YAAA,CAAa,QAAU,EAAA,SAAA,CAAU,OAAO,CAAA,CAAA;AAAA,GACjD;AAEA,EAAO,OAAA,IAAA,CAAA;AACT;;;;"}
|
package/esm/prompt/Prompt.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Prompt.js","sources":["../../src/prompt/Prompt.tsx"],"sourcesContent":["import { useThemeAttributes } from \"@vuu-ui/vuu-utils\";\nimport { Button } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport cx from \"clsx\";\nimport { HTMLAttributes, useLayoutEffect, useRef } from \"react\";\nimport { PopupComponentProps, useAnchoredPosition } from \"../popup\";\n\nimport propmtCss from \"./Prompt.css\";\n\nconst classBase = \"vuuPrompt\";\n\nconst AnchorBody = { current: document.body };\n\nconst EMPTY_PROPS = {};\n\nexport interface PromptProps extends HTMLAttributes<HTMLDialogElement> {\n PopupProps?: Partial<PopupComponentProps>;\n cancelButtonLabel?: string;\n confirmButtonLabel?: string;\n onCancel: () => void;\n onConfirm: () => void;\n icon?: string;\n text: string;\n variant?: \"warn\" | \"error\" | \"info\";\n}\n\nexport const Prompt = ({\n PopupProps = EMPTY_PROPS,\n cancelButtonLabel = \"Cancel\",\n confirmButtonLabel = \"Confirm\",\n icon,\n onCancel,\n onConfirm,\n style,\n text,\n title,\n variant = \"info\",\n ...htmlAttributes\n}: PromptProps) => {\n const {\n anchorElement = AnchorBody,\n offsetLeft = 0,\n offsetTop = 0,\n placement = \"below\"
|
|
1
|
+
{"version":3,"file":"Prompt.js","sources":["../../src/prompt/Prompt.tsx"],"sourcesContent":["import { useThemeAttributes } from \"@vuu-ui/vuu-utils\";\nimport { Button } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport cx from \"clsx\";\nimport { HTMLAttributes, useLayoutEffect, useRef } from \"react\";\nimport { PopupComponentProps, useAnchoredPosition } from \"../popup\";\n\nimport propmtCss from \"./Prompt.css\";\n\nconst classBase = \"vuuPrompt\";\n\nconst AnchorBody = { current: document.body };\n\nconst EMPTY_PROPS = {};\n\nexport interface PromptProps extends HTMLAttributes<HTMLDialogElement> {\n PopupProps?: Partial<PopupComponentProps>;\n cancelButtonLabel?: string;\n confirmButtonLabel?: string;\n onCancel: () => void;\n onConfirm: () => void;\n icon?: string;\n text: string;\n variant?: \"warn\" | \"error\" | \"info\";\n}\n\nexport const Prompt = ({\n PopupProps = EMPTY_PROPS,\n cancelButtonLabel = \"Cancel\",\n confirmButtonLabel = \"Confirm\",\n icon,\n onCancel,\n onConfirm,\n style,\n text,\n title,\n variant = \"info\",\n ...htmlAttributes\n}: PromptProps) => {\n const {\n anchorElement = AnchorBody,\n offsetLeft = 0,\n offsetTop = 0,\n placement = \"below\",\n } = PopupProps;\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-prompt\",\n css: propmtCss,\n window: targetWindow,\n });\n\n const [themeClass, _, dataMode] = useThemeAttributes();\n const { position } = useAnchoredPosition({\n anchorElement,\n offsetLeft,\n offsetTop,\n placement,\n });\n const rootRef = useRef<HTMLDialogElement>(null);\n const confirmRef = useRef<HTMLButtonElement>(null);\n\n useLayoutEffect(() => {\n if (rootRef.current) {\n rootRef.current.showModal();\n if (confirmRef.current) {\n confirmRef.current.focus();\n }\n if (placement.endsWith(\"center\")) {\n const { width } = rootRef.current.getBoundingClientRect();\n rootRef.current.style.marginLeft = `-${width / 2}px`;\n }\n }\n }, [placement]);\n\n return (\n <dialog\n {...htmlAttributes}\n className={cx(classBase, `${classBase}-${variant}`, themeClass)}\n data-mode={dataMode}\n ref={rootRef}\n style={{ ...style, ...position }}\n >\n <form className={`${classBase}-form`}>\n <div className={`${classBase}-header`} data-icon={icon}>\n {title}\n </div>\n <div className={`${classBase}-text`}>{text}</div>\n <div className={`${classBase}-buttonBar`}>\n <Button onClick={onCancel} variant=\"secondary\">\n {cancelButtonLabel}\n </Button>\n <Button onClick={onConfirm} ref={confirmRef} value=\"default\">\n {confirmButtonLabel}\n </Button>\n </div>\n </form>\n </dialog>\n );\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
|
|
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,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.8.
|
|
2
|
+
"version": "0.8.88",
|
|
3
3
|
"description": "VUU popup components - Context Menu, Dialog etc",
|
|
4
4
|
"author": "heswell",
|
|
5
5
|
"license": "Apache-2.0",
|
|
@@ -7,10 +7,10 @@
|
|
|
7
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.
|
|
11
|
-
"@vuu-ui/vuu-layout": "0.8.
|
|
12
|
-
"@vuu-ui/vuu-utils": "0.8.
|
|
13
|
-
"@vuu-ui/vuu-ui-controls": "0.8.
|
|
10
|
+
"@vuu-ui/vuu-data-types": "0.8.88",
|
|
11
|
+
"@vuu-ui/vuu-layout": "0.8.88",
|
|
12
|
+
"@vuu-ui/vuu-utils": "0.8.88",
|
|
13
|
+
"@vuu-ui/vuu-ui-controls": "0.8.88"
|
|
14
14
|
},
|
|
15
15
|
"peerDependencies": {
|
|
16
16
|
"clsx": "^2.0.0",
|
|
@@ -9,4 +9,4 @@ export interface ContextMenuProviderProps extends ContextMenuConfiguration {
|
|
|
9
9
|
children: ReactNode;
|
|
10
10
|
label?: string;
|
|
11
11
|
}
|
|
12
|
-
export declare const ContextMenuProvider: ({ children, label, menuActionHandler, menuBuilder }: ContextMenuProviderProps) => JSX.Element;
|
|
12
|
+
export declare const ContextMenuProvider: ({ children, label, menuActionHandler, menuBuilder, }: ContextMenuProviderProps) => JSX.Element;
|
|
@@ -27,4 +27,4 @@ export interface NavigationHookResult {
|
|
|
27
27
|
listProps: KeyboardHookListProps;
|
|
28
28
|
setIgnoreFocus: (ignoreFocus: boolean) => void;
|
|
29
29
|
}
|
|
30
|
-
export declare const useKeyboardNavigation: ({ autoHighlightFirstItem, count, defaultHighlightedIdx, highlightedIndex: highlightedIndexProp, onActivate, onHighlight, onCloseMenu, onOpenMenu }: KeyboardNavigationProps) => NavigationHookResult;
|
|
30
|
+
export declare const useKeyboardNavigation: ({ autoHighlightFirstItem, count, defaultHighlightedIdx, highlightedIndex: highlightedIndexProp, onActivate, onHighlight, onCloseMenu, onOpenMenu, }: KeyboardNavigationProps) => NavigationHookResult;
|
|
@@ -3,4 +3,4 @@ import { NotificationsContext } from "./NotificationsProvider";
|
|
|
3
3
|
export interface NotificationsCenterProps {
|
|
4
4
|
notificationsContext: NotificationsContext;
|
|
5
5
|
}
|
|
6
|
-
export declare const NotificationsCenter: ({ notificationsContext }: NotificationsCenterProps) => JSX.Element;
|
|
6
|
+
export declare const NotificationsCenter: ({ notificationsContext, }: NotificationsCenterProps) => JSX.Element;
|
package/types/portal/Portal.d.ts
CHANGED
|
@@ -39,4 +39,4 @@ export interface PortalProps {
|
|
|
39
39
|
* Portals provide a first-class way to render children into a DOM node
|
|
40
40
|
* that exists outside the DOM hierarchy of the parent component.
|
|
41
41
|
*/
|
|
42
|
-
export declare const Portal: ({ children, container: containerProp, id, onRender, open, themeAttributes }: PortalProps) => import("react").ReactPortal | null;
|
|
42
|
+
export declare const Portal: ({ children, container: containerProp, id, onRender, open, themeAttributes, }: PortalProps) => import("react").ReactPortal | null;
|
|
@@ -7,7 +7,7 @@ export interface TooltipHookProps {
|
|
|
7
7
|
placement?: TooltipPlacement | TooltipPlacement[];
|
|
8
8
|
tooltipContent: ReactNode;
|
|
9
9
|
}
|
|
10
|
-
export declare const useTooltip: ({ anchorQuery, id: idProp, placement, tooltipContent }: TooltipHookProps) => {
|
|
10
|
+
export declare const useTooltip: ({ anchorQuery, id: idProp, placement, tooltipContent, }: TooltipHookProps) => {
|
|
11
11
|
anchorProps: {
|
|
12
12
|
"aria-describedby": string;
|
|
13
13
|
onMouseEnter: (evt: MouseEvent) => void;
|