@cloudscape-design/components 3.0.873 → 3.0.874

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.
Files changed (46) hide show
  1. package/app-layout/visual-refresh-toolbar/toolbar/trigger-button/index.js +4 -4
  2. package/app-layout/visual-refresh-toolbar/toolbar/trigger-button/index.js.map +1 -1
  3. package/button-group/item-element.js +4 -4
  4. package/button-group/item-element.js.map +1 -1
  5. package/code-editor/resizable-box/index.js +4 -4
  6. package/code-editor/resizable-box/index.js.map +1 -1
  7. package/container/use-sticky-header.js +4 -4
  8. package/container/use-sticky-header.js.map +1 -1
  9. package/file-dropzone/use-files-dragging.d.ts.map +1 -1
  10. package/file-dropzone/use-files-dragging.js +5 -6
  11. package/file-dropzone/use-files-dragging.js.map +1 -1
  12. package/internal/analytics/components/analytics-funnel.js +4 -4
  13. package/internal/analytics/components/analytics-funnel.js.map +1 -1
  14. package/internal/animate.js +1 -1
  15. package/internal/animate.js.map +1 -1
  16. package/internal/components/chart-plot/focus-outline.js +4 -4
  17. package/internal/components/chart-plot/focus-outline.js.map +1 -1
  18. package/internal/components/dropdown/index.js +4 -4
  19. package/internal/components/dropdown/index.js.map +1 -1
  20. package/internal/components/transition/index.js +4 -4
  21. package/internal/components/transition/index.js.map +1 -1
  22. package/internal/environment.js +1 -1
  23. package/internal/environment.json +1 -1
  24. package/internal/focus-tracker.d.ts +1 -0
  25. package/internal/focus-tracker.d.ts.map +1 -1
  26. package/internal/focus-tracker.js +4 -4
  27. package/internal/focus-tracker.js.map +1 -1
  28. package/internal/hooks/use-mouse-down-target.js +4 -4
  29. package/internal/hooks/use-mouse-down-target.js.map +1 -1
  30. package/internal/manifest.json +1 -1
  31. package/package.json +1 -1
  32. package/popover/container.d.ts.map +1 -1
  33. package/popover/container.js +5 -6
  34. package/popover/container.js.map +1 -1
  35. package/table/resizer/index.d.ts.map +1 -1
  36. package/table/resizer/index.js +5 -6
  37. package/table/resizer/index.js.map +1 -1
  38. package/table/table-role/grid-navigation.js +5 -6
  39. package/table/table-role/grid-navigation.js.map +1 -1
  40. package/test-utils/dom/index.d.ts +78 -78
  41. package/test-utils/dom/index.js +9 -3
  42. package/test-utils/dom/index.js.map +1 -1
  43. package/test-utils/selectors/index.d.ts +78 -78
  44. package/test-utils/selectors/index.js +5 -1
  45. package/test-utils/selectors/index.js.map +1 -1
  46. package/test-utils/tsconfig.tsbuildinfo +1 -1
@@ -84,11 +84,11 @@ function TriggerButton({ ariaLabel, className, iconName, iconSvg, ariaExpanded,
84
84
  };
85
85
  const wrapperDiv = containerRef.current;
86
86
  if (wrapperDiv) {
87
- wrapperDiv.addEventListener('pointerdown', handlePointerDownEvent);
88
- wrapperDiv.addEventListener('keydown', handleKeyDownEvent);
87
+ const controller = new AbortController();
88
+ wrapperDiv.addEventListener('pointerdown', handlePointerDownEvent, { signal: controller.signal });
89
+ wrapperDiv.addEventListener('keydown', handleKeyDownEvent, { signal: controller.signal });
89
90
  return () => {
90
- wrapperDiv.removeEventListener('pointerdown', handlePointerDownEvent);
91
- wrapperDiv.removeEventListener('keydown', handleKeyDownEvent);
91
+ controller.abort();
92
92
  };
93
93
  }
94
94
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../src/app-layout/visual-refresh-toolbar/toolbar/trigger-button/index.tsx"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport React, { Ref, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport clsx from 'clsx';\n\nimport { ButtonProps } from '../../../../button/interfaces';\nimport { IconProps } from '../../../../icon/interfaces';\nimport Icon from '../../../../icon/internal';\nimport Tooltip from '../../../../internal/components/tooltip';\nimport { registerTooltip } from '../../../../internal/components/tooltip/registry';\n\nimport testutilStyles from '../../../test-classes/styles.css.js';\nimport styles from './styles.css.js';\n\nexport interface TriggerButtonProps {\n ariaLabel?: string;\n className?: string;\n iconName?: IconProps.Name;\n iconSvg?: React.ReactNode;\n ariaExpanded: boolean | undefined;\n ariaControls?: string;\n disabled?: boolean;\n /**\n * Ovewrwrites any internal testIds when provided\n */\n testId?: string;\n /**\n * If button is selected. Used only for desktop and applies a selected class\n */\n selected?: boolean;\n onClick: React.MouseEventHandler<HTMLButtonElement>;\n\n badge?: boolean;\n /**\n * If the button is expected to have a tooltip. When false it will not set the event listeners\n *\n * defaults to false\n */\n hasTooltip?: boolean;\n /**\n * This text allows for a customized tooltip.\n *\n * When falsy, the tooltip will parse the tooltip form the aria-lable\n */\n tooltipText?: string;\n hasOpenDrawer?: boolean;\n /**\n * If the AppLayout is in mobile mode\n * Used to determine if and where to render tooltips\n */\n isMobile?: boolean;\n /**\n * set to true if the trigger button was used to open the last active drawer\n * this is also used to hide the tooltip should the focus be set programmatically\n * on focus from a drawer close using this\n */\n isForPreviousActiveDrawer?: boolean;\n /**\n * if the trigger button is for the split panel\n */\n isForSplitPanel?: boolean;\n tabIndex?: number | undefined;\n}\n\nfunction TriggerButton(\n {\n ariaLabel,\n className,\n iconName,\n iconSvg,\n ariaExpanded,\n ariaControls,\n onClick,\n testId,\n disabled = false,\n badge,\n selected = false,\n hasTooltip = false,\n tooltipText,\n hasOpenDrawer = false,\n isMobile = false,\n isForPreviousActiveDrawer = false,\n isForSplitPanel = false,\n }: TriggerButtonProps,\n ref: React.Ref<ButtonProps.Ref>\n) {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const tooltipValue = tooltipText ? tooltipText : ariaLabel ? ariaLabel : '';\n const [showTooltip, setShowTooltip] = useState<boolean>(false);\n const [suppressTooltip, setSupressTooltip] = useState<boolean>(false);\n\n const handleTriggerClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.stopPropagation(); // Stop the event from propagating to the badge icon\n setShowTooltip(false);\n setSupressTooltip(true);\n onClick(event);\n };\n\n const handleBlur = (keepSupressed = false) => {\n setSupressTooltip(keepSupressed);\n setShowTooltip(false);\n };\n\n const handlePointerEnter = () => {\n setSupressTooltip(false);\n setShowTooltip(true);\n };\n\n /**\n * Takes the drawer being closed and the data-shift-focus value from a close button on that drawer that persists\n * on the event relatedTarget to determine not to show the tooltip\n * @param event\n */\n const handleOnFocus = useCallback(\n (event: FocusEvent) => {\n let shouldShowTooltip = false;\n const eventWithRelatedTarget = event as any;\n const relatedTarget = eventWithRelatedTarget?.relatedTarget;\n const isFromAnotherTrigger = relatedTarget?.dataset?.shiftFocus === 'awsui-layout-drawer-trigger';\n if (\n (isForSplitPanel && !!relatedTarget) || // relatedTarget is null when split panel is closed\n (!isForSplitPanel &&\n (isFromAnotherTrigger || // for key navigation from another trigger button\n !isForPreviousActiveDrawer)) // for when the drawer was not opened recently\n ) {\n shouldShowTooltip = true;\n }\n setSupressTooltip(!shouldShowTooltip);\n setShowTooltip(true);\n },\n [\n // To assert reference equality check\n isForPreviousActiveDrawer,\n isForSplitPanel,\n ]\n );\n\n const tooltipVisible = useMemo(() => {\n return (\n hasTooltip &&\n showTooltip &&\n !suppressTooltip &&\n !!containerRef?.current &&\n tooltipValue &&\n !(isMobile && hasOpenDrawer)\n );\n }, [hasTooltip, showTooltip, containerRef, tooltipValue, isMobile, hasOpenDrawer, suppressTooltip]);\n\n useEffect(() => {\n if (hasTooltip && tooltipValue) {\n const close = () => {\n setShowTooltip(false);\n setSupressTooltip(false);\n };\n\n const shouldCloseTooltip = (event: PointerEvent) => {\n if (event.target && containerRef && (containerRef.current as any)?.contains(event.target as HTMLElement)) {\n return false;\n }\n return true;\n };\n\n const handlePointerDownEvent = (event: PointerEvent) => {\n if (shouldCloseTooltip(event)) {\n close();\n }\n };\n\n const handleKeyDownEvent = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n close();\n }\n };\n\n const wrapperDiv = containerRef.current;\n if (wrapperDiv) {\n wrapperDiv.addEventListener('pointerdown', handlePointerDownEvent);\n wrapperDiv.addEventListener('keydown', handleKeyDownEvent);\n\n return () => {\n wrapperDiv.removeEventListener('pointerdown', handlePointerDownEvent);\n wrapperDiv.removeEventListener('keydown', handleKeyDownEvent);\n };\n }\n }\n }, [containerRef, hasTooltip, tooltipValue]);\n\n useEffect(() => {\n if (tooltipVisible) {\n return registerTooltip(() => {\n setShowTooltip(false);\n setSupressTooltip(false);\n });\n }\n }, [tooltipVisible]);\n\n return (\n <div\n ref={containerRef}\n {...(hasTooltip && {\n onPointerEnter: () => handlePointerEnter(),\n onPointerLeave: () => handleBlur(true),\n onFocus: e => handleOnFocus(e as any),\n onBlur: () => handleBlur(true),\n })}\n className={styles['trigger-wrapper']}\n >\n <button\n aria-expanded={ariaExpanded}\n aria-controls={ariaControls}\n aria-haspopup={true}\n aria-label={ariaLabel}\n aria-disabled={disabled}\n disabled={disabled}\n className={clsx(\n styles.trigger,\n styles['trigger-button-styles'],\n {\n [styles.selected]: selected,\n [styles.badge]: badge,\n [testutilStyles['drawers-trigger-with-badge']]: badge,\n },\n className\n )}\n onClick={handleTriggerClick}\n ref={ref as Ref<HTMLButtonElement>}\n type=\"button\"\n data-testid={testId}\n data-shift-focus=\"awsui-layout-drawer-trigger\"\n >\n <span className={clsx(badge && clsx(styles['trigger-badge-wrapper'], styles['trigger-button-styles']))}>\n {(iconName || iconSvg) && <Icon name={iconName} svg={iconSvg} />}\n </span>\n </button>\n {badge && <div className={styles.dot} />}\n {tooltipVisible && (\n <Tooltip trackRef={containerRef} value={tooltipValue} className={testutilStyles['trigger-tooltip']} />\n )}\n </div>\n );\n}\n\nexport default React.forwardRef(TriggerButton);\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../src/app-layout/visual-refresh-toolbar/toolbar/trigger-button/index.tsx"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport React, { Ref, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport clsx from 'clsx';\n\nimport { ButtonProps } from '../../../../button/interfaces';\nimport { IconProps } from '../../../../icon/interfaces';\nimport Icon from '../../../../icon/internal';\nimport Tooltip from '../../../../internal/components/tooltip';\nimport { registerTooltip } from '../../../../internal/components/tooltip/registry';\n\nimport testutilStyles from '../../../test-classes/styles.css.js';\nimport styles from './styles.css.js';\n\nexport interface TriggerButtonProps {\n ariaLabel?: string;\n className?: string;\n iconName?: IconProps.Name;\n iconSvg?: React.ReactNode;\n ariaExpanded: boolean | undefined;\n ariaControls?: string;\n disabled?: boolean;\n /**\n * Ovewrwrites any internal testIds when provided\n */\n testId?: string;\n /**\n * If button is selected. Used only for desktop and applies a selected class\n */\n selected?: boolean;\n onClick: React.MouseEventHandler<HTMLButtonElement>;\n\n badge?: boolean;\n /**\n * If the button is expected to have a tooltip. When false it will not set the event listeners\n *\n * defaults to false\n */\n hasTooltip?: boolean;\n /**\n * This text allows for a customized tooltip.\n *\n * When falsy, the tooltip will parse the tooltip form the aria-lable\n */\n tooltipText?: string;\n hasOpenDrawer?: boolean;\n /**\n * If the AppLayout is in mobile mode\n * Used to determine if and where to render tooltips\n */\n isMobile?: boolean;\n /**\n * set to true if the trigger button was used to open the last active drawer\n * this is also used to hide the tooltip should the focus be set programmatically\n * on focus from a drawer close using this\n */\n isForPreviousActiveDrawer?: boolean;\n /**\n * if the trigger button is for the split panel\n */\n isForSplitPanel?: boolean;\n tabIndex?: number | undefined;\n}\n\nfunction TriggerButton(\n {\n ariaLabel,\n className,\n iconName,\n iconSvg,\n ariaExpanded,\n ariaControls,\n onClick,\n testId,\n disabled = false,\n badge,\n selected = false,\n hasTooltip = false,\n tooltipText,\n hasOpenDrawer = false,\n isMobile = false,\n isForPreviousActiveDrawer = false,\n isForSplitPanel = false,\n }: TriggerButtonProps,\n ref: React.Ref<ButtonProps.Ref>\n) {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const tooltipValue = tooltipText ? tooltipText : ariaLabel ? ariaLabel : '';\n const [showTooltip, setShowTooltip] = useState<boolean>(false);\n const [suppressTooltip, setSupressTooltip] = useState<boolean>(false);\n\n const handleTriggerClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.stopPropagation(); // Stop the event from propagating to the badge icon\n setShowTooltip(false);\n setSupressTooltip(true);\n onClick(event);\n };\n\n const handleBlur = (keepSupressed = false) => {\n setSupressTooltip(keepSupressed);\n setShowTooltip(false);\n };\n\n const handlePointerEnter = () => {\n setSupressTooltip(false);\n setShowTooltip(true);\n };\n\n /**\n * Takes the drawer being closed and the data-shift-focus value from a close button on that drawer that persists\n * on the event relatedTarget to determine not to show the tooltip\n * @param event\n */\n const handleOnFocus = useCallback(\n (event: FocusEvent) => {\n let shouldShowTooltip = false;\n const eventWithRelatedTarget = event as any;\n const relatedTarget = eventWithRelatedTarget?.relatedTarget;\n const isFromAnotherTrigger = relatedTarget?.dataset?.shiftFocus === 'awsui-layout-drawer-trigger';\n if (\n (isForSplitPanel && !!relatedTarget) || // relatedTarget is null when split panel is closed\n (!isForSplitPanel &&\n (isFromAnotherTrigger || // for key navigation from another trigger button\n !isForPreviousActiveDrawer)) // for when the drawer was not opened recently\n ) {\n shouldShowTooltip = true;\n }\n setSupressTooltip(!shouldShowTooltip);\n setShowTooltip(true);\n },\n [\n // To assert reference equality check\n isForPreviousActiveDrawer,\n isForSplitPanel,\n ]\n );\n\n const tooltipVisible = useMemo(() => {\n return (\n hasTooltip &&\n showTooltip &&\n !suppressTooltip &&\n !!containerRef?.current &&\n tooltipValue &&\n !(isMobile && hasOpenDrawer)\n );\n }, [hasTooltip, showTooltip, containerRef, tooltipValue, isMobile, hasOpenDrawer, suppressTooltip]);\n\n useEffect(() => {\n if (hasTooltip && tooltipValue) {\n const close = () => {\n setShowTooltip(false);\n setSupressTooltip(false);\n };\n\n const shouldCloseTooltip = (event: PointerEvent) => {\n if (event.target && containerRef && (containerRef.current as any)?.contains(event.target as HTMLElement)) {\n return false;\n }\n return true;\n };\n\n const handlePointerDownEvent = (event: PointerEvent) => {\n if (shouldCloseTooltip(event)) {\n close();\n }\n };\n\n const handleKeyDownEvent = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n close();\n }\n };\n\n const wrapperDiv = containerRef.current;\n if (wrapperDiv) {\n const controller = new AbortController();\n wrapperDiv.addEventListener('pointerdown', handlePointerDownEvent, { signal: controller.signal });\n wrapperDiv.addEventListener('keydown', handleKeyDownEvent, { signal: controller.signal });\n\n return () => {\n controller.abort();\n };\n }\n }\n }, [containerRef, hasTooltip, tooltipValue]);\n\n useEffect(() => {\n if (tooltipVisible) {\n return registerTooltip(() => {\n setShowTooltip(false);\n setSupressTooltip(false);\n });\n }\n }, [tooltipVisible]);\n\n return (\n <div\n ref={containerRef}\n {...(hasTooltip && {\n onPointerEnter: () => handlePointerEnter(),\n onPointerLeave: () => handleBlur(true),\n onFocus: e => handleOnFocus(e as any),\n onBlur: () => handleBlur(true),\n })}\n className={styles['trigger-wrapper']}\n >\n <button\n aria-expanded={ariaExpanded}\n aria-controls={ariaControls}\n aria-haspopup={true}\n aria-label={ariaLabel}\n aria-disabled={disabled}\n disabled={disabled}\n className={clsx(\n styles.trigger,\n styles['trigger-button-styles'],\n {\n [styles.selected]: selected,\n [styles.badge]: badge,\n [testutilStyles['drawers-trigger-with-badge']]: badge,\n },\n className\n )}\n onClick={handleTriggerClick}\n ref={ref as Ref<HTMLButtonElement>}\n type=\"button\"\n data-testid={testId}\n data-shift-focus=\"awsui-layout-drawer-trigger\"\n >\n <span className={clsx(badge && clsx(styles['trigger-badge-wrapper'], styles['trigger-button-styles']))}>\n {(iconName || iconSvg) && <Icon name={iconName} svg={iconSvg} />}\n </span>\n </button>\n {badge && <div className={styles.dot} />}\n {tooltipVisible && (\n <Tooltip trackRef={containerRef} value={tooltipValue} className={testutilStyles['trigger-tooltip']} />\n )}\n </div>\n );\n}\n\nexport default React.forwardRef(TriggerButton);\n"]}
@@ -36,11 +36,11 @@ const ItemElement = forwardRef(({ item, dropdownExpandToViewport, tooltip, setTo
36
36
  close();
37
37
  }
38
38
  };
39
- window.addEventListener('pointerdown', handlePointerDownEvent);
40
- window.addEventListener('keydown', handleKeyDownEvent);
39
+ const controller = new AbortController();
40
+ window.addEventListener('pointerdown', handlePointerDownEvent, { signal: controller.signal });
41
+ window.addEventListener('keydown', handleKeyDownEvent, { signal: controller.signal });
41
42
  return () => {
42
- window.removeEventListener('pointerdown', handlePointerDownEvent);
43
- window.removeEventListener('keydown', handleKeyDownEvent);
43
+ controller.abort();
44
44
  };
45
45
  }, [item.id, tooltip, setTooltip]);
46
46
  const onShowTooltipSoft = (show) => {
@@ -1 +1 @@
1
- {"version":3,"file":"item-element.js","sourceRoot":"","sources":["../../../src/button-group/item-element.tsx"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport React, { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';\n\nimport { ButtonProps } from '../button/interfaces.js';\nimport { fireCancelableEvent, NonCancelableEventHandler } from '../internal/events';\nimport { nodeBelongs } from '../internal/utils/node-belongs';\nimport FileInputItem from './file-input-item';\nimport IconButtonItem from './icon-button-item';\nimport IconToggleButtonItem from './icon-toggle-button-item.js';\nimport { ButtonGroupProps } from './interfaces';\nimport MenuDropdownItem from './menu-dropdown-item';\n\nimport styles from './styles.css.js';\n\ninterface ItemElementProps {\n item: ButtonGroupProps.Item;\n dropdownExpandToViewport?: boolean;\n tooltip: null | { item: string; feedback: boolean };\n setTooltip: (tooltip: null | { item: string; feedback: boolean }) => void;\n onItemClick?: NonCancelableEventHandler<ButtonGroupProps.ItemClickDetails> | undefined;\n onFilesChange?: NonCancelableEventHandler<ButtonGroupProps.FilesChangeDetails> | undefined;\n}\n\nconst ItemElement = forwardRef(\n (\n { item, dropdownExpandToViewport, tooltip, setTooltip, onItemClick, onFilesChange }: ItemElementProps,\n ref: React.Ref<ButtonProps.Ref>\n ) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const itemRef = useRef<HTMLButtonElement | HTMLInputElement>(null);\n\n useImperativeHandle(ref, () => ({\n focus: () => {\n itemRef.current?.focus();\n },\n }));\n\n useEffect(() => {\n if (tooltip?.item !== item.id) {\n return;\n }\n\n const close = () => {\n setTooltip(null);\n };\n\n const handlePointerDownEvent = (event: PointerEvent) => {\n if (event.target && containerRef.current?.contains(event.target as HTMLElement)) {\n return;\n }\n\n close();\n };\n\n const handleKeyDownEvent = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n close();\n }\n };\n\n window.addEventListener('pointerdown', handlePointerDownEvent);\n window.addEventListener('keydown', handleKeyDownEvent);\n\n return () => {\n window.removeEventListener('pointerdown', handlePointerDownEvent);\n window.removeEventListener('keydown', handleKeyDownEvent);\n };\n }, [item.id, tooltip, setTooltip]);\n\n const onShowTooltipSoft = (show: boolean) => {\n if (!tooltip?.feedback) {\n setTooltip(show ? { item: item.id, feedback: false } : null);\n }\n };\n\n const onShowTooltipHard = (show: boolean) => {\n if (!show && item.id !== tooltip?.item) {\n return;\n }\n\n setTooltip(show ? { item: item.id, feedback: false } : null);\n };\n\n const onClickHandler = (event: CustomEvent<ButtonGroupProps.ItemClickDetails>) => {\n const hasPopoverFeedback = 'popoverFeedback' in item && item.popoverFeedback;\n\n if (hasPopoverFeedback) {\n setTooltip({ item: item.id, feedback: true });\n }\n\n fireCancelableEvent(onItemClick, event.detail, event);\n };\n\n const onFilesChangeHandler = (event: CustomEvent<ButtonGroupProps.FilesChangeDetails>) => {\n fireCancelableEvent(onFilesChange, event.detail, event);\n\n setTooltip(null);\n };\n\n return (\n <div\n key={item.id}\n className={styles['item-wrapper']}\n ref={containerRef}\n onPointerEnter={() => onShowTooltipSoft(true)}\n onPointerLeave={() => onShowTooltipSoft(false)}\n onFocus={event => {\n // Showing no tooltip when the focus comes from inside the container.\n // This is needed to prevent the tooltip after a menu closes with item selection or Escape.\n if (event && event.relatedTarget && nodeBelongs(containerRef.current, event.relatedTarget)) {\n return;\n }\n onShowTooltipHard(true);\n }}\n onBlur={() => onShowTooltipHard(false)}\n >\n {item.type === 'icon-button' && (\n <IconButtonItem\n ref={itemRef}\n item={item}\n onItemClick={onClickHandler}\n showTooltip={tooltip?.item === item.id}\n showFeedback={!!tooltip?.feedback}\n />\n )}\n {item.type === 'icon-toggle-button' && (\n <IconToggleButtonItem\n ref={itemRef}\n item={item}\n onItemClick={onClickHandler}\n showTooltip={tooltip?.item === item.id}\n showFeedback={!!tooltip?.feedback}\n />\n )}\n {item.type === 'icon-file-input' && (\n <FileInputItem\n ref={itemRef}\n item={item}\n onFilesChange={onFilesChangeHandler}\n showTooltip={tooltip?.item === item.id}\n />\n )}\n {item.type === 'menu-dropdown' && (\n <MenuDropdownItem\n ref={itemRef}\n item={item}\n showTooltip={tooltip?.item === item.id}\n onItemClick={onClickHandler}\n expandToViewport={dropdownExpandToViewport}\n />\n )}\n </div>\n );\n }\n);\n\nexport default ItemElement;\n"]}
1
+ {"version":3,"file":"item-element.js","sourceRoot":"","sources":["../../../src/button-group/item-element.tsx"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport React, { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';\n\nimport { ButtonProps } from '../button/interfaces.js';\nimport { fireCancelableEvent, NonCancelableEventHandler } from '../internal/events';\nimport { nodeBelongs } from '../internal/utils/node-belongs';\nimport FileInputItem from './file-input-item';\nimport IconButtonItem from './icon-button-item';\nimport IconToggleButtonItem from './icon-toggle-button-item.js';\nimport { ButtonGroupProps } from './interfaces';\nimport MenuDropdownItem from './menu-dropdown-item';\n\nimport styles from './styles.css.js';\n\ninterface ItemElementProps {\n item: ButtonGroupProps.Item;\n dropdownExpandToViewport?: boolean;\n tooltip: null | { item: string; feedback: boolean };\n setTooltip: (tooltip: null | { item: string; feedback: boolean }) => void;\n onItemClick?: NonCancelableEventHandler<ButtonGroupProps.ItemClickDetails> | undefined;\n onFilesChange?: NonCancelableEventHandler<ButtonGroupProps.FilesChangeDetails> | undefined;\n}\n\nconst ItemElement = forwardRef(\n (\n { item, dropdownExpandToViewport, tooltip, setTooltip, onItemClick, onFilesChange }: ItemElementProps,\n ref: React.Ref<ButtonProps.Ref>\n ) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const itemRef = useRef<HTMLButtonElement | HTMLInputElement>(null);\n\n useImperativeHandle(ref, () => ({\n focus: () => {\n itemRef.current?.focus();\n },\n }));\n\n useEffect(() => {\n if (tooltip?.item !== item.id) {\n return;\n }\n\n const close = () => {\n setTooltip(null);\n };\n\n const handlePointerDownEvent = (event: PointerEvent) => {\n if (event.target && containerRef.current?.contains(event.target as HTMLElement)) {\n return;\n }\n\n close();\n };\n\n const handleKeyDownEvent = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n close();\n }\n };\n\n const controller = new AbortController();\n window.addEventListener('pointerdown', handlePointerDownEvent, { signal: controller.signal });\n window.addEventListener('keydown', handleKeyDownEvent, { signal: controller.signal });\n\n return () => {\n controller.abort();\n };\n }, [item.id, tooltip, setTooltip]);\n\n const onShowTooltipSoft = (show: boolean) => {\n if (!tooltip?.feedback) {\n setTooltip(show ? { item: item.id, feedback: false } : null);\n }\n };\n\n const onShowTooltipHard = (show: boolean) => {\n if (!show && item.id !== tooltip?.item) {\n return;\n }\n\n setTooltip(show ? { item: item.id, feedback: false } : null);\n };\n\n const onClickHandler = (event: CustomEvent<ButtonGroupProps.ItemClickDetails>) => {\n const hasPopoverFeedback = 'popoverFeedback' in item && item.popoverFeedback;\n\n if (hasPopoverFeedback) {\n setTooltip({ item: item.id, feedback: true });\n }\n\n fireCancelableEvent(onItemClick, event.detail, event);\n };\n\n const onFilesChangeHandler = (event: CustomEvent<ButtonGroupProps.FilesChangeDetails>) => {\n fireCancelableEvent(onFilesChange, event.detail, event);\n\n setTooltip(null);\n };\n\n return (\n <div\n key={item.id}\n className={styles['item-wrapper']}\n ref={containerRef}\n onPointerEnter={() => onShowTooltipSoft(true)}\n onPointerLeave={() => onShowTooltipSoft(false)}\n onFocus={event => {\n // Showing no tooltip when the focus comes from inside the container.\n // This is needed to prevent the tooltip after a menu closes with item selection or Escape.\n if (event && event.relatedTarget && nodeBelongs(containerRef.current, event.relatedTarget)) {\n return;\n }\n onShowTooltipHard(true);\n }}\n onBlur={() => onShowTooltipHard(false)}\n >\n {item.type === 'icon-button' && (\n <IconButtonItem\n ref={itemRef}\n item={item}\n onItemClick={onClickHandler}\n showTooltip={tooltip?.item === item.id}\n showFeedback={!!tooltip?.feedback}\n />\n )}\n {item.type === 'icon-toggle-button' && (\n <IconToggleButtonItem\n ref={itemRef}\n item={item}\n onItemClick={onClickHandler}\n showTooltip={tooltip?.item === item.id}\n showFeedback={!!tooltip?.feedback}\n />\n )}\n {item.type === 'icon-file-input' && (\n <FileInputItem\n ref={itemRef}\n item={item}\n onFilesChange={onFilesChangeHandler}\n showTooltip={tooltip?.item === item.id}\n />\n )}\n {item.type === 'menu-dropdown' && (\n <MenuDropdownItem\n ref={itemRef}\n item={item}\n showTooltip={tooltip?.item === item.id}\n onItemClick={onClickHandler}\n expandToViewport={dropdownExpandToViewport}\n />\n )}\n </div>\n );\n }\n);\n\nexport default ItemElement;\n"]}
@@ -27,12 +27,12 @@ export function ResizableBox({ children, height, minHeight, onResize }) {
27
27
  const onMouseUp = () => {
28
28
  setDragOffset(null);
29
29
  };
30
+ const controller = new AbortController();
30
31
  document.body.classList.add(styles['resize-active']);
31
- document.addEventListener('mousemove', onMouseMove);
32
- document.addEventListener('mouseup', onMouseUp);
32
+ document.addEventListener('mousemove', onMouseMove, { signal: controller.signal });
33
+ document.addEventListener('mouseup', onMouseUp, { signal: controller.signal });
33
34
  return () => {
34
- document.removeEventListener('mousemove', onMouseMove);
35
- document.removeEventListener('mouseup', onMouseUp);
35
+ controller.abort();
36
36
  document.body.classList.remove(styles['resize-active']);
37
37
  };
38
38
  }, [dragOffset, minHeight, onResizeStable]);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/code-editor/resizable-box/index.tsx"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,sCAAsC;AACtC,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAElF,OAAO,MAAM,MAAM,iBAAiB,CAAC;AASrC,MAAM,UAAU,YAAY,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAkB;IACpF,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAClE,MAAM,cAAc,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACnD,MAAM,YAAY,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAElD,MAAM,WAAW,GAA4B,KAAK,CAAC,EAAE;QACnD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;YAC/C,OAAO;SACR;QACD,MAAM,eAAe,GAAG,YAAY,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC,MAAM,CAAC;QAC5E,aAAa,CAAC,eAAe,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;IACjD,CAAC,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,UAAU,KAAK,IAAI,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;YAChD,OAAO;SACR;QACD,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC;QAEvC,MAAM,WAAW,GAAG,CAAC,KAAiB,EAAE,EAAE;YACxC,MAAM,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC,qBAAqB,EAAE,CAAC;YAClD,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC;YAC7B,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,UAAU,GAAG,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC;QACjE,CAAC,CAAC;QACF,MAAM,SAAS,GAAG,GAAG,EAAE;YACrB,aAAa,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC,CAAC;QACF,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC;QACrD,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QACpD,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAChD,OAAO,GAAG,EAAE;YACV,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;YACvD,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;YACnD,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC;QAC1D,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,UAAU,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC,CAAC;IAE5C,OAAO,CACL,6BAAK,GAAG,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE;QAC1E,QAAQ;QACT,8BAAM,SAAS,EAAE,MAAM,CAAC,sBAAsB,CAAC,EAAE,WAAW,EAAE,WAAW,GAAI,CACzE,CACP,CAAC;AACJ,CAAC","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport React, { useEffect, useRef, useState } from 'react';\n\nimport { useStableCallback } from '@cloudscape-design/component-toolkit/internal';\n\nimport styles from './styles.css.js';\n\nexport interface ResizeBoxProps {\n children: React.ReactNode;\n height: number;\n minHeight: number;\n onResize: (newHeight: number) => void;\n}\n\nexport function ResizableBox({ children, height, minHeight, onResize }: ResizeBoxProps) {\n const [dragOffset, setDragOffset] = useState<null | number>(null);\n const onResizeStable = useStableCallback(onResize);\n const containerRef = useRef<HTMLDivElement>(null);\n\n const onMouseDown: React.MouseEventHandler = event => {\n if (event.button !== 0 || !containerRef.current) {\n return;\n }\n const containerBottom = containerRef.current.getBoundingClientRect().bottom;\n setDragOffset(containerBottom - event.clientY);\n };\n\n useEffect(() => {\n if (dragOffset === null || !containerRef.current) {\n return;\n }\n const container = containerRef.current;\n\n const onMouseMove = (event: MouseEvent) => {\n const { top } = container.getBoundingClientRect();\n const cursor = event.clientY;\n onResizeStable(Math.max(cursor + dragOffset - top, minHeight));\n };\n const onMouseUp = () => {\n setDragOffset(null);\n };\n document.body.classList.add(styles['resize-active']);\n document.addEventListener('mousemove', onMouseMove);\n document.addEventListener('mouseup', onMouseUp);\n return () => {\n document.removeEventListener('mousemove', onMouseMove);\n document.removeEventListener('mouseup', onMouseUp);\n document.body.classList.remove(styles['resize-active']);\n };\n }, [dragOffset, minHeight, onResizeStable]);\n\n return (\n <div ref={containerRef} className={styles['resizable-box']} style={{ height }}>\n {children}\n <span className={styles['resizable-box-handle']} onMouseDown={onMouseDown} />\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/code-editor/resizable-box/index.tsx"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,sCAAsC;AACtC,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAElF,OAAO,MAAM,MAAM,iBAAiB,CAAC;AASrC,MAAM,UAAU,YAAY,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAkB;IACpF,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAClE,MAAM,cAAc,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACnD,MAAM,YAAY,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAElD,MAAM,WAAW,GAA4B,KAAK,CAAC,EAAE;QACnD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;YAC/C,OAAO;SACR;QACD,MAAM,eAAe,GAAG,YAAY,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC,MAAM,CAAC;QAC5E,aAAa,CAAC,eAAe,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;IACjD,CAAC,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,UAAU,KAAK,IAAI,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;YAChD,OAAO;SACR;QACD,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC;QAEvC,MAAM,WAAW,GAAG,CAAC,KAAiB,EAAE,EAAE;YACxC,MAAM,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC,qBAAqB,EAAE,CAAC;YAClD,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC;YAC7B,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,UAAU,GAAG,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC;QACjE,CAAC,CAAC;QACF,MAAM,SAAS,GAAG,GAAG,EAAE;YACrB,aAAa,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC,CAAC;QACF,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC;QACrD,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;QACnF,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;QAC/E,OAAO,GAAG,EAAE;YACV,UAAU,CAAC,KAAK,EAAE,CAAC;YACnB,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC;QAC1D,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,UAAU,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC,CAAC;IAE5C,OAAO,CACL,6BAAK,GAAG,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE;QAC1E,QAAQ;QACT,8BAAM,SAAS,EAAE,MAAM,CAAC,sBAAsB,CAAC,EAAE,WAAW,EAAE,WAAW,GAAI,CACzE,CACP,CAAC;AACJ,CAAC","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport React, { useEffect, useRef, useState } from 'react';\n\nimport { useStableCallback } from '@cloudscape-design/component-toolkit/internal';\n\nimport styles from './styles.css.js';\n\nexport interface ResizeBoxProps {\n children: React.ReactNode;\n height: number;\n minHeight: number;\n onResize: (newHeight: number) => void;\n}\n\nexport function ResizableBox({ children, height, minHeight, onResize }: ResizeBoxProps) {\n const [dragOffset, setDragOffset] = useState<null | number>(null);\n const onResizeStable = useStableCallback(onResize);\n const containerRef = useRef<HTMLDivElement>(null);\n\n const onMouseDown: React.MouseEventHandler = event => {\n if (event.button !== 0 || !containerRef.current) {\n return;\n }\n const containerBottom = containerRef.current.getBoundingClientRect().bottom;\n setDragOffset(containerBottom - event.clientY);\n };\n\n useEffect(() => {\n if (dragOffset === null || !containerRef.current) {\n return;\n }\n const container = containerRef.current;\n\n const onMouseMove = (event: MouseEvent) => {\n const { top } = container.getBoundingClientRect();\n const cursor = event.clientY;\n onResizeStable(Math.max(cursor + dragOffset - top, minHeight));\n };\n const onMouseUp = () => {\n setDragOffset(null);\n };\n const controller = new AbortController();\n document.body.classList.add(styles['resize-active']);\n document.addEventListener('mousemove', onMouseMove, { signal: controller.signal });\n document.addEventListener('mouseup', onMouseUp, { signal: controller.signal });\n return () => {\n controller.abort();\n document.body.classList.remove(styles['resize-active']);\n };\n }, [dragOffset, minHeight, onResizeStable]);\n\n return (\n <div ref={containerRef} className={styles['resizable-box']} style={{ height }}>\n {children}\n <span className={styles['resizable-box-handle']} onMouseDown={onMouseDown} />\n </div>\n );\n}\n"]}
@@ -70,11 +70,11 @@ export const useStickyHeader = (rootRef, headerRef, __stickyHeader, __stickyOffs
70
70
  }, [rootRef, headerRef]);
71
71
  useEffect(() => {
72
72
  if (isSticky) {
73
- window.addEventListener('scroll', checkIfStuck, true);
74
- window.addEventListener('resize', checkIfStuck);
73
+ const controller = new AbortController();
74
+ window.addEventListener('scroll', checkIfStuck, { capture: true, signal: controller.signal });
75
+ window.addEventListener('resize', checkIfStuck, { signal: controller.signal });
75
76
  return () => {
76
- window.removeEventListener('scroll', checkIfStuck, true);
77
- window.removeEventListener('resize', checkIfStuck);
77
+ controller.abort();
78
78
  };
79
79
  }
80
80
  }, [isSticky, checkIfStuck]);
@@ -1 +1 @@
1
- {"version":3,"file":"use-sticky-header.js","sourceRoot":"","sources":["../../../src/container/use-sticky-header.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport { createContext, RefObject, useCallback, useEffect, useLayoutEffect, useState } from 'react';\n\nimport { findUpUntil } from '@cloudscape-design/component-toolkit/dom';\n\nimport * as tokens from '../internal/generated/styles/tokens';\nimport { useMobile } from '../internal/hooks/use-mobile';\nimport globalVars from '../internal/styles/global-vars';\nimport { getOverflowParents } from '../internal/utils/scrollable-containers';\n\ninterface StickyHeaderContextProps {\n isStuck: boolean;\n}\n\ninterface ComputeOffsetProps {\n isMobile: boolean;\n __stickyOffset?: number;\n __mobileStickyOffset?: number;\n hasInnerOverflowParents: boolean;\n __additionalOffset?: boolean;\n}\n\nexport function computeOffset({\n isMobile,\n __stickyOffset,\n __mobileStickyOffset,\n hasInnerOverflowParents,\n __additionalOffset,\n}: ComputeOffsetProps): string {\n const localOffset = isMobile ? (__stickyOffset ?? 0) - (__mobileStickyOffset ?? 0) : __stickyOffset ?? 0;\n if (hasInnerOverflowParents || __stickyOffset !== undefined) {\n return `${localOffset}px`;\n }\n const globalOffset = `var(${globalVars.stickyVerticalTopOffset}, 0px)`;\n\n return `calc(${globalOffset} + ${localOffset}px + ${__additionalOffset ? tokens.spaceScaledS : '0px'})`;\n}\n\nexport const StickyHeaderContext = createContext<StickyHeaderContextProps>({\n isStuck: false,\n});\n\nexport const useStickyHeader = (\n rootRef: RefObject<HTMLDivElement>,\n headerRef: RefObject<HTMLDivElement>,\n __stickyHeader?: boolean,\n __stickyOffset?: number,\n __mobileStickyOffset?: number,\n __disableMobile?: boolean,\n __additionalOffset = false\n) => {\n const isMobile = useMobile();\n const disableSticky = isMobile && __disableMobile;\n const isSticky = !disableSticky && !!__stickyHeader;\n\n // If it has overflow parents inside the app layout, we shouldn't apply a sticky offset.\n const [hasInnerOverflowParents, setHasInnerOverflowParents] = useState(false);\n const [isStuck, setIsStuck] = useState(false);\n useLayoutEffect(() => {\n if (rootRef.current) {\n const overflowParents = getOverflowParents(rootRef.current);\n const mainElement = findUpUntil(rootRef.current, elem => elem.tagName === 'MAIN');\n // In both versions of the app layout, the scrolling element for disableBodyScroll\n // is the <main>. If the closest overflow parent is also the closest <main> and we have\n // offset values, it's safe to assume that it's the app layout scroll root and we\n // should stop there.\n setHasInnerOverflowParents(overflowParents.length > 0 && overflowParents[0] !== mainElement);\n }\n }, [rootRef]);\n\n const computedOffset = computeOffset({\n isMobile,\n __stickyOffset,\n __mobileStickyOffset,\n hasInnerOverflowParents,\n __additionalOffset,\n });\n\n const stickyStyles = isSticky\n ? {\n style: {\n top: computedOffset,\n },\n }\n : {};\n\n // \"stuck\" state, when the header has moved from its original posititon has a\n // box-shadow, applied here by a \"header-stuck\" className\n const checkIfStuck = useCallback(\n ({ isTrusted, target, type }) => {\n if (type === 'resize' && target === window && !isTrusted) {\n // The window size didn't actually change, it was a synthetic event\n return;\n }\n if (rootRef.current && headerRef.current) {\n const rootTopBorderWidth = parseFloat(getComputedStyle(rootRef.current).borderTopWidth) || 0;\n const rootTop = rootRef.current.getBoundingClientRect().top + rootTopBorderWidth;\n const headerTop = headerRef.current.getBoundingClientRect().top;\n\n if (rootTop < headerTop) {\n setIsStuck(true);\n } else {\n setIsStuck(false);\n }\n }\n },\n [rootRef, headerRef]\n );\n useEffect(() => {\n if (isSticky) {\n window.addEventListener('scroll', checkIfStuck, true);\n window.addEventListener('resize', checkIfStuck);\n return () => {\n window.removeEventListener('scroll', checkIfStuck, true);\n window.removeEventListener('resize', checkIfStuck);\n };\n }\n }, [isSticky, checkIfStuck]);\n return {\n isSticky,\n isStuck,\n stickyStyles,\n };\n};\n"]}
1
+ {"version":3,"file":"use-sticky-header.js","sourceRoot":"","sources":["../../../src/container/use-sticky-header.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport { createContext, RefObject, useCallback, useEffect, useLayoutEffect, useState } from 'react';\n\nimport { findUpUntil } from '@cloudscape-design/component-toolkit/dom';\n\nimport * as tokens from '../internal/generated/styles/tokens';\nimport { useMobile } from '../internal/hooks/use-mobile';\nimport globalVars from '../internal/styles/global-vars';\nimport { getOverflowParents } from '../internal/utils/scrollable-containers';\n\ninterface StickyHeaderContextProps {\n isStuck: boolean;\n}\n\ninterface ComputeOffsetProps {\n isMobile: boolean;\n __stickyOffset?: number;\n __mobileStickyOffset?: number;\n hasInnerOverflowParents: boolean;\n __additionalOffset?: boolean;\n}\n\nexport function computeOffset({\n isMobile,\n __stickyOffset,\n __mobileStickyOffset,\n hasInnerOverflowParents,\n __additionalOffset,\n}: ComputeOffsetProps): string {\n const localOffset = isMobile ? (__stickyOffset ?? 0) - (__mobileStickyOffset ?? 0) : __stickyOffset ?? 0;\n if (hasInnerOverflowParents || __stickyOffset !== undefined) {\n return `${localOffset}px`;\n }\n const globalOffset = `var(${globalVars.stickyVerticalTopOffset}, 0px)`;\n\n return `calc(${globalOffset} + ${localOffset}px + ${__additionalOffset ? tokens.spaceScaledS : '0px'})`;\n}\n\nexport const StickyHeaderContext = createContext<StickyHeaderContextProps>({\n isStuck: false,\n});\n\nexport const useStickyHeader = (\n rootRef: RefObject<HTMLDivElement>,\n headerRef: RefObject<HTMLDivElement>,\n __stickyHeader?: boolean,\n __stickyOffset?: number,\n __mobileStickyOffset?: number,\n __disableMobile?: boolean,\n __additionalOffset = false\n) => {\n const isMobile = useMobile();\n const disableSticky = isMobile && __disableMobile;\n const isSticky = !disableSticky && !!__stickyHeader;\n\n // If it has overflow parents inside the app layout, we shouldn't apply a sticky offset.\n const [hasInnerOverflowParents, setHasInnerOverflowParents] = useState(false);\n const [isStuck, setIsStuck] = useState(false);\n useLayoutEffect(() => {\n if (rootRef.current) {\n const overflowParents = getOverflowParents(rootRef.current);\n const mainElement = findUpUntil(rootRef.current, elem => elem.tagName === 'MAIN');\n // In both versions of the app layout, the scrolling element for disableBodyScroll\n // is the <main>. If the closest overflow parent is also the closest <main> and we have\n // offset values, it's safe to assume that it's the app layout scroll root and we\n // should stop there.\n setHasInnerOverflowParents(overflowParents.length > 0 && overflowParents[0] !== mainElement);\n }\n }, [rootRef]);\n\n const computedOffset = computeOffset({\n isMobile,\n __stickyOffset,\n __mobileStickyOffset,\n hasInnerOverflowParents,\n __additionalOffset,\n });\n\n const stickyStyles = isSticky\n ? {\n style: {\n top: computedOffset,\n },\n }\n : {};\n\n // \"stuck\" state, when the header has moved from its original posititon has a\n // box-shadow, applied here by a \"header-stuck\" className\n const checkIfStuck = useCallback(\n ({ isTrusted, target, type }) => {\n if (type === 'resize' && target === window && !isTrusted) {\n // The window size didn't actually change, it was a synthetic event\n return;\n }\n if (rootRef.current && headerRef.current) {\n const rootTopBorderWidth = parseFloat(getComputedStyle(rootRef.current).borderTopWidth) || 0;\n const rootTop = rootRef.current.getBoundingClientRect().top + rootTopBorderWidth;\n const headerTop = headerRef.current.getBoundingClientRect().top;\n\n if (rootTop < headerTop) {\n setIsStuck(true);\n } else {\n setIsStuck(false);\n }\n }\n },\n [rootRef, headerRef]\n );\n useEffect(() => {\n if (isSticky) {\n const controller = new AbortController();\n window.addEventListener('scroll', checkIfStuck, { capture: true, signal: controller.signal });\n window.addEventListener('resize', checkIfStuck, { signal: controller.signal });\n return () => {\n controller.abort();\n };\n }\n }, [isSticky, checkIfStuck]);\n return {\n isSticky,\n isStuck,\n stickyStyles,\n };\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"use-files-dragging.d.ts","sourceRoot":"","sources":["../../../src/file-dropzone/use-files-dragging.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,wBAAgB,gBAAgB;;EAoD/B"}
1
+ {"version":3,"file":"use-files-dragging.d.ts","sourceRoot":"","sources":["../../../src/file-dropzone/use-files-dragging.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,wBAAgB,gBAAgB;;EAmD/B"}
@@ -38,14 +38,13 @@ export function useFilesDragging() {
38
38
  event.preventDefault();
39
39
  dragTimer = setTimeout(() => setFilesDragging(false), 25);
40
40
  };
41
- document.addEventListener('dragover', onDocumentDragOver, false);
42
- document.addEventListener('dragleave', onDocumentDragLeave, false);
43
- document.addEventListener('drop', onDocumentDrop, false);
41
+ const controller = new AbortController();
42
+ document.addEventListener('dragover', onDocumentDragOver, { signal: controller.signal });
43
+ document.addEventListener('dragleave', onDocumentDragLeave, { signal: controller.signal });
44
+ document.addEventListener('drop', onDocumentDrop, { signal: controller.signal });
44
45
  return () => {
45
46
  dragTimer && clearTimeout(dragTimer);
46
- document.removeEventListener('dragover', onDocumentDragOver);
47
- document.removeEventListener('dragleave', onDocumentDragLeave);
48
- document.removeEventListener('drop', onDocumentDrop);
47
+ controller.abort();
49
48
  };
50
49
  }, []);
51
50
  return { areFilesDragging };
@@ -1 +1 @@
1
- {"version":3,"file":"use-files-dragging.js","sourceRoot":"","sources":["../../../src/file-dropzone/use-files-dragging.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,sCAAsC;AACtC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE7D,4CAA4C;IAC5C,SAAS,CAAC,GAAG,EAAE;QACb,8CAA8C;QAC9C,IAAI,SAAS,GAAyC,IAAI,CAAC;QAE3D,mFAAmF;QACnF,MAAM,kBAAkB,GAAG,CAAC,KAAgB,EAAE,EAAE;;YAC9C,KAAK,CAAC,cAAc,EAAE,CAAC;YAEvB,IAAI,KAAK,GAAG,CAAC,CAAC;YACd,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,CAAA,MAAA,KAAK,CAAC,YAAY,0CAAE,KAAK,CAAC,MAAM,KAAI,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE;gBACzE,IAAI,CAAA,MAAA,KAAK,CAAC,YAAY,0CAAE,KAAK,CAAC,IAAI,CAAC,MAAK,OAAO,EAAE;oBAC/C,KAAK,EAAE,CAAC;iBACT;aACF;YAED,IAAI,KAAK,GAAG,CAAC,EAAE;gBACb,gBAAgB,CAAC,IAAI,CAAC,CAAC;gBACvB,SAAS,IAAI,YAAY,CAAC,SAAS,CAAC,CAAC;aACtC;QACH,CAAC,CAAC;QAEF,iFAAiF;QACjF,MAAM,mBAAmB,GAAG,CAAC,KAAgB,EAAE,EAAE;YAC/C,KAAK,CAAC,cAAc,EAAE,CAAC;YAEvB,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QAC5D,CAAC,CAAC;QAEF,qDAAqD;QACrD,MAAM,cAAc,GAAG,CAAC,KAAgB,EAAE,EAAE;YAC1C,KAAK,CAAC,cAAc,EAAE,CAAC;YAEvB,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QAC5D,CAAC,CAAC;QAEF,QAAQ,CAAC,gBAAgB,CAAC,UAAU,EAAE,kBAAkB,EAAE,KAAK,CAAC,CAAC;QACjE,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,mBAAmB,EAAE,KAAK,CAAC,CAAC;QACnE,QAAQ,CAAC,gBAAgB,CAAC,MAAM,EAAE,cAAc,EAAE,KAAK,CAAC,CAAC;QAEzD,OAAO,GAAG,EAAE;YACV,SAAS,IAAI,YAAY,CAAC,SAAS,CAAC,CAAC;YACrC,QAAQ,CAAC,mBAAmB,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;YAC7D,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC;YAC/D,QAAQ,CAAC,mBAAmB,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;QACvD,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAC9B,CAAC","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport { useEffect, useState } from 'react';\n\n/**\n * A utility to determine whether or not a file is being currently dragged into the window.\n *\n * @returns An object with the following arguments:\n * `areFilesDragging`: True if a file is being dragged over the current window, false otherwise.\n */\nexport function useFilesDragging() {\n const [areFilesDragging, setFilesDragging] = useState(false);\n\n // Registering global drag events listeners.\n useEffect(() => {\n // The timer helps avoiding dropzone blinking.\n let dragTimer: null | ReturnType<typeof setTimeout> = null;\n\n // The file-upload dropzone is shown when the user drags files over to the browser.\n const onDocumentDragOver = (event: DragEvent) => {\n event.preventDefault();\n\n let files = 0;\n for (let item = 0; item < (event.dataTransfer?.types.length || 0); item++) {\n if (event.dataTransfer?.types[item] === 'Files') {\n files++;\n }\n }\n\n if (files > 0) {\n setFilesDragging(true);\n dragTimer && clearTimeout(dragTimer);\n }\n };\n\n // When the files are no longer dragged over the browser the state must be reset.\n const onDocumentDragLeave = (event: DragEvent) => {\n event.preventDefault();\n\n dragTimer = setTimeout(() => setFilesDragging(false), 25);\n };\n\n // If the files were dropped the state must be reset.\n const onDocumentDrop = (event: DragEvent) => {\n event.preventDefault();\n\n dragTimer = setTimeout(() => setFilesDragging(false), 25);\n };\n\n document.addEventListener('dragover', onDocumentDragOver, false);\n document.addEventListener('dragleave', onDocumentDragLeave, false);\n document.addEventListener('drop', onDocumentDrop, false);\n\n return () => {\n dragTimer && clearTimeout(dragTimer);\n document.removeEventListener('dragover', onDocumentDragOver);\n document.removeEventListener('dragleave', onDocumentDragLeave);\n document.removeEventListener('drop', onDocumentDrop);\n };\n }, []);\n\n return { areFilesDragging };\n}\n"]}
1
+ {"version":3,"file":"use-files-dragging.js","sourceRoot":"","sources":["../../../src/file-dropzone/use-files-dragging.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,sCAAsC;AACtC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE7D,4CAA4C;IAC5C,SAAS,CAAC,GAAG,EAAE;QACb,8CAA8C;QAC9C,IAAI,SAAS,GAAyC,IAAI,CAAC;QAE3D,mFAAmF;QACnF,MAAM,kBAAkB,GAAG,CAAC,KAAgB,EAAE,EAAE;;YAC9C,KAAK,CAAC,cAAc,EAAE,CAAC;YAEvB,IAAI,KAAK,GAAG,CAAC,CAAC;YACd,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,CAAA,MAAA,KAAK,CAAC,YAAY,0CAAE,KAAK,CAAC,MAAM,KAAI,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE;gBACzE,IAAI,CAAA,MAAA,KAAK,CAAC,YAAY,0CAAE,KAAK,CAAC,IAAI,CAAC,MAAK,OAAO,EAAE;oBAC/C,KAAK,EAAE,CAAC;iBACT;aACF;YAED,IAAI,KAAK,GAAG,CAAC,EAAE;gBACb,gBAAgB,CAAC,IAAI,CAAC,CAAC;gBACvB,SAAS,IAAI,YAAY,CAAC,SAAS,CAAC,CAAC;aACtC;QACH,CAAC,CAAC;QAEF,iFAAiF;QACjF,MAAM,mBAAmB,GAAG,CAAC,KAAgB,EAAE,EAAE;YAC/C,KAAK,CAAC,cAAc,EAAE,CAAC;YAEvB,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QAC5D,CAAC,CAAC;QAEF,qDAAqD;QACrD,MAAM,cAAc,GAAG,CAAC,KAAgB,EAAE,EAAE;YAC1C,KAAK,CAAC,cAAc,EAAE,CAAC;YAEvB,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QAC5D,CAAC,CAAC;QAEF,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,QAAQ,CAAC,gBAAgB,CAAC,UAAU,EAAE,kBAAkB,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;QACzF,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,mBAAmB,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;QAC3F,QAAQ,CAAC,gBAAgB,CAAC,MAAM,EAAE,cAAc,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;QAEjF,OAAO,GAAG,EAAE;YACV,SAAS,IAAI,YAAY,CAAC,SAAS,CAAC,CAAC;YACrC,UAAU,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAC9B,CAAC","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport { useEffect, useState } from 'react';\n\n/**\n * A utility to determine whether or not a file is being currently dragged into the window.\n *\n * @returns An object with the following arguments:\n * `areFilesDragging`: True if a file is being dragged over the current window, false otherwise.\n */\nexport function useFilesDragging() {\n const [areFilesDragging, setFilesDragging] = useState(false);\n\n // Registering global drag events listeners.\n useEffect(() => {\n // The timer helps avoiding dropzone blinking.\n let dragTimer: null | ReturnType<typeof setTimeout> = null;\n\n // The file-upload dropzone is shown when the user drags files over to the browser.\n const onDocumentDragOver = (event: DragEvent) => {\n event.preventDefault();\n\n let files = 0;\n for (let item = 0; item < (event.dataTransfer?.types.length || 0); item++) {\n if (event.dataTransfer?.types[item] === 'Files') {\n files++;\n }\n }\n\n if (files > 0) {\n setFilesDragging(true);\n dragTimer && clearTimeout(dragTimer);\n }\n };\n\n // When the files are no longer dragged over the browser the state must be reset.\n const onDocumentDragLeave = (event: DragEvent) => {\n event.preventDefault();\n\n dragTimer = setTimeout(() => setFilesDragging(false), 25);\n };\n\n // If the files were dropped the state must be reset.\n const onDocumentDrop = (event: DragEvent) => {\n event.preventDefault();\n\n dragTimer = setTimeout(() => setFilesDragging(false), 25);\n };\n\n const controller = new AbortController();\n document.addEventListener('dragover', onDocumentDragOver, { signal: controller.signal });\n document.addEventListener('dragleave', onDocumentDragLeave, { signal: controller.signal });\n document.addEventListener('drop', onDocumentDrop, { signal: controller.signal });\n\n return () => {\n dragTimer && clearTimeout(dragTimer);\n controller.abort();\n };\n }, []);\n\n return { areFilesDragging };\n}\n"]}
@@ -477,11 +477,11 @@ export const AnalyticsFunnelSubStep = ({ children, subStepIdentifier, subStepErr
477
477
  (_a = focusCleanupFunction.current) === null || _a === void 0 ? void 0 : _a.call(focusCleanupFunction);
478
478
  }
479
479
  });
480
- window.addEventListener('mousedown', onMouseDown);
481
- window.addEventListener('mouseup', onMouseUp);
480
+ const controller = new AbortController();
481
+ window.addEventListener('mousedown', onMouseDown, { signal: controller.signal });
482
+ window.addEventListener('mouseup', onMouseUp, { signal: controller.signal });
482
483
  return () => {
483
- window.removeEventListener('mousedown', onMouseDown);
484
- window.removeEventListener('mouseup', onMouseUp);
484
+ controller.abort();
485
485
  };
486
486
  }, [
487
487
  funnelInteractionId,
@@ -1 +1 @@
1
- {"version":3,"file":"analytics-funnel.js","sourceRoot":"","sources":["../../../../../src/internal/analytics/components/analytics-funnel.tsx"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport React, { useContext, useEffect, useRef, useState } from 'react';\n\nimport { PACKAGE_VERSION } from '../../environment';\nimport { useDebounceCallback } from '../../hooks/use-debounce-callback';\nimport { useUniqueId } from '../../hooks/use-unique-id';\nimport { useVisualRefresh } from '../../hooks/use-visual-mode';\nimport { nodeBelongs } from '../../utils/node-belongs';\nimport {\n FunnelContext,\n FunnelContextValue,\n FunnelState,\n FunnelStepContext,\n FunnelStepContextValue,\n FunnelSubStepContext,\n FunnelSubStepContextValue,\n} from '../context/analytics-context';\nimport { useFunnel, useFunnelStep } from '../hooks/use-funnel';\nimport { FunnelMetrics, PerformanceMetrics } from '../index';\nimport {\n AnalyticsMetadata,\n FunnelStartProps,\n FunnelStepProps,\n StepConfiguration,\n SubStepConfiguration,\n TaskCompletionDataProps,\n} from '../interfaces';\nimport {\n DATA_ATTR_FUNNEL_STEP,\n DATA_ATTR_RESOURCE_TYPE,\n getFunnelNameSelector,\n getSubStepAllSelector,\n getSubStepNameSelector,\n getSubStepSelector,\n getTextFromSelector,\n} from '../selectors';\n\nconst FUNNEL_VERSION = '1.4';\n\ninterface AnalyticsFunnelProps {\n mounted?: boolean;\n children?: React.ReactNode;\n stepConfiguration?: StepConfiguration[];\n funnelNameSelectors?: () => string[];\n funnelType: FunnelStartProps['funnelType'];\n optionalStepNumbers: FunnelStartProps['optionalStepNumbers'];\n totalFunnelSteps: FunnelStartProps['totalFunnelSteps'];\n funnelIdentifier?: AnalyticsMetadata['instanceIdentifier'];\n funnelFlowType?: AnalyticsMetadata['flowType'];\n funnelErrorContext?: AnalyticsMetadata['errorContext'];\n funnelResourceType?: AnalyticsMetadata['resourceType'];\n}\n\nexport const AnalyticsFunnel = (props: AnalyticsFunnelProps) => {\n const { isInFunnel } = useFunnel();\n /*\n If the current funnel component is a Form (i.e. single-page funnel), it should\n defer its funnel-handling to a parent Form element, if present.\n Wizards (i.e. multi-page funnels) always take highest precedence for handling funnels,\n and do not defer to any other element.\n */\n if (isInFunnel && props.funnelType === 'single-page') {\n return <>{props.children}</>;\n }\n\n return <InnerAnalyticsFunnel {...props} />;\n};\n\nexport const CREATION_EDIT_FLOW_DONE_EVENT_NAME = 'awsui-creation-edit-flow-done';\nconst dispatchCreateEditFlowDoneEvent = () => {\n try {\n window.top?.document.dispatchEvent(new Event(CREATION_EDIT_FLOW_DONE_EVENT_NAME));\n } catch {\n // probably because of cross-origin error, then do not dispatch the event\n }\n};\n\nconst onFunnelCancelled = ({\n funnelInteractionId,\n funnelIdentifier,\n}: {\n funnelInteractionId: string;\n funnelIdentifier?: string;\n}) => {\n FunnelMetrics.funnelCancelled({ funnelInteractionId, funnelIdentifier });\n};\n\nconst onFunnelComplete = (taskCompletionDataProps: TaskCompletionDataProps) => {\n FunnelMetrics.funnelComplete({\n funnelInteractionId: taskCompletionDataProps.taskInteractionId,\n funnelIdentifier: taskCompletionDataProps.taskIdentifier,\n });\n PerformanceMetrics.taskCompletionData(taskCompletionDataProps);\n dispatchCreateEditFlowDoneEvent();\n};\n\nfunction evaluateSelectors(selectors: string[], defaultSelector: string) {\n for (const selector of selectors) {\n const element = document.querySelector(selector);\n if (element) {\n return selector;\n }\n }\n\n return defaultSelector;\n}\n\nconst InnerAnalyticsFunnel = ({ mounted = true, children, stepConfiguration, ...props }: AnalyticsFunnelProps) => {\n const [funnelInteractionId, setFunnelInteractionId] = useState<string>('');\n const [submissionAttempt, setSubmissionAttempt] = useState(0);\n const isVisualRefresh = useVisualRefresh();\n const funnelState = useRef<FunnelState>('default');\n const funnelNameSelector = useRef<string>(getFunnelNameSelector());\n const errorCount = useRef<number>(0);\n const loadingButtonCount = useRef<number>(0);\n const wizardCount = useRef<number>(0);\n const latestFocusCleanupFunction = useRef<undefined | (() => void)>(undefined);\n const formSubmitStartTime = useRef<number>(0);\n // This useEffect hook is run once on component mount to initiate the funnel analytics.\n // It first calls the 'funnelStart' method from FunnelMetrics, providing all necessary details\n // about the funnel, and receives a unique interaction id.\n // This unique interaction id is then stored in the state for further use.\n //\n // On component unmount, it checks whether the funnel was successfully completed.\n // Based on this, it either calls 'funnelComplete' or 'funnelCancelled' method from FunnelMetrics.\n //\n // The eslint-disable is required as we deliberately want this effect to run only once on mount and unmount,\n // hence we do not provide any dependencies.\n useEffect(() => {\n if (!mounted) {\n return;\n }\n\n /*\n We run this effect with a delay, in order to detect whether this funnel contains a Wizard.\n If it does contain a Wizard, that Wizard should take precedence for handling the funnel, and\n this current funnel component should do nothing.\n */\n let funnelInteractionId: string;\n const handle = setTimeout(() => {\n funnelNameSelector.current = evaluateSelectors(props.funnelNameSelectors?.() || [], getFunnelNameSelector());\n if (props.funnelType === 'single-page' && wizardCount.current > 0) {\n return;\n }\n\n // Reset the state, in case the component was re-mounted.\n funnelState.current = 'default';\n const funnelName = getTextFromSelector(funnelNameSelector.current) ?? '';\n\n const singleStepFlowStepConfiguration = [\n {\n number: 1,\n isOptional: false,\n name: funnelName,\n stepIdentifier: props.funnelIdentifier,\n },\n ];\n\n funnelInteractionId = FunnelMetrics.funnelStart({\n funnelName,\n funnelIdentifier: props.funnelIdentifier,\n flowType: props.funnelFlowType,\n funnelNameSelector: funnelNameSelector.current,\n optionalStepNumbers: props.optionalStepNumbers,\n funnelType: props.funnelType,\n totalFunnelSteps: props.totalFunnelSteps,\n componentVersion: PACKAGE_VERSION,\n componentTheme: isVisualRefresh ? 'vr' : 'classic',\n funnelVersion: FUNNEL_VERSION,\n stepConfiguration: stepConfiguration ?? singleStepFlowStepConfiguration,\n resourceType: props.funnelResourceType || getTextFromSelector(`[${DATA_ATTR_RESOURCE_TYPE}]`),\n });\n\n setFunnelInteractionId(funnelInteractionId);\n }, 1);\n\n /*\n A funnel counts as \"successful\" if it is unmounted after being \"complete\".\n */\n /* eslint-disable react-hooks/exhaustive-deps */\n return () => {\n clearTimeout(handle);\n if (props.funnelType === 'single-page' && wizardCount.current > 0) {\n return;\n }\n\n if (funnelState.current === 'validating') {\n // Finish the validation phase early.\n const taskCompletionDataProps: TaskCompletionDataProps = {\n taskIdentifier: props.funnelIdentifier,\n taskType: props.funnelType,\n timeToRespondAfterFormSubmit: performance.now() - formSubmitStartTime.current,\n taskInteractionId: funnelInteractionId,\n taskFlowType: props.funnelFlowType,\n };\n onFunnelComplete(taskCompletionDataProps);\n funnelState.current = 'complete';\n }\n\n if (funnelState.current === 'complete') {\n FunnelMetrics.funnelSuccessful({ funnelInteractionId, funnelIdentifier: props.funnelIdentifier });\n } else {\n funnelState.current = 'cancelled';\n onFunnelCancelled({ funnelInteractionId, funnelIdentifier: props.funnelIdentifier });\n }\n };\n }, [mounted]);\n /* eslint-enable react-hooks/exhaustive-deps */\n\n const funnelSubmit = () => {\n funnelState.current = 'validating';\n formSubmitStartTime.current = performance.now();\n /*\n When the user attempts to submit the form, we wait for 50 milliseconds before checking\n if any form validation errors are present. This value was chosen to give enough time\n for validation and rerendering to occur, but be low enough that the user will not\n be able to take further action in the meantime.\n */\n const VALIDATION_WAIT_DELAY = 50;\n /*\n Loading is expected to take longer than validation, so we can keep the pressure on the CPU low.\n */\n const LOADING_WAIT_DELAY = 100;\n\n const checkForCompleteness = () => {\n if (funnelState.current === 'complete') {\n return;\n }\n\n if (loadingButtonCount.current > 0) {\n setTimeout(checkForCompleteness, LOADING_WAIT_DELAY);\n return;\n }\n\n if (errorCount.current === 0) {\n /*\n If no validation errors are rendered, we treat the funnel as complete.\n */\n const taskCompletionDataProps: TaskCompletionDataProps = {\n taskIdentifier: props.funnelIdentifier,\n taskType: props.funnelType,\n timeToRespondAfterFormSubmit: performance.now() - formSubmitStartTime.current,\n taskInteractionId: funnelInteractionId,\n taskFlowType: props.funnelFlowType,\n };\n onFunnelComplete(taskCompletionDataProps);\n funnelState.current = 'complete';\n } else {\n funnelState.current = 'default';\n }\n };\n setTimeout(checkForCompleteness, VALIDATION_WAIT_DELAY);\n };\n\n const funnelNextOrSubmitAttempt = () => setSubmissionAttempt(i => i + 1);\n\n const funnelCancel = () => {};\n\n const funnelContextValue: FunnelContextValue = {\n funnelInteractionId,\n funnelIdentifier: props.funnelIdentifier,\n funnelFlowType: props.funnelFlowType,\n funnelErrorContext: props.funnelErrorContext,\n setFunnelInteractionId,\n funnelType: props.funnelType,\n optionalStepNumbers: props.optionalStepNumbers,\n totalFunnelSteps: props.totalFunnelSteps,\n funnelNameSelector: funnelNameSelector.current,\n funnelSubmit,\n funnelCancel,\n submissionAttempt,\n funnelNextOrSubmitAttempt,\n funnelState,\n errorCount,\n loadingButtonCount,\n latestFocusCleanupFunction,\n isInFunnel: true,\n wizardCount,\n };\n\n return <FunnelContext.Provider value={funnelContextValue}>{children}</FunnelContext.Provider>;\n};\n\ninterface AnalyticsFunnelStepProps {\n mounted?: boolean;\n stepIdentifier?: AnalyticsMetadata['instanceIdentifier'];\n stepErrorContext?: AnalyticsMetadata['errorContext'];\n children?: React.ReactNode | ((props: FunnelStepContextValue) => React.ReactNode);\n stepNameSelector?: FunnelStepProps['stepNameSelector'];\n stepNumber: FunnelStepProps['stepNumber'];\n}\n\nexport const AnalyticsFunnelStep = (props: AnalyticsFunnelStepProps) => {\n /*\n This wrapper is used to apply a `key` property to the actual (inner) AnalyticsFunnelStep\n element. This allows us to keep the state and effects separate per step.\n */\n return <InnerAnalyticsFunnelStep {...props} key={props.stepNumber} />;\n};\n\nfunction getSubStepConfiguration(): SubStepConfiguration[] {\n const subSteps = Array.from(document.querySelectorAll<HTMLElement>(getSubStepAllSelector()));\n\n const subStepConfiguration = subSteps.map((substep, index) => {\n const subStepIdentifier = (substep as any)?.__awsuiMetadata__?.analytics?.instanceIdentifier;\n const name = substep.querySelector<HTMLElement>(getSubStepNameSelector())?.innerText?.trim() ?? '';\n\n return {\n name,\n number: index + 1,\n subStepIdentifier,\n };\n });\n return subStepConfiguration;\n}\n\nfunction useStepChangeListener(stepNumber: number, handler: (stepConfiguration: SubStepConfiguration[]) => void) {\n const subStepConfiguration = useRef(new Map<number, SubStepConfiguration[] | undefined>());\n /*\n Chosen so that it's hopefully shorter than a user interaction, but gives enough time for the\n amount of containers to stabilise.\n */\n const SUBSTEP_CHANGE_DEBOUNCE = 50;\n\n const listenForSubStepChanges = useRef(false);\n useEffect(() => {\n // We prevent emitting the event on the first render.\n const handle = setTimeout(() => (listenForSubStepChanges.current = true), SUBSTEP_CHANGE_DEBOUNCE);\n\n return () => {\n clearTimeout(handle);\n listenForSubStepChanges.current = false;\n };\n }, []);\n\n useEffect(() => {\n const handle = setTimeout(\n () => subStepConfiguration.current.set(stepNumber, getSubStepConfiguration()),\n SUBSTEP_CHANGE_DEBOUNCE\n );\n return () => {\n clearTimeout(handle);\n };\n }, [stepNumber]);\n\n /* We debounce this handler, so that multiple containers can change at once without causing\n too many events. */\n const stepChangeCallback = useDebounceCallback(() => {\n // We don't want to emit the event after the component has been unmounted.\n if (!listenForSubStepChanges.current) {\n return;\n }\n\n subStepConfiguration.current.set(stepNumber, getSubStepConfiguration());\n handler(subStepConfiguration.current.get(stepNumber)!);\n }, SUBSTEP_CHANGE_DEBOUNCE);\n\n return { onStepChange: stepChangeCallback, subStepConfiguration };\n}\n\nconst InnerAnalyticsFunnelStep = ({\n mounted = true,\n children,\n stepNumber,\n stepIdentifier,\n stepErrorContext,\n ...rest\n}: AnalyticsFunnelStepProps) => {\n const { funnelInteractionId, funnelIdentifier, funnelNameSelector, funnelState, funnelType } = useFunnel();\n const parentStep = useFunnelStep();\n const parentStepExists = parentStep.isInStep;\n const parentStepFunnelInteractionId = parentStep.funnelInteractionId;\n\n const funnelStepProps = { [DATA_ATTR_FUNNEL_STEP]: stepNumber };\n\n const subStepCount = useRef<number>(0);\n\n const stepNameSelector = rest.stepNameSelector || funnelNameSelector;\n const { onStepChange, subStepConfiguration } = useStepChangeListener(stepNumber, subStepConfiguration => {\n if (!funnelInteractionId) {\n return;\n }\n\n FunnelMetrics.funnelStepChange({\n stepIdentifier,\n funnelIdentifier,\n funnelInteractionId,\n stepNumber,\n stepNameSelector,\n subStepAllSelector: getSubStepAllSelector(),\n totalSubSteps: subStepCount.current,\n subStepConfiguration,\n });\n });\n\n useEffect(() => {\n if (!funnelInteractionId) {\n // This step is not inside an active funnel.\n return;\n }\n\n if (mounted) {\n return;\n }\n\n const stepName = getTextFromSelector(stepNameSelector);\n const handler = setTimeout(() => {\n if (funnelState.current !== 'cancelled') {\n FunnelMetrics.funnelStepComplete({\n funnelIdentifier,\n funnelInteractionId,\n stepIdentifier,\n stepNumber,\n stepName,\n stepNameSelector,\n subStepAllSelector: getSubStepAllSelector(),\n totalSubSteps: subStepCount.current,\n });\n }\n }, 0);\n\n return () => {\n clearTimeout(handler);\n };\n }, [\n stepIdentifier,\n funnelIdentifier,\n funnelInteractionId,\n stepNumber,\n stepNameSelector,\n funnelState,\n parentStepExists,\n funnelType,\n parentStepFunnelInteractionId,\n mounted,\n ]);\n\n // This useEffect hook is used to track the start and completion of interaction with the step.\n // On mount, if there is a valid funnel interaction id, it calls the 'funnelStepStart' method from FunnelMetrics\n // to record the beginning of the interaction with the current step.\n // On unmount, it does a similar thing but this time calling 'funnelStepComplete' to record the completion of the interaction.\n useEffect(() => {\n if (!funnelInteractionId) {\n // This step is not inside an active funnel.\n return;\n }\n\n if (parentStepExists && parentStepFunnelInteractionId) {\n /*\n This step is inside another step, which already reports events as\n part of an active funnel (i.e. that step is not a parent of a Wizard).\n Thus, this current step does not need to report any events.\n */\n return;\n }\n\n const stepName = getTextFromSelector(stepNameSelector);\n\n if (funnelState.current === 'default') {\n FunnelMetrics.funnelStepStart({\n stepIdentifier,\n funnelIdentifier,\n funnelInteractionId,\n stepNumber,\n stepName,\n stepNameSelector,\n subStepAllSelector: getSubStepAllSelector(),\n totalSubSteps: subStepCount.current,\n subStepConfiguration: getSubStepConfiguration(),\n });\n }\n\n return () => {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n if (funnelState.current !== 'cancelled') {\n FunnelMetrics.funnelStepComplete({\n funnelIdentifier,\n funnelInteractionId,\n stepIdentifier,\n stepNumber,\n stepName,\n stepNameSelector,\n subStepAllSelector: getSubStepAllSelector(),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n totalSubSteps: subStepCount.current,\n });\n }\n };\n }, [\n stepIdentifier,\n funnelIdentifier,\n funnelInteractionId,\n stepNumber,\n stepNameSelector,\n funnelState,\n parentStepExists,\n funnelType,\n parentStepFunnelInteractionId,\n ]);\n\n const contextValue: FunnelStepContextValue = {\n stepIdentifier,\n stepNumber,\n stepNameSelector,\n funnelStepProps,\n subStepCount,\n isInStep: true,\n funnelInteractionId,\n onStepChange,\n subStepConfiguration,\n stepErrorContext,\n };\n\n /*\n If this step is inside another step which already reports events as part of an active\n funnel (i.e. that step is not a parent of a Wizard), the current step becomes invisible\n in the hierarchy by passing the context of its parent through.\n */\n const effectiveContextValue = parentStepExists && parentStepFunnelInteractionId ? parentStep : contextValue;\n\n return (\n <FunnelStepContext.Provider value={effectiveContextValue}>\n {typeof children === 'function' ? children(effectiveContextValue) : children}\n </FunnelStepContext.Provider>\n );\n};\ninterface AnalyticsFunnelSubStepProps {\n subStepIdentifier?: AnalyticsMetadata['instanceIdentifier'];\n subStepErrorContext?: AnalyticsMetadata['errorContext'];\n children?: React.ReactNode | ((props: FunnelSubStepContextValue) => React.ReactNode);\n}\n\nexport const AnalyticsFunnelSubStep = ({\n children,\n subStepIdentifier,\n subStepErrorContext,\n}: AnalyticsFunnelSubStepProps) => {\n const subStepId = useUniqueId('substep');\n const subStepSelector = getSubStepSelector(subStepId);\n const subStepNameSelector = getSubStepNameSelector(subStepId);\n const subStepRef = useRef<HTMLDivElement | null>(null);\n const { subStepCount, onStepChange } = useFunnelStep();\n const mousePressed = useRef<boolean>(false);\n const isFocusedSubStep = useRef<boolean>(false);\n const focusCleanupFunction = useRef<undefined | (() => void)>(undefined);\n const { funnelState, funnelInteractionId } = useFunnel();\n const { stepNumber, stepNameSelector } = useFunnelStep();\n\n const newContext: FunnelSubStepContextValue = {\n subStepIdentifier,\n subStepErrorContext,\n subStepSelector,\n subStepNameSelector,\n subStepId,\n subStepRef,\n mousePressed,\n isFocusedSubStep,\n focusCleanupFunction,\n isNestedSubStep: false,\n };\n\n const inheritedContext = { ...useContext(FunnelSubStepContext), isNestedSubStep: true };\n\n const isNested = Boolean(inheritedContext.subStepId);\n\n useEffect(() => {\n if (!isNested) {\n subStepCount.current++;\n onStepChange();\n\n return () => {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n subStepCount.current--;\n onStepChange();\n };\n }\n }, [isNested, subStepCount, onStepChange]);\n\n const context = isNested ? inheritedContext : newContext;\n\n useEffect(() => {\n if (isNested || !subStepRef.current) {\n return;\n }\n\n const onMouseDown = () => (mousePressed.current = true);\n\n const onMouseUp = async () => {\n mousePressed.current = false;\n\n if (!isFocusedSubStep.current) {\n return;\n }\n\n /*\n Some mouse events result in an element being focused. However,\n this happens only _after_ the onMouseUp event. We yield the\n event loop here, so that `document.activeElement` has the\n correct new value.\n */\n await new Promise(r => setTimeout(r, 1));\n\n if (!subStepRef.current || !document.activeElement || !nodeBelongs(subStepRef.current, document.activeElement)) {\n isFocusedSubStep.current = false;\n\n /*\n Run this substep's own focus cleanup function if another substep\n hasn't already done it for us.\n */\n focusCleanupFunction.current?.();\n }\n };\n window.addEventListener('mousedown', onMouseDown);\n window.addEventListener('mouseup', onMouseUp);\n return () => {\n window.removeEventListener('mousedown', onMouseDown);\n window.removeEventListener('mouseup', onMouseUp);\n };\n }, [\n funnelInteractionId,\n funnelState,\n stepNameSelector,\n stepNumber,\n subStepNameSelector,\n subStepSelector,\n focusCleanupFunction,\n isNested,\n subStepRef,\n ]);\n\n return (\n <FunnelSubStepContext.Provider value={context}>\n {typeof children === 'function' ? children(context) : children}\n </FunnelSubStepContext.Provider>\n );\n};\n"]}
1
+ {"version":3,"file":"analytics-funnel.js","sourceRoot":"","sources":["../../../../../src/internal/analytics/components/analytics-funnel.tsx"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport React, { useContext, useEffect, useRef, useState } from 'react';\n\nimport { PACKAGE_VERSION } from '../../environment';\nimport { useDebounceCallback } from '../../hooks/use-debounce-callback';\nimport { useUniqueId } from '../../hooks/use-unique-id';\nimport { useVisualRefresh } from '../../hooks/use-visual-mode';\nimport { nodeBelongs } from '../../utils/node-belongs';\nimport {\n FunnelContext,\n FunnelContextValue,\n FunnelState,\n FunnelStepContext,\n FunnelStepContextValue,\n FunnelSubStepContext,\n FunnelSubStepContextValue,\n} from '../context/analytics-context';\nimport { useFunnel, useFunnelStep } from '../hooks/use-funnel';\nimport { FunnelMetrics, PerformanceMetrics } from '../index';\nimport {\n AnalyticsMetadata,\n FunnelStartProps,\n FunnelStepProps,\n StepConfiguration,\n SubStepConfiguration,\n TaskCompletionDataProps,\n} from '../interfaces';\nimport {\n DATA_ATTR_FUNNEL_STEP,\n DATA_ATTR_RESOURCE_TYPE,\n getFunnelNameSelector,\n getSubStepAllSelector,\n getSubStepNameSelector,\n getSubStepSelector,\n getTextFromSelector,\n} from '../selectors';\n\nconst FUNNEL_VERSION = '1.4';\n\ninterface AnalyticsFunnelProps {\n mounted?: boolean;\n children?: React.ReactNode;\n stepConfiguration?: StepConfiguration[];\n funnelNameSelectors?: () => string[];\n funnelType: FunnelStartProps['funnelType'];\n optionalStepNumbers: FunnelStartProps['optionalStepNumbers'];\n totalFunnelSteps: FunnelStartProps['totalFunnelSteps'];\n funnelIdentifier?: AnalyticsMetadata['instanceIdentifier'];\n funnelFlowType?: AnalyticsMetadata['flowType'];\n funnelErrorContext?: AnalyticsMetadata['errorContext'];\n funnelResourceType?: AnalyticsMetadata['resourceType'];\n}\n\nexport const AnalyticsFunnel = (props: AnalyticsFunnelProps) => {\n const { isInFunnel } = useFunnel();\n /*\n If the current funnel component is a Form (i.e. single-page funnel), it should\n defer its funnel-handling to a parent Form element, if present.\n Wizards (i.e. multi-page funnels) always take highest precedence for handling funnels,\n and do not defer to any other element.\n */\n if (isInFunnel && props.funnelType === 'single-page') {\n return <>{props.children}</>;\n }\n\n return <InnerAnalyticsFunnel {...props} />;\n};\n\nexport const CREATION_EDIT_FLOW_DONE_EVENT_NAME = 'awsui-creation-edit-flow-done';\nconst dispatchCreateEditFlowDoneEvent = () => {\n try {\n window.top?.document.dispatchEvent(new Event(CREATION_EDIT_FLOW_DONE_EVENT_NAME));\n } catch {\n // probably because of cross-origin error, then do not dispatch the event\n }\n};\n\nconst onFunnelCancelled = ({\n funnelInteractionId,\n funnelIdentifier,\n}: {\n funnelInteractionId: string;\n funnelIdentifier?: string;\n}) => {\n FunnelMetrics.funnelCancelled({ funnelInteractionId, funnelIdentifier });\n};\n\nconst onFunnelComplete = (taskCompletionDataProps: TaskCompletionDataProps) => {\n FunnelMetrics.funnelComplete({\n funnelInteractionId: taskCompletionDataProps.taskInteractionId,\n funnelIdentifier: taskCompletionDataProps.taskIdentifier,\n });\n PerformanceMetrics.taskCompletionData(taskCompletionDataProps);\n dispatchCreateEditFlowDoneEvent();\n};\n\nfunction evaluateSelectors(selectors: string[], defaultSelector: string) {\n for (const selector of selectors) {\n const element = document.querySelector(selector);\n if (element) {\n return selector;\n }\n }\n\n return defaultSelector;\n}\n\nconst InnerAnalyticsFunnel = ({ mounted = true, children, stepConfiguration, ...props }: AnalyticsFunnelProps) => {\n const [funnelInteractionId, setFunnelInteractionId] = useState<string>('');\n const [submissionAttempt, setSubmissionAttempt] = useState(0);\n const isVisualRefresh = useVisualRefresh();\n const funnelState = useRef<FunnelState>('default');\n const funnelNameSelector = useRef<string>(getFunnelNameSelector());\n const errorCount = useRef<number>(0);\n const loadingButtonCount = useRef<number>(0);\n const wizardCount = useRef<number>(0);\n const latestFocusCleanupFunction = useRef<undefined | (() => void)>(undefined);\n const formSubmitStartTime = useRef<number>(0);\n // This useEffect hook is run once on component mount to initiate the funnel analytics.\n // It first calls the 'funnelStart' method from FunnelMetrics, providing all necessary details\n // about the funnel, and receives a unique interaction id.\n // This unique interaction id is then stored in the state for further use.\n //\n // On component unmount, it checks whether the funnel was successfully completed.\n // Based on this, it either calls 'funnelComplete' or 'funnelCancelled' method from FunnelMetrics.\n //\n // The eslint-disable is required as we deliberately want this effect to run only once on mount and unmount,\n // hence we do not provide any dependencies.\n useEffect(() => {\n if (!mounted) {\n return;\n }\n\n /*\n We run this effect with a delay, in order to detect whether this funnel contains a Wizard.\n If it does contain a Wizard, that Wizard should take precedence for handling the funnel, and\n this current funnel component should do nothing.\n */\n let funnelInteractionId: string;\n const handle = setTimeout(() => {\n funnelNameSelector.current = evaluateSelectors(props.funnelNameSelectors?.() || [], getFunnelNameSelector());\n if (props.funnelType === 'single-page' && wizardCount.current > 0) {\n return;\n }\n\n // Reset the state, in case the component was re-mounted.\n funnelState.current = 'default';\n const funnelName = getTextFromSelector(funnelNameSelector.current) ?? '';\n\n const singleStepFlowStepConfiguration = [\n {\n number: 1,\n isOptional: false,\n name: funnelName,\n stepIdentifier: props.funnelIdentifier,\n },\n ];\n\n funnelInteractionId = FunnelMetrics.funnelStart({\n funnelName,\n funnelIdentifier: props.funnelIdentifier,\n flowType: props.funnelFlowType,\n funnelNameSelector: funnelNameSelector.current,\n optionalStepNumbers: props.optionalStepNumbers,\n funnelType: props.funnelType,\n totalFunnelSteps: props.totalFunnelSteps,\n componentVersion: PACKAGE_VERSION,\n componentTheme: isVisualRefresh ? 'vr' : 'classic',\n funnelVersion: FUNNEL_VERSION,\n stepConfiguration: stepConfiguration ?? singleStepFlowStepConfiguration,\n resourceType: props.funnelResourceType || getTextFromSelector(`[${DATA_ATTR_RESOURCE_TYPE}]`),\n });\n\n setFunnelInteractionId(funnelInteractionId);\n }, 1);\n\n /*\n A funnel counts as \"successful\" if it is unmounted after being \"complete\".\n */\n /* eslint-disable react-hooks/exhaustive-deps */\n return () => {\n clearTimeout(handle);\n if (props.funnelType === 'single-page' && wizardCount.current > 0) {\n return;\n }\n\n if (funnelState.current === 'validating') {\n // Finish the validation phase early.\n const taskCompletionDataProps: TaskCompletionDataProps = {\n taskIdentifier: props.funnelIdentifier,\n taskType: props.funnelType,\n timeToRespondAfterFormSubmit: performance.now() - formSubmitStartTime.current,\n taskInteractionId: funnelInteractionId,\n taskFlowType: props.funnelFlowType,\n };\n onFunnelComplete(taskCompletionDataProps);\n funnelState.current = 'complete';\n }\n\n if (funnelState.current === 'complete') {\n FunnelMetrics.funnelSuccessful({ funnelInteractionId, funnelIdentifier: props.funnelIdentifier });\n } else {\n funnelState.current = 'cancelled';\n onFunnelCancelled({ funnelInteractionId, funnelIdentifier: props.funnelIdentifier });\n }\n };\n }, [mounted]);\n /* eslint-enable react-hooks/exhaustive-deps */\n\n const funnelSubmit = () => {\n funnelState.current = 'validating';\n formSubmitStartTime.current = performance.now();\n /*\n When the user attempts to submit the form, we wait for 50 milliseconds before checking\n if any form validation errors are present. This value was chosen to give enough time\n for validation and rerendering to occur, but be low enough that the user will not\n be able to take further action in the meantime.\n */\n const VALIDATION_WAIT_DELAY = 50;\n /*\n Loading is expected to take longer than validation, so we can keep the pressure on the CPU low.\n */\n const LOADING_WAIT_DELAY = 100;\n\n const checkForCompleteness = () => {\n if (funnelState.current === 'complete') {\n return;\n }\n\n if (loadingButtonCount.current > 0) {\n setTimeout(checkForCompleteness, LOADING_WAIT_DELAY);\n return;\n }\n\n if (errorCount.current === 0) {\n /*\n If no validation errors are rendered, we treat the funnel as complete.\n */\n const taskCompletionDataProps: TaskCompletionDataProps = {\n taskIdentifier: props.funnelIdentifier,\n taskType: props.funnelType,\n timeToRespondAfterFormSubmit: performance.now() - formSubmitStartTime.current,\n taskInteractionId: funnelInteractionId,\n taskFlowType: props.funnelFlowType,\n };\n onFunnelComplete(taskCompletionDataProps);\n funnelState.current = 'complete';\n } else {\n funnelState.current = 'default';\n }\n };\n setTimeout(checkForCompleteness, VALIDATION_WAIT_DELAY);\n };\n\n const funnelNextOrSubmitAttempt = () => setSubmissionAttempt(i => i + 1);\n\n const funnelCancel = () => {};\n\n const funnelContextValue: FunnelContextValue = {\n funnelInteractionId,\n funnelIdentifier: props.funnelIdentifier,\n funnelFlowType: props.funnelFlowType,\n funnelErrorContext: props.funnelErrorContext,\n setFunnelInteractionId,\n funnelType: props.funnelType,\n optionalStepNumbers: props.optionalStepNumbers,\n totalFunnelSteps: props.totalFunnelSteps,\n funnelNameSelector: funnelNameSelector.current,\n funnelSubmit,\n funnelCancel,\n submissionAttempt,\n funnelNextOrSubmitAttempt,\n funnelState,\n errorCount,\n loadingButtonCount,\n latestFocusCleanupFunction,\n isInFunnel: true,\n wizardCount,\n };\n\n return <FunnelContext.Provider value={funnelContextValue}>{children}</FunnelContext.Provider>;\n};\n\ninterface AnalyticsFunnelStepProps {\n mounted?: boolean;\n stepIdentifier?: AnalyticsMetadata['instanceIdentifier'];\n stepErrorContext?: AnalyticsMetadata['errorContext'];\n children?: React.ReactNode | ((props: FunnelStepContextValue) => React.ReactNode);\n stepNameSelector?: FunnelStepProps['stepNameSelector'];\n stepNumber: FunnelStepProps['stepNumber'];\n}\n\nexport const AnalyticsFunnelStep = (props: AnalyticsFunnelStepProps) => {\n /*\n This wrapper is used to apply a `key` property to the actual (inner) AnalyticsFunnelStep\n element. This allows us to keep the state and effects separate per step.\n */\n return <InnerAnalyticsFunnelStep {...props} key={props.stepNumber} />;\n};\n\nfunction getSubStepConfiguration(): SubStepConfiguration[] {\n const subSteps = Array.from(document.querySelectorAll<HTMLElement>(getSubStepAllSelector()));\n\n const subStepConfiguration = subSteps.map((substep, index) => {\n const subStepIdentifier = (substep as any)?.__awsuiMetadata__?.analytics?.instanceIdentifier;\n const name = substep.querySelector<HTMLElement>(getSubStepNameSelector())?.innerText?.trim() ?? '';\n\n return {\n name,\n number: index + 1,\n subStepIdentifier,\n };\n });\n return subStepConfiguration;\n}\n\nfunction useStepChangeListener(stepNumber: number, handler: (stepConfiguration: SubStepConfiguration[]) => void) {\n const subStepConfiguration = useRef(new Map<number, SubStepConfiguration[] | undefined>());\n /*\n Chosen so that it's hopefully shorter than a user interaction, but gives enough time for the\n amount of containers to stabilise.\n */\n const SUBSTEP_CHANGE_DEBOUNCE = 50;\n\n const listenForSubStepChanges = useRef(false);\n useEffect(() => {\n // We prevent emitting the event on the first render.\n const handle = setTimeout(() => (listenForSubStepChanges.current = true), SUBSTEP_CHANGE_DEBOUNCE);\n\n return () => {\n clearTimeout(handle);\n listenForSubStepChanges.current = false;\n };\n }, []);\n\n useEffect(() => {\n const handle = setTimeout(\n () => subStepConfiguration.current.set(stepNumber, getSubStepConfiguration()),\n SUBSTEP_CHANGE_DEBOUNCE\n );\n return () => {\n clearTimeout(handle);\n };\n }, [stepNumber]);\n\n /* We debounce this handler, so that multiple containers can change at once without causing\n too many events. */\n const stepChangeCallback = useDebounceCallback(() => {\n // We don't want to emit the event after the component has been unmounted.\n if (!listenForSubStepChanges.current) {\n return;\n }\n\n subStepConfiguration.current.set(stepNumber, getSubStepConfiguration());\n handler(subStepConfiguration.current.get(stepNumber)!);\n }, SUBSTEP_CHANGE_DEBOUNCE);\n\n return { onStepChange: stepChangeCallback, subStepConfiguration };\n}\n\nconst InnerAnalyticsFunnelStep = ({\n mounted = true,\n children,\n stepNumber,\n stepIdentifier,\n stepErrorContext,\n ...rest\n}: AnalyticsFunnelStepProps) => {\n const { funnelInteractionId, funnelIdentifier, funnelNameSelector, funnelState, funnelType } = useFunnel();\n const parentStep = useFunnelStep();\n const parentStepExists = parentStep.isInStep;\n const parentStepFunnelInteractionId = parentStep.funnelInteractionId;\n\n const funnelStepProps = { [DATA_ATTR_FUNNEL_STEP]: stepNumber };\n\n const subStepCount = useRef<number>(0);\n\n const stepNameSelector = rest.stepNameSelector || funnelNameSelector;\n const { onStepChange, subStepConfiguration } = useStepChangeListener(stepNumber, subStepConfiguration => {\n if (!funnelInteractionId) {\n return;\n }\n\n FunnelMetrics.funnelStepChange({\n stepIdentifier,\n funnelIdentifier,\n funnelInteractionId,\n stepNumber,\n stepNameSelector,\n subStepAllSelector: getSubStepAllSelector(),\n totalSubSteps: subStepCount.current,\n subStepConfiguration,\n });\n });\n\n useEffect(() => {\n if (!funnelInteractionId) {\n // This step is not inside an active funnel.\n return;\n }\n\n if (mounted) {\n return;\n }\n\n const stepName = getTextFromSelector(stepNameSelector);\n const handler = setTimeout(() => {\n if (funnelState.current !== 'cancelled') {\n FunnelMetrics.funnelStepComplete({\n funnelIdentifier,\n funnelInteractionId,\n stepIdentifier,\n stepNumber,\n stepName,\n stepNameSelector,\n subStepAllSelector: getSubStepAllSelector(),\n totalSubSteps: subStepCount.current,\n });\n }\n }, 0);\n\n return () => {\n clearTimeout(handler);\n };\n }, [\n stepIdentifier,\n funnelIdentifier,\n funnelInteractionId,\n stepNumber,\n stepNameSelector,\n funnelState,\n parentStepExists,\n funnelType,\n parentStepFunnelInteractionId,\n mounted,\n ]);\n\n // This useEffect hook is used to track the start and completion of interaction with the step.\n // On mount, if there is a valid funnel interaction id, it calls the 'funnelStepStart' method from FunnelMetrics\n // to record the beginning of the interaction with the current step.\n // On unmount, it does a similar thing but this time calling 'funnelStepComplete' to record the completion of the interaction.\n useEffect(() => {\n if (!funnelInteractionId) {\n // This step is not inside an active funnel.\n return;\n }\n\n if (parentStepExists && parentStepFunnelInteractionId) {\n /*\n This step is inside another step, which already reports events as\n part of an active funnel (i.e. that step is not a parent of a Wizard).\n Thus, this current step does not need to report any events.\n */\n return;\n }\n\n const stepName = getTextFromSelector(stepNameSelector);\n\n if (funnelState.current === 'default') {\n FunnelMetrics.funnelStepStart({\n stepIdentifier,\n funnelIdentifier,\n funnelInteractionId,\n stepNumber,\n stepName,\n stepNameSelector,\n subStepAllSelector: getSubStepAllSelector(),\n totalSubSteps: subStepCount.current,\n subStepConfiguration: getSubStepConfiguration(),\n });\n }\n\n return () => {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n if (funnelState.current !== 'cancelled') {\n FunnelMetrics.funnelStepComplete({\n funnelIdentifier,\n funnelInteractionId,\n stepIdentifier,\n stepNumber,\n stepName,\n stepNameSelector,\n subStepAllSelector: getSubStepAllSelector(),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n totalSubSteps: subStepCount.current,\n });\n }\n };\n }, [\n stepIdentifier,\n funnelIdentifier,\n funnelInteractionId,\n stepNumber,\n stepNameSelector,\n funnelState,\n parentStepExists,\n funnelType,\n parentStepFunnelInteractionId,\n ]);\n\n const contextValue: FunnelStepContextValue = {\n stepIdentifier,\n stepNumber,\n stepNameSelector,\n funnelStepProps,\n subStepCount,\n isInStep: true,\n funnelInteractionId,\n onStepChange,\n subStepConfiguration,\n stepErrorContext,\n };\n\n /*\n If this step is inside another step which already reports events as part of an active\n funnel (i.e. that step is not a parent of a Wizard), the current step becomes invisible\n in the hierarchy by passing the context of its parent through.\n */\n const effectiveContextValue = parentStepExists && parentStepFunnelInteractionId ? parentStep : contextValue;\n\n return (\n <FunnelStepContext.Provider value={effectiveContextValue}>\n {typeof children === 'function' ? children(effectiveContextValue) : children}\n </FunnelStepContext.Provider>\n );\n};\ninterface AnalyticsFunnelSubStepProps {\n subStepIdentifier?: AnalyticsMetadata['instanceIdentifier'];\n subStepErrorContext?: AnalyticsMetadata['errorContext'];\n children?: React.ReactNode | ((props: FunnelSubStepContextValue) => React.ReactNode);\n}\n\nexport const AnalyticsFunnelSubStep = ({\n children,\n subStepIdentifier,\n subStepErrorContext,\n}: AnalyticsFunnelSubStepProps) => {\n const subStepId = useUniqueId('substep');\n const subStepSelector = getSubStepSelector(subStepId);\n const subStepNameSelector = getSubStepNameSelector(subStepId);\n const subStepRef = useRef<HTMLDivElement | null>(null);\n const { subStepCount, onStepChange } = useFunnelStep();\n const mousePressed = useRef<boolean>(false);\n const isFocusedSubStep = useRef<boolean>(false);\n const focusCleanupFunction = useRef<undefined | (() => void)>(undefined);\n const { funnelState, funnelInteractionId } = useFunnel();\n const { stepNumber, stepNameSelector } = useFunnelStep();\n\n const newContext: FunnelSubStepContextValue = {\n subStepIdentifier,\n subStepErrorContext,\n subStepSelector,\n subStepNameSelector,\n subStepId,\n subStepRef,\n mousePressed,\n isFocusedSubStep,\n focusCleanupFunction,\n isNestedSubStep: false,\n };\n\n const inheritedContext = { ...useContext(FunnelSubStepContext), isNestedSubStep: true };\n\n const isNested = Boolean(inheritedContext.subStepId);\n\n useEffect(() => {\n if (!isNested) {\n subStepCount.current++;\n onStepChange();\n\n return () => {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n subStepCount.current--;\n onStepChange();\n };\n }\n }, [isNested, subStepCount, onStepChange]);\n\n const context = isNested ? inheritedContext : newContext;\n\n useEffect(() => {\n if (isNested || !subStepRef.current) {\n return;\n }\n\n const onMouseDown = () => (mousePressed.current = true);\n\n const onMouseUp = async () => {\n mousePressed.current = false;\n\n if (!isFocusedSubStep.current) {\n return;\n }\n\n /*\n Some mouse events result in an element being focused. However,\n this happens only _after_ the onMouseUp event. We yield the\n event loop here, so that `document.activeElement` has the\n correct new value.\n */\n await new Promise(r => setTimeout(r, 1));\n\n if (!subStepRef.current || !document.activeElement || !nodeBelongs(subStepRef.current, document.activeElement)) {\n isFocusedSubStep.current = false;\n\n /*\n Run this substep's own focus cleanup function if another substep\n hasn't already done it for us.\n */\n focusCleanupFunction.current?.();\n }\n };\n const controller = new AbortController();\n window.addEventListener('mousedown', onMouseDown, { signal: controller.signal });\n window.addEventListener('mouseup', onMouseUp, { signal: controller.signal });\n return () => {\n controller.abort();\n };\n }, [\n funnelInteractionId,\n funnelState,\n stepNameSelector,\n stepNumber,\n subStepNameSelector,\n subStepSelector,\n focusCleanupFunction,\n isNested,\n subStepRef,\n ]);\n\n return (\n <FunnelSubStepContext.Provider value={context}>\n {typeof children === 'function' ? children(context) : children}\n </FunnelSubStepContext.Provider>\n );\n};\n"]}
@@ -81,7 +81,7 @@ export function animate({ oldState, elements, onTransitionsEnd, newElementInitia
81
81
  if (event.target === element) {
82
82
  // Clean up remaining inline styles
83
83
  element.style.transitionProperty = '';
84
- element.removeEventListener('transitionstart', onTransitionEnd);
84
+ element.removeEventListener('transitionend', onTransitionEnd);
85
85
  if (onTransitionsEnd) {
86
86
  ongoingAnimations.delete(id);
87
87
  if (ongoingAnimations.size === 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"animate.js","sourceRoot":"","sources":["../../../src/internal/animate.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nexport function getDOMRects(elements: Record<string, HTMLElement | null>) {\n const rects: Record<string, DOMRect> = {};\n for (const id in elements) {\n const element = elements[id];\n if (element) {\n rects[id] = element.getBoundingClientRect();\n }\n }\n return rects;\n}\n\n/*\n Animate DOM elements based on the FLIP technique\n - https://aerotwist.com/blog/flip-your-animations/\n - https://css-tricks.com/animating-layouts-with-the-flip-technique/\n\n This can be useful when the initial dimensions or position of the element is not known,\n so the initial offset or scaling needs to be retrieved via JS.\n\n Caveat: this currently does not support elements having CSS transforms in the end state.\n These would be overridden in the animation instead of combined.\n */\nexport function animate({\n oldState,\n elements,\n onTransitionsEnd,\n newElementInitialState,\n}: {\n elements: Record<string, HTMLElement | null>;\n oldState: Record<string, DOMRect>;\n onTransitionsEnd?: () => void;\n newElementInitialState?: (newRect: DOMRect) => { scale?: number; y?: number };\n}) {\n // First, apply the transform that will make the elements \"look like\" in the start position\n for (const id in elements) {\n const element = elements[id];\n const oldRect = oldState[id];\n if (element) {\n const newRect = element.getBoundingClientRect();\n const noOpTransform = { scale: 1, x: 0, y: 0 };\n // Calculate initial position.\n // If the element didn't exist previously, use the newElementInitialState function if provided.\n // If not, default to no transitions (scale: 1, y: 0)\n const calculatedInverseTransform = oldRect\n ? {\n scale: oldRect.width / newRect.width,\n x: (oldRect.left + oldRect.right) / 2 - (newRect.left + newRect.right) / 2,\n y: (oldRect.top + oldRect.bottom) / 2 - (newRect.top + newRect.bottom) / 2,\n }\n : newElementInitialState\n ? newElementInitialState(newRect)\n : {};\n const inverseTransform = { ...noOpTransform, ...calculatedInverseTransform };\n // Apply this initial change, without animating\n element.style.transitionProperty = 'none';\n element.style.transform = `scale(${inverseTransform.scale}) translate(${inverseTransform.x}px, ${inverseTransform.y}px)`;\n if (!oldRect) {\n // If the element didn't exist, then fade it in\n // (besides any other possibly defined transitions based on `newElementInitialState`)\n element.style.opacity = '0';\n }\n }\n }\n\n // Animate from the initial state to the end state\n requestAnimationFrame(() => {\n const ongoingAnimations = new Set();\n for (const id in elements) {\n const element = elements[id];\n if (element) {\n const oldRect = oldState[id];\n if (oldRect) {\n // Animate from here on\n element.style.transitionProperty = `transform`;\n // Unset inline CSS transforms so that the final state is applied\n element.style.transform = '';\n } else {\n // If the element didn't exist previously, fade in as well\n element.style.transitionProperty = `transform, opacity`;\n element.style.transform = '';\n element.style.opacity = '';\n }\n const onTransitionStart = (event: TransitionEvent) => {\n if (event.target === element) {\n ongoingAnimations.add(id);\n element.removeEventListener('transitionstart', onTransitionStart);\n }\n };\n const onTransitionEnd = (event: TransitionEvent) => {\n if (event.target === element) {\n // Clean up remaining inline styles\n element.style.transitionProperty = '';\n element.removeEventListener('transitionstart', onTransitionEnd);\n if (onTransitionsEnd) {\n ongoingAnimations.delete(id);\n if (ongoingAnimations.size === 0) {\n onTransitionsEnd();\n }\n }\n }\n };\n element.addEventListener('transitionstart', onTransitionStart);\n element.addEventListener('transitionend', onTransitionEnd);\n }\n }\n });\n}\n"]}
1
+ {"version":3,"file":"animate.js","sourceRoot":"","sources":["../../../src/internal/animate.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nexport function getDOMRects(elements: Record<string, HTMLElement | null>) {\n const rects: Record<string, DOMRect> = {};\n for (const id in elements) {\n const element = elements[id];\n if (element) {\n rects[id] = element.getBoundingClientRect();\n }\n }\n return rects;\n}\n\n/*\n Animate DOM elements based on the FLIP technique\n - https://aerotwist.com/blog/flip-your-animations/\n - https://css-tricks.com/animating-layouts-with-the-flip-technique/\n\n This can be useful when the initial dimensions or position of the element is not known,\n so the initial offset or scaling needs to be retrieved via JS.\n\n Caveat: this currently does not support elements having CSS transforms in the end state.\n These would be overridden in the animation instead of combined.\n */\nexport function animate({\n oldState,\n elements,\n onTransitionsEnd,\n newElementInitialState,\n}: {\n elements: Record<string, HTMLElement | null>;\n oldState: Record<string, DOMRect>;\n onTransitionsEnd?: () => void;\n newElementInitialState?: (newRect: DOMRect) => { scale?: number; y?: number };\n}) {\n // First, apply the transform that will make the elements \"look like\" in the start position\n for (const id in elements) {\n const element = elements[id];\n const oldRect = oldState[id];\n if (element) {\n const newRect = element.getBoundingClientRect();\n const noOpTransform = { scale: 1, x: 0, y: 0 };\n // Calculate initial position.\n // If the element didn't exist previously, use the newElementInitialState function if provided.\n // If not, default to no transitions (scale: 1, y: 0)\n const calculatedInverseTransform = oldRect\n ? {\n scale: oldRect.width / newRect.width,\n x: (oldRect.left + oldRect.right) / 2 - (newRect.left + newRect.right) / 2,\n y: (oldRect.top + oldRect.bottom) / 2 - (newRect.top + newRect.bottom) / 2,\n }\n : newElementInitialState\n ? newElementInitialState(newRect)\n : {};\n const inverseTransform = { ...noOpTransform, ...calculatedInverseTransform };\n // Apply this initial change, without animating\n element.style.transitionProperty = 'none';\n element.style.transform = `scale(${inverseTransform.scale}) translate(${inverseTransform.x}px, ${inverseTransform.y}px)`;\n if (!oldRect) {\n // If the element didn't exist, then fade it in\n // (besides any other possibly defined transitions based on `newElementInitialState`)\n element.style.opacity = '0';\n }\n }\n }\n\n // Animate from the initial state to the end state\n requestAnimationFrame(() => {\n const ongoingAnimations = new Set();\n for (const id in elements) {\n const element = elements[id];\n if (element) {\n const oldRect = oldState[id];\n if (oldRect) {\n // Animate from here on\n element.style.transitionProperty = `transform`;\n // Unset inline CSS transforms so that the final state is applied\n element.style.transform = '';\n } else {\n // If the element didn't exist previously, fade in as well\n element.style.transitionProperty = `transform, opacity`;\n element.style.transform = '';\n element.style.opacity = '';\n }\n const onTransitionStart = (event: TransitionEvent) => {\n if (event.target === element) {\n ongoingAnimations.add(id);\n element.removeEventListener('transitionstart', onTransitionStart);\n }\n };\n const onTransitionEnd = (event: TransitionEvent) => {\n if (event.target === element) {\n // Clean up remaining inline styles\n element.style.transitionProperty = '';\n element.removeEventListener('transitionend', onTransitionEnd);\n if (onTransitionsEnd) {\n ongoingAnimations.delete(id);\n if (ongoingAnimations.size === 0) {\n onTransitionsEnd();\n }\n }\n }\n };\n element.addEventListener('transitionstart', onTransitionStart);\n element.addEventListener('transitionend', onTransitionEnd);\n }\n }\n });\n}\n"]}
@@ -16,11 +16,11 @@ function useFocusVisibleState() {
16
16
  setFocusVisible(true);
17
17
  }
18
18
  }
19
- document.addEventListener('mousedown', handleMousedown);
20
- document.addEventListener('keydown', handleKeydown);
19
+ const controller = new AbortController();
20
+ document.addEventListener('mousedown', handleMousedown, { signal: controller.signal });
21
+ document.addEventListener('keydown', handleKeydown, { signal: controller.signal });
21
22
  return () => {
22
- document.removeEventListener('mousedown', handleMousedown);
23
- document.removeEventListener('keydown', handleKeydown);
23
+ controller.abort();
24
24
  };
25
25
  });
26
26
  return focusVisible;
@@ -1 +1 @@
1
- {"version":3,"file":"focus-outline.js","sourceRoot":"","sources":["../../../../../src/internal/components/chart-plot/focus-outline.tsx"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport React, { useEffect, useRef, useState } from 'react';\n\nimport { isModifierKey } from '@cloudscape-design/component-toolkit/internal';\n\nimport { Offset } from '../interfaces';\n\nimport styles from './styles.css.js';\n\ninterface FocusOutlineProps {\n elementKey?: null | string | number | boolean;\n elementRef?: React.RefObject<SVGSVGElement | SVGGElement>;\n offset?: Offset;\n}\n\nfunction useFocusVisibleState() {\n const [focusVisible, setFocusVisible] = useState(false);\n useEffect(() => {\n function handleMousedown() {\n return setFocusVisible(false);\n }\n\n function handleKeydown(event: KeyboardEvent) {\n // we do not want to highlight focused element\n // when special keys are pressed\n if (!isModifierKey(event)) {\n setFocusVisible(true);\n }\n }\n\n document.addEventListener('mousedown', handleMousedown);\n document.addEventListener('keydown', handleKeydown);\n return () => {\n document.removeEventListener('mousedown', handleMousedown);\n document.removeEventListener('keydown', handleKeydown);\n };\n });\n\n return focusVisible;\n}\n\nexport default function FocusOutline({ elementKey, elementRef, offset = 0 }: FocusOutlineProps) {\n const ref = useRef<SVGRectElement>(null);\n const focusVisible = useFocusVisibleState();\n\n useEffect(() => {\n if (!ref.current) {\n return;\n }\n\n if (focusVisible && elementKey && elementRef && elementRef.current && elementRef.current.getBBox) {\n const element = elementRef.current.getBBox();\n showOutline(ref.current, element, offset);\n } else {\n hideOutline(ref.current);\n }\n }, [focusVisible, elementKey, elementRef, offset]);\n\n return <rect ref={ref} aria-hidden=\"true\" className={styles['focus-outline']} rx=\"2\" />;\n}\n\nfunction showOutline(\n el: SVGRectElement,\n position: { x: number; y: number; width: number; height: number },\n offset: Offset\n) {\n const offsetX = typeof offset === 'number' ? offset : offset.x;\n const offsetY = typeof offset === 'number' ? offset : offset.y;\n el.setAttribute('x', (position.x - offsetX).toString());\n el.setAttribute('y', (position.y - offsetY).toString());\n el.setAttribute('width', (position.width + 2 * offsetX).toString());\n el.setAttribute('height', (position.height + 2 * offsetY).toString());\n el.style.visibility = 'visible';\n}\n\nfunction hideOutline(el: SVGRectElement) {\n el.style.visibility = 'hidden';\n el.removeAttribute('x');\n el.removeAttribute('y');\n el.removeAttribute('width');\n el.removeAttribute('height');\n}\n"]}
1
+ {"version":3,"file":"focus-outline.js","sourceRoot":"","sources":["../../../../../src/internal/components/chart-plot/focus-outline.tsx"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport React, { useEffect, useRef, useState } from 'react';\n\nimport { isModifierKey } from '@cloudscape-design/component-toolkit/internal';\n\nimport { Offset } from '../interfaces';\n\nimport styles from './styles.css.js';\n\ninterface FocusOutlineProps {\n elementKey?: null | string | number | boolean;\n elementRef?: React.RefObject<SVGSVGElement | SVGGElement>;\n offset?: Offset;\n}\n\nfunction useFocusVisibleState() {\n const [focusVisible, setFocusVisible] = useState(false);\n useEffect(() => {\n function handleMousedown() {\n return setFocusVisible(false);\n }\n\n function handleKeydown(event: KeyboardEvent) {\n // we do not want to highlight focused element\n // when special keys are pressed\n if (!isModifierKey(event)) {\n setFocusVisible(true);\n }\n }\n\n const controller = new AbortController();\n document.addEventListener('mousedown', handleMousedown, { signal: controller.signal });\n document.addEventListener('keydown', handleKeydown, { signal: controller.signal });\n return () => {\n controller.abort();\n };\n });\n\n return focusVisible;\n}\n\nexport default function FocusOutline({ elementKey, elementRef, offset = 0 }: FocusOutlineProps) {\n const ref = useRef<SVGRectElement>(null);\n const focusVisible = useFocusVisibleState();\n\n useEffect(() => {\n if (!ref.current) {\n return;\n }\n\n if (focusVisible && elementKey && elementRef && elementRef.current && elementRef.current.getBBox) {\n const element = elementRef.current.getBBox();\n showOutline(ref.current, element, offset);\n } else {\n hideOutline(ref.current);\n }\n }, [focusVisible, elementKey, elementRef, offset]);\n\n return <rect ref={ref} aria-hidden=\"true\" className={styles['focus-outline']} rx=\"2\" />;\n}\n\nfunction showOutline(\n el: SVGRectElement,\n position: { x: number; y: number; width: number; height: number },\n offset: Offset\n) {\n const offsetX = typeof offset === 'number' ? offset : offset.x;\n const offsetY = typeof offset === 'number' ? offset : offset.y;\n el.setAttribute('x', (position.x - offsetX).toString());\n el.setAttribute('y', (position.y - offsetY).toString());\n el.setAttribute('width', (position.width + 2 * offsetX).toString());\n el.setAttribute('height', (position.height + 2 * offsetY).toString());\n el.style.visibility = 'visible';\n}\n\nfunction hideOutline(el: SVGRectElement) {\n el.style.visibility = 'hidden';\n el.removeAttribute('x');\n el.removeAttribute('y');\n el.removeAttribute('width');\n el.removeAttribute('height');\n}\n"]}