@salt-ds/core 1.44.1 → 1.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +55 -0
- package/css/salt-core.css +449 -11
- package/dist-cjs/accordion/Accordion.js.map +1 -1
- package/dist-cjs/accordion/AccordionContext.js.map +1 -1
- package/dist-cjs/accordion/AccordionHeader.js.map +1 -1
- package/dist-cjs/accordion/AccordionPanel.js.map +1 -1
- package/dist-cjs/aria-announcer/AriaAnnouncerContext.js.map +1 -1
- package/dist-cjs/aria-announcer/AriaAnnouncerProvider.js.map +1 -1
- package/dist-cjs/aria-announcer/useAriaAnnouncer.js +1 -9
- package/dist-cjs/aria-announcer/useAriaAnnouncer.js.map +1 -1
- package/dist-cjs/avatar/Avatar.js.map +1 -1
- package/dist-cjs/button/Button.js.map +1 -1
- package/dist-cjs/button/useButton.js.map +1 -1
- package/dist-cjs/checkbox/Checkbox.js.map +1 -1
- package/dist-cjs/checkbox/CheckboxGroup.js.map +1 -1
- package/dist-cjs/checkbox/internal/CheckboxGroupContext.js.map +1 -1
- package/dist-cjs/combo-box/ComboBox.js.map +1 -1
- package/dist-cjs/combo-box/useComboBox.js.map +1 -1
- package/dist-cjs/dialog/Dialog.js.map +1 -1
- package/dist-cjs/dialog/DialogContent.js.map +1 -1
- package/dist-cjs/dialog/DialogContext.js.map +1 -1
- package/dist-cjs/drawer/Drawer.js.map +1 -1
- package/dist-cjs/dropdown/Dropdown.js.map +1 -1
- package/dist-cjs/file-drop-zone/FileDropZone.js.map +1 -1
- package/dist-cjs/file-drop-zone/FileDropZoneTrigger.js.map +1 -1
- package/dist-cjs/file-drop-zone/internal/utils.js.map +1 -1
- package/dist-cjs/flex-layout/parseSpacing.js.map +1 -1
- package/dist-cjs/form-field/FormField.js.map +1 -1
- package/dist-cjs/form-field/FormFieldHelperText.js.map +1 -1
- package/dist-cjs/form-field/FormFieldLabel.js.map +1 -1
- package/dist-cjs/grid-layout/GridLayout.js.map +1 -1
- package/dist-cjs/index.js +4 -0
- package/dist-cjs/index.js.map +1 -1
- package/dist-cjs/input/Input.js.map +1 -1
- package/dist-cjs/interactable-card/InteractableCard.js.map +1 -1
- package/dist-cjs/interactable-card/InteractableCardGroup.js.map +1 -1
- package/dist-cjs/interactable-card/InteractableCardGroupContext.js.map +1 -1
- package/dist-cjs/interactable-card/useInteractableCard.js.map +1 -1
- package/dist-cjs/link/Link.js.map +1 -1
- package/dist-cjs/list-box/ListBox.js.map +1 -1
- package/dist-cjs/list-control/ListControlContext.js.map +1 -1
- package/dist-cjs/list-control/ListControlState.js.map +1 -1
- package/dist-cjs/menu/MenuBase.js.map +1 -1
- package/dist-cjs/menu/MenuContext.js.map +1 -1
- package/dist-cjs/menu/MenuGroup.js.map +1 -1
- package/dist-cjs/menu/MenuItem.js.map +1 -1
- package/dist-cjs/menu/MenuPanel.js.map +1 -1
- package/dist-cjs/menu/MenuPanelContext.js.map +1 -1
- package/dist-cjs/menu/MenuTrigger.js.map +1 -1
- package/dist-cjs/multiline-input/MultilineInput.js.map +1 -1
- package/dist-cjs/navigation-item/ExpansionIcon.js +1 -1
- package/dist-cjs/navigation-item/ExpansionIcon.js.map +1 -1
- package/dist-cjs/navigation-item/NavigationItem.js.map +1 -1
- package/dist-cjs/option/Option.js.map +1 -1
- package/dist-cjs/overlay/Overlay.js.map +1 -1
- package/dist-cjs/pagination/PageButton.js.map +1 -1
- package/dist-cjs/pagination/Pagination.js.map +1 -1
- package/dist-cjs/pagination/PaginationContext.js.map +1 -1
- package/dist-cjs/pagination/usePagination.js.map +1 -1
- package/dist-cjs/parent-child-layout/ParentChildLayout.js.map +1 -1
- package/dist-cjs/pill-input/PillInput.js.map +1 -1
- package/dist-cjs/progress/CircularProgress/CircularProgress.js.map +1 -1
- package/dist-cjs/progress/LinearProgress/LinearProgress.js.map +1 -1
- package/dist-cjs/radio-button/RadioButton.js.map +1 -1
- package/dist-cjs/radio-button/RadioButtonGroup.js.map +1 -1
- package/dist-cjs/radio-button/internal/RadioGroupContext.js.map +1 -1
- package/dist-cjs/salt-provider/SaltProvider.js.map +1 -1
- package/dist-cjs/skip-link/internal/useManageFocusOnTarget.js.map +1 -1
- package/dist-cjs/slider/RangeSlider.js.map +1 -1
- package/dist-cjs/slider/Slider.js.map +1 -1
- package/dist-cjs/slider/internal/SliderThumb.js.map +1 -1
- package/dist-cjs/slider/internal/SliderTrack.js.map +1 -1
- package/dist-cjs/slider/internal/useRangeSliderThumb.js.map +1 -1
- package/dist-cjs/slider/internal/useSliderThumb.js.map +1 -1
- package/dist-cjs/stack-layout/StackLayout.js.map +1 -1
- package/dist-cjs/stepper/Step.css.js +6 -0
- package/dist-cjs/stepper/Step.css.js.map +1 -0
- package/dist-cjs/stepper/Step.js +167 -0
- package/dist-cjs/stepper/Step.js.map +1 -0
- package/dist-cjs/stepper/Stepper.css.js +6 -0
- package/dist-cjs/stepper/Stepper.css.js.map +1 -0
- package/dist-cjs/stepper/Stepper.js +40 -0
- package/dist-cjs/stepper/Stepper.js.map +1 -0
- package/dist-cjs/stepper/internal/StepConnector.css.js +6 -0
- package/dist-cjs/stepper/internal/StepConnector.css.js.map +1 -0
- package/dist-cjs/stepper/internal/StepConnector.js +27 -0
- package/dist-cjs/stepper/internal/StepConnector.js.map +1 -0
- package/dist-cjs/stepper/internal/StepExpandTrigger.css.js +6 -0
- package/dist-cjs/stepper/internal/StepExpandTrigger.css.js.map +1 -0
- package/dist-cjs/stepper/internal/StepExpandTrigger.js +45 -0
- package/dist-cjs/stepper/internal/StepExpandTrigger.js.map +1 -0
- package/dist-cjs/stepper/internal/StepIcon.css.js +6 -0
- package/dist-cjs/stepper/internal/StepIcon.css.js.map +1 -0
- package/dist-cjs/stepper/internal/StepIcon.js +62 -0
- package/dist-cjs/stepper/internal/StepIcon.js.map +1 -0
- package/dist-cjs/stepper/internal/StepScreenReaderOnly.js +13 -0
- package/dist-cjs/stepper/internal/StepScreenReaderOnly.js.map +1 -0
- package/dist-cjs/stepper/internal/StepText.css.js +6 -0
- package/dist-cjs/stepper/internal/StepText.css.js.map +1 -0
- package/dist-cjs/stepper/internal/StepText.js +50 -0
- package/dist-cjs/stepper/internal/StepText.js.map +1 -0
- package/dist-cjs/stepper/internal/StepperProvider.js +19 -0
- package/dist-cjs/stepper/internal/StepperProvider.js.map +1 -0
- package/dist-cjs/switch/Switch.js.map +1 -1
- package/dist-cjs/toggle-button/ToggleButton.css.js +1 -1
- package/dist-cjs/toggle-button/ToggleButton.js +34 -20
- package/dist-cjs/toggle-button/ToggleButton.js.map +1 -1
- package/dist-cjs/toggle-button-group/ToggleButtonGroup.css.js +1 -1
- package/dist-cjs/toggle-button-group/ToggleButtonGroup.js +30 -6
- package/dist-cjs/toggle-button-group/ToggleButtonGroup.js.map +1 -1
- package/dist-cjs/toggle-button-group/ToggleButtonGroupContext.js.map +1 -1
- package/dist-cjs/tooltip/Tooltip.js.map +1 -1
- package/dist-cjs/tooltip/TooltipBase.js.map +1 -1
- package/dist-cjs/tooltip/useAriaAnnounce.js.map +1 -1
- package/dist-cjs/tooltip/useTooltip.js.map +1 -1
- package/dist-cjs/utils/mergeProps.js.map +1 -1
- package/dist-cjs/utils/useControlled.js.map +1 -1
- package/dist-cjs/utils/useFloatingUI/useFloatingUI.js.map +1 -1
- package/dist-cjs/utils/useId.js.map +1 -1
- package/dist-cjs/utils/usePreventScroll.js.map +1 -1
- package/dist-cjs/utils/useResizeObserver.js.map +1 -1
- package/dist-cjs/utils/useResponsiveProp.js.map +1 -1
- package/dist-es/accordion/Accordion.js.map +1 -1
- package/dist-es/accordion/AccordionContext.js.map +1 -1
- package/dist-es/accordion/AccordionHeader.js.map +1 -1
- package/dist-es/accordion/AccordionPanel.js.map +1 -1
- package/dist-es/aria-announcer/AriaAnnouncerContext.js.map +1 -1
- package/dist-es/aria-announcer/AriaAnnouncerProvider.js.map +1 -1
- package/dist-es/aria-announcer/useAriaAnnouncer.js +1 -9
- package/dist-es/aria-announcer/useAriaAnnouncer.js.map +1 -1
- package/dist-es/avatar/Avatar.js.map +1 -1
- package/dist-es/breakpoints/BreakpointProvider.js +1 -1
- package/dist-es/button/Button.js.map +1 -1
- package/dist-es/button/useButton.js.map +1 -1
- package/dist-es/checkbox/Checkbox.js.map +1 -1
- package/dist-es/checkbox/CheckboxGroup.js.map +1 -1
- package/dist-es/checkbox/internal/CheckboxGroupContext.js.map +1 -1
- package/dist-es/combo-box/ComboBox.js.map +1 -1
- package/dist-es/combo-box/useComboBox.js.map +1 -1
- package/dist-es/dialog/Dialog.js.map +1 -1
- package/dist-es/dialog/DialogContent.js.map +1 -1
- package/dist-es/dialog/DialogContext.js.map +1 -1
- package/dist-es/drawer/Drawer.js.map +1 -1
- package/dist-es/dropdown/Dropdown.js.map +1 -1
- package/dist-es/file-drop-zone/FileDropZone.js +1 -1
- package/dist-es/file-drop-zone/FileDropZone.js.map +1 -1
- package/dist-es/file-drop-zone/FileDropZoneTrigger.js.map +1 -1
- package/dist-es/file-drop-zone/internal/utils.js.map +1 -1
- package/dist-es/flex-layout/parseSpacing.js.map +1 -1
- package/dist-es/form-field/FormField.js.map +1 -1
- package/dist-es/form-field/FormFieldHelperText.js.map +1 -1
- package/dist-es/form-field/FormFieldLabel.js.map +1 -1
- package/dist-es/grid-layout/GridLayout.js.map +1 -1
- package/dist-es/index.js +2 -0
- package/dist-es/index.js.map +1 -1
- package/dist-es/input/Input.js.map +1 -1
- package/dist-es/interactable-card/InteractableCard.js.map +1 -1
- package/dist-es/interactable-card/InteractableCardGroup.js.map +1 -1
- package/dist-es/interactable-card/InteractableCardGroupContext.js.map +1 -1
- package/dist-es/interactable-card/useInteractableCard.js.map +1 -1
- package/dist-es/link/Link.js.map +1 -1
- package/dist-es/list-box/ListBox.js.map +1 -1
- package/dist-es/list-control/ListControlContext.js.map +1 -1
- package/dist-es/list-control/ListControlState.js.map +1 -1
- package/dist-es/menu/MenuBase.js +1 -1
- package/dist-es/menu/MenuBase.js.map +1 -1
- package/dist-es/menu/MenuContext.js.map +1 -1
- package/dist-es/menu/MenuGroup.js.map +1 -1
- package/dist-es/menu/MenuItem.js.map +1 -1
- package/dist-es/menu/MenuPanel.js.map +1 -1
- package/dist-es/menu/MenuPanelContext.js.map +1 -1
- package/dist-es/menu/MenuTrigger.js.map +1 -1
- package/dist-es/multiline-input/MultilineInput.js.map +1 -1
- package/dist-es/navigation-item/ExpansionIcon.js +1 -1
- package/dist-es/navigation-item/ExpansionIcon.js.map +1 -1
- package/dist-es/navigation-item/NavigationItem.js.map +1 -1
- package/dist-es/option/Option.js.map +1 -1
- package/dist-es/overlay/Overlay.js +1 -1
- package/dist-es/overlay/Overlay.js.map +1 -1
- package/dist-es/pagination/PageButton.js.map +1 -1
- package/dist-es/pagination/Pagination.js.map +1 -1
- package/dist-es/pagination/PaginationContext.js.map +1 -1
- package/dist-es/pagination/usePagination.js.map +1 -1
- package/dist-es/parent-child-layout/ParentChildLayout.js.map +1 -1
- package/dist-es/pill-input/PillInput.js.map +1 -1
- package/dist-es/progress/CircularProgress/CircularProgress.js.map +1 -1
- package/dist-es/progress/LinearProgress/LinearProgress.js.map +1 -1
- package/dist-es/radio-button/RadioButton.js.map +1 -1
- package/dist-es/radio-button/RadioButtonGroup.js.map +1 -1
- package/dist-es/radio-button/internal/RadioGroupContext.js.map +1 -1
- package/dist-es/salt-provider/SaltProvider.js.map +1 -1
- package/dist-es/semantic-icon-provider/SemanticIconProvider.js +1 -1
- package/dist-es/skip-link/internal/useManageFocusOnTarget.js.map +1 -1
- package/dist-es/slider/RangeSlider.js.map +1 -1
- package/dist-es/slider/Slider.js.map +1 -1
- package/dist-es/slider/internal/SliderThumb.js.map +1 -1
- package/dist-es/slider/internal/SliderTrack.js.map +1 -1
- package/dist-es/slider/internal/useRangeSliderThumb.js.map +1 -1
- package/dist-es/slider/internal/useSliderThumb.js.map +1 -1
- package/dist-es/stack-layout/StackLayout.js.map +1 -1
- package/dist-es/stepper/Step.css.js +4 -0
- package/dist-es/stepper/Step.css.js.map +1 -0
- package/dist-es/stepper/Step.js +165 -0
- package/dist-es/stepper/Step.js.map +1 -0
- package/dist-es/stepper/Stepper.css.js +4 -0
- package/dist-es/stepper/Stepper.css.js.map +1 -0
- package/dist-es/stepper/Stepper.js +38 -0
- package/dist-es/stepper/Stepper.js.map +1 -0
- package/dist-es/stepper/internal/StepConnector.css.js +4 -0
- package/dist-es/stepper/internal/StepConnector.css.js.map +1 -0
- package/dist-es/stepper/internal/StepConnector.js +25 -0
- package/dist-es/stepper/internal/StepConnector.js.map +1 -0
- package/dist-es/stepper/internal/StepExpandTrigger.css.js +4 -0
- package/dist-es/stepper/internal/StepExpandTrigger.css.js.map +1 -0
- package/dist-es/stepper/internal/StepExpandTrigger.js +43 -0
- package/dist-es/stepper/internal/StepExpandTrigger.js.map +1 -0
- package/dist-es/stepper/internal/StepIcon.css.js +4 -0
- package/dist-es/stepper/internal/StepIcon.css.js.map +1 -0
- package/dist-es/stepper/internal/StepIcon.js +60 -0
- package/dist-es/stepper/internal/StepIcon.js.map +1 -0
- package/dist-es/stepper/internal/StepScreenReaderOnly.js +11 -0
- package/dist-es/stepper/internal/StepScreenReaderOnly.js.map +1 -0
- package/dist-es/stepper/internal/StepText.css.js +4 -0
- package/dist-es/stepper/internal/StepText.css.js.map +1 -0
- package/dist-es/stepper/internal/StepText.js +48 -0
- package/dist-es/stepper/internal/StepText.js.map +1 -0
- package/dist-es/stepper/internal/StepperProvider.js +15 -0
- package/dist-es/stepper/internal/StepperProvider.js.map +1 -0
- package/dist-es/switch/Switch.js.map +1 -1
- package/dist-es/toggle-button/ToggleButton.css.js +1 -1
- package/dist-es/toggle-button/ToggleButton.js +34 -20
- package/dist-es/toggle-button/ToggleButton.js.map +1 -1
- package/dist-es/toggle-button-group/ToggleButtonGroup.css.js +1 -1
- package/dist-es/toggle-button-group/ToggleButtonGroup.js +30 -6
- package/dist-es/toggle-button-group/ToggleButtonGroup.js.map +1 -1
- package/dist-es/toggle-button-group/ToggleButtonGroupContext.js.map +1 -1
- package/dist-es/tooltip/Tooltip.js.map +1 -1
- package/dist-es/tooltip/TooltipBase.js.map +1 -1
- package/dist-es/tooltip/useAriaAnnounce.js.map +1 -1
- package/dist-es/tooltip/useTooltip.js +1 -1
- package/dist-es/tooltip/useTooltip.js.map +1 -1
- package/dist-es/utils/mergeProps.js.map +1 -1
- package/dist-es/utils/useControlled.js.map +1 -1
- package/dist-es/utils/useFloatingUI/useFloatingUI.js +2 -2
- package/dist-es/utils/useFloatingUI/useFloatingUI.js.map +1 -1
- package/dist-es/utils/useId.js.map +1 -1
- package/dist-es/utils/usePreventScroll.js.map +1 -1
- package/dist-es/utils/useResizeObserver.js.map +1 -1
- package/dist-es/utils/useResponsiveProp.js.map +1 -1
- package/dist-types/combo-box/ComboBox.d.ts +2 -2
- package/dist-types/form-field/FormFieldHelperText.d.ts +3 -1
- package/dist-types/index.d.ts +1 -0
- package/dist-types/stepper/Step.d.ts +46 -0
- package/dist-types/stepper/Stepper.d.ts +9 -0
- package/dist-types/stepper/index.d.ts +2 -0
- package/dist-types/stepper/internal/StepConnector.d.ts +1 -0
- package/dist-types/stepper/internal/StepExpandTrigger.d.ts +5 -0
- package/dist-types/stepper/internal/StepIcon.d.ts +8 -0
- package/dist-types/stepper/internal/StepScreenReaderOnly.d.ts +5 -0
- package/dist-types/stepper/internal/StepText.d.ts +5 -0
- package/dist-types/stepper/internal/StepperProvider.d.ts +9 -0
- package/dist-types/toggle-button/ToggleButton.d.ts +30 -1
- package/dist-types/toggle-button-group/ToggleButtonGroup.d.ts +16 -2
- package/dist-types/toggle-button-group/ToggleButtonGroupContext.d.ts +6 -2
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToggleButtonGroupContext.js","sources":["../src/toggle-button-group/ToggleButtonGroupContext.ts"],"sourcesContent":["import { type SyntheticEvent, useContext } from \"react\";\nimport { createContext } from \"../utils\";\n\nexport type Value = string | readonly string[] | number | undefined;\n\nexport interface ToggleButtonGroupContextValue {\n
|
|
1
|
+
{"version":3,"file":"ToggleButtonGroupContext.js","sources":["../src/toggle-button-group/ToggleButtonGroupContext.ts"],"sourcesContent":["import { type SyntheticEvent, useContext } from \"react\";\nimport type { ButtonAppearance, ButtonSentiment } from \"../button\";\nimport { createContext } from \"../utils\";\n\nexport type Value = string | readonly string[] | number | undefined;\n\nexport interface ToggleButtonGroupContextValue {\n appearance?: Extract<ButtonAppearance, \"bordered\" | \"solid\">;\n disabled?: boolean;\n focus: (id: Value) => void;\n isFocused: (id: Value) => boolean;\n isSelected: (id: Value) => boolean;\n orientation: \"horizontal\" | \"vertical\";\n readOnly?: boolean;\n select: (event: SyntheticEvent<HTMLButtonElement>) => void;\n sentiment?: ButtonSentiment;\n}\n\nexport const ToggleButtonGroupContext = createContext<\n ToggleButtonGroupContextValue | undefined\n>(\"ToggleButtonGroupContext\", undefined);\n\nexport function useToggleButtonGroup() {\n return useContext(ToggleButtonGroupContext);\n}\n"],"names":["createContext","useContext"],"mappings":";;;;;;;;;;;AAkBa,MAAA,wBAAA,GAA2BA,2BAEtC,CAAA,0BAAA,EAA4B,MAAS;AAEhC,SAAS,oBAAuB,GAAA;AACrC,EAAA,OAAOC,iBAAW,wBAAwB,CAAA;AAC5C;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip.js","sources":["../src/tooltip/Tooltip.tsx"],"sourcesContent":["import { clsx } from \"clsx\";\nimport {\n type HTMLAttributes,\n type ReactNode,\n cloneElement,\n forwardRef,\n isValidElement,\n} from \"react\";\n\nimport {\n VALIDATION_NAMED_STATUS,\n type ValidationStatus,\n} from \"../status-indicator\";\nimport {\n type UseFloatingUIProps,\n getRefFromChildren,\n makePrefixer,\n mergeProps,\n useFloatingComponent,\n useForkRef,\n} from \"../utils\";\n\nimport { useFormFieldProps } from \"../form-field-context\";\nimport { TooltipBase } from \"./TooltipBase\";\nimport { type UseTooltipProps, useTooltip } from \"./useTooltip\";\n\nconst withBaseName = makePrefixer(\"saltTooltip\");\n\nexport interface TooltipProps\n extends Pick<UseFloatingUIProps, \"open\" | \"onOpenChange\" | \"placement\">,\n Omit<HTMLAttributes<HTMLDivElement>, \"content\"> {\n /**\n * The children will be the Tooltip's trigger.\n */\n children: ReactNode;\n /**\n * Whether to hide the Tooltip arrow. Defaults to `false`.\n */\n hideArrow?: boolean;\n /**\n * Whether to hide the status icon within the Tooltip. Defaults to `false`.\n * If no status is provided, icon will also be hidden.\n */\n hideIcon?: boolean;\n /**\n * Content displayed inside the Tooltip. Can be a string or a React component.\n */\n content: ReactNode;\n /**\n * Optional string to determine the status of the Tooltip.\n */\n status?: ValidationStatus;\n /**\n * Delay in milliseconds before the Tooltip is shown.\n */\n enterDelay?: number;\n /**\n * Delay in milliseconds before the Tooltip is hidden. Defaults to 300ms.\n */\n leaveDelay?: number;\n /**\n * Option to not display the Tooltip. Can be used in conditional situations like text truncation. Defaults to 0.\n */\n disabled?: boolean;\n /**\n * Option to remove the hover listener.\n */\n disableHoverListener?: boolean;\n /**\n * Option to remove the focus listener.\n */\n disableFocusListener?: boolean;\n}\n\nexport const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(\n function Tooltip(props, ref) {\n const {\n children,\n className,\n disabled: disabledProp = false,\n hideArrow = false,\n hideIcon = false,\n open: openProp,\n content,\n status: statusProp,\n placement = \"right\",\n enterDelay = 300,\n leaveDelay = 0,\n ...rest\n } = props;\n\n const {\n disabled: formFieldDisabled,\n validationStatus: formFieldValidationStatus,\n } = useFormFieldProps();\n\n const disabled = disabledProp || formFieldDisabled;\n const status =\n statusProp ??\n (formFieldValidationStatus !== undefined &&\n VALIDATION_NAMED_STATUS.includes(formFieldValidationStatus)\n ? formFieldValidationStatus\n : undefined);\n const { Component: FloatingComponent } = useFloatingComponent();\n\n const hookProps: UseTooltipProps = {\n open: openProp,\n disabled,\n placement,\n enterDelay,\n leaveDelay,\n ...rest,\n };\n\n const {\n arrowProps,\n open,\n floating,\n reference,\n getTriggerProps,\n getTooltipProps,\n getTooltipPosition,\n } = useTooltip(hookProps);\n\n const triggerRef = useForkRef(getRefFromChildren(children), reference);\n\n const floatingRef = useForkRef<HTMLDivElement>(floating, ref);\n const hasContent = content !== undefined && content !== \"\";\n\n return (\n <>\n {isValidElement(children) &&\n cloneElement(children, {\n ...mergeProps(getTriggerProps(), children.props),\n ref: triggerRef,\n })}\n\n <FloatingComponent\n className={clsx(\n withBaseName(),\n { [withBaseName(status ?? \"\")]: status },\n className,\n )}\n open={open && !disabled && hasContent}\n {...getTooltipProps()}\n ref={floatingRef}\n {...getTooltipPosition()}\n >\n <TooltipBase\n hideIcon={hideIcon}\n status={status}\n content={content}\n hideArrow={hideArrow}\n arrowProps={arrowProps}\n />\n </FloatingComponent>\n </>\n );\n },\n);\n"],"names":["makePrefixer","forwardRef","Tooltip","useFormFieldProps","VALIDATION_NAMED_STATUS","useFloatingComponent","useTooltip","useForkRef","getRefFromChildren","jsxs","Fragment","isValidElement","cloneElement","mergeProps","jsx","clsx","TooltipBase"],"mappings":";;;;;;;;;;;;;;;;;;;;AA0BA,MAAM,YAAA,GAAeA,0BAAa,aAAa,CAAA;AAgDxC,MAAM,OAAU,GAAAC,gBAAA;AAAA,EACrB,SAASC,QAAQ,CAAA,KAAA,EAAO,GAAK,EAAA;AAC3B,IAAM,MAAA;AAAA,MACJ,QAAA;AAAA,MACA,SAAA;AAAA,MACA,UAAU,YAAe,GAAA,KAAA;AAAA,MACzB,SAAY,GAAA,KAAA;AAAA,MACZ,QAAW,GAAA,KAAA;AAAA,MACX,IAAM,EAAA,QAAA;AAAA,MACN,OAAA;AAAA,MACA,MAAQ,EAAA,UAAA;AAAA,MACR,SAAY,GAAA,OAAA;AAAA,MACZ,UAAa,GAAA,GAAA;AAAA,MACb,UAAa,GAAA,CAAA;AAAA,MACb,GAAG;AAAA,KACD,GAAA,KAAA;AAEJ,IAAM,MAAA;AAAA,MACJ,QAAU,EAAA,iBAAA;AAAA,MACV,gBAAkB,EAAA;AAAA,QAChBC,mCAAkB,EAAA;AAEtB,IAAA,MAAM,WAAW,YAAgB,IAAA,iBAAA;AACjC,IAAM,MAAA,MAAA,GACJ,eACC,yBAA8B,KAAA,
|
|
1
|
+
{"version":3,"file":"Tooltip.js","sources":["../src/tooltip/Tooltip.tsx"],"sourcesContent":["import { clsx } from \"clsx\";\nimport {\n type HTMLAttributes,\n type ReactNode,\n cloneElement,\n forwardRef,\n isValidElement,\n} from \"react\";\n\nimport {\n VALIDATION_NAMED_STATUS,\n type ValidationStatus,\n} from \"../status-indicator\";\nimport {\n type UseFloatingUIProps,\n getRefFromChildren,\n makePrefixer,\n mergeProps,\n useFloatingComponent,\n useForkRef,\n} from \"../utils\";\n\nimport { useFormFieldProps } from \"../form-field-context\";\nimport { TooltipBase } from \"./TooltipBase\";\nimport { type UseTooltipProps, useTooltip } from \"./useTooltip\";\n\nconst withBaseName = makePrefixer(\"saltTooltip\");\n\nexport interface TooltipProps\n extends Pick<UseFloatingUIProps, \"open\" | \"onOpenChange\" | \"placement\">,\n Omit<HTMLAttributes<HTMLDivElement>, \"content\"> {\n /**\n * The children will be the Tooltip's trigger.\n */\n children: ReactNode;\n /**\n * Whether to hide the Tooltip arrow. Defaults to `false`.\n */\n hideArrow?: boolean;\n /**\n * Whether to hide the status icon within the Tooltip. Defaults to `false`.\n * If no status is provided, icon will also be hidden.\n */\n hideIcon?: boolean;\n /**\n * Content displayed inside the Tooltip. Can be a string or a React component.\n */\n content: ReactNode;\n /**\n * Optional string to determine the status of the Tooltip.\n */\n status?: ValidationStatus;\n /**\n * Delay in milliseconds before the Tooltip is shown.\n */\n enterDelay?: number;\n /**\n * Delay in milliseconds before the Tooltip is hidden. Defaults to 300ms.\n */\n leaveDelay?: number;\n /**\n * Option to not display the Tooltip. Can be used in conditional situations like text truncation. Defaults to 0.\n */\n disabled?: boolean;\n /**\n * Option to remove the hover listener.\n */\n disableHoverListener?: boolean;\n /**\n * Option to remove the focus listener.\n */\n disableFocusListener?: boolean;\n}\n\nexport const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(\n function Tooltip(props, ref) {\n const {\n children,\n className,\n disabled: disabledProp = false,\n hideArrow = false,\n hideIcon = false,\n open: openProp,\n content,\n status: statusProp,\n placement = \"right\",\n enterDelay = 300,\n leaveDelay = 0,\n ...rest\n } = props;\n\n const {\n disabled: formFieldDisabled,\n validationStatus: formFieldValidationStatus,\n } = useFormFieldProps();\n\n const disabled = disabledProp || formFieldDisabled;\n const status =\n statusProp ??\n (formFieldValidationStatus !== undefined &&\n VALIDATION_NAMED_STATUS.includes(formFieldValidationStatus)\n ? formFieldValidationStatus\n : undefined);\n const { Component: FloatingComponent } = useFloatingComponent();\n\n const hookProps: UseTooltipProps = {\n open: openProp,\n disabled,\n placement,\n enterDelay,\n leaveDelay,\n ...rest,\n };\n\n const {\n arrowProps,\n open,\n floating,\n reference,\n getTriggerProps,\n getTooltipProps,\n getTooltipPosition,\n } = useTooltip(hookProps);\n\n const triggerRef = useForkRef(getRefFromChildren(children), reference);\n\n const floatingRef = useForkRef<HTMLDivElement>(floating, ref);\n const hasContent = content !== undefined && content !== \"\";\n\n return (\n <>\n {isValidElement(children) &&\n cloneElement(children, {\n ...mergeProps(getTriggerProps(), children.props),\n ref: triggerRef,\n })}\n\n <FloatingComponent\n className={clsx(\n withBaseName(),\n { [withBaseName(status ?? \"\")]: status },\n className,\n )}\n open={open && !disabled && hasContent}\n {...getTooltipProps()}\n ref={floatingRef}\n {...getTooltipPosition()}\n >\n <TooltipBase\n hideIcon={hideIcon}\n status={status}\n content={content}\n hideArrow={hideArrow}\n arrowProps={arrowProps}\n />\n </FloatingComponent>\n </>\n );\n },\n);\n"],"names":["makePrefixer","forwardRef","Tooltip","useFormFieldProps","VALIDATION_NAMED_STATUS","useFloatingComponent","useTooltip","useForkRef","getRefFromChildren","jsxs","Fragment","isValidElement","cloneElement","mergeProps","jsx","clsx","TooltipBase"],"mappings":";;;;;;;;;;;;;;;;;;;;AA0BA,MAAM,YAAA,GAAeA,0BAAa,aAAa,CAAA;AAgDxC,MAAM,OAAU,GAAAC,gBAAA;AAAA,EACrB,SAASC,QAAQ,CAAA,KAAA,EAAO,GAAK,EAAA;AAC3B,IAAM,MAAA;AAAA,MACJ,QAAA;AAAA,MACA,SAAA;AAAA,MACA,UAAU,YAAe,GAAA,KAAA;AAAA,MACzB,SAAY,GAAA,KAAA;AAAA,MACZ,QAAW,GAAA,KAAA;AAAA,MACX,IAAM,EAAA,QAAA;AAAA,MACN,OAAA;AAAA,MACA,MAAQ,EAAA,UAAA;AAAA,MACR,SAAY,GAAA,OAAA;AAAA,MACZ,UAAa,GAAA,GAAA;AAAA,MACb,UAAa,GAAA,CAAA;AAAA,MACb,GAAG;AAAA,KACD,GAAA,KAAA;AAEJ,IAAM,MAAA;AAAA,MACJ,QAAU,EAAA,iBAAA;AAAA,MACV,gBAAkB,EAAA;AAAA,QAChBC,mCAAkB,EAAA;AAEtB,IAAA,MAAM,WAAW,YAAgB,IAAA,iBAAA;AACjC,IAAM,MAAA,MAAA,GACJ,eACC,yBAA8B,KAAA,MAAA,IAC/BC,yCAAwB,QAAS,CAAA,yBAAyB,IACtD,yBACA,GAAA,MAAA,CAAA;AACN,IAAA,MAAM,EAAE,SAAA,EAAW,iBAAkB,EAAA,GAAIC,kCAAqB,EAAA;AAE9D,IAAA,MAAM,SAA6B,GAAA;AAAA,MACjC,IAAM,EAAA,QAAA;AAAA,MACN,QAAA;AAAA,MACA,SAAA;AAAA,MACA,UAAA;AAAA,MACA,UAAA;AAAA,MACA,GAAG;AAAA,KACL;AAEA,IAAM,MAAA;AAAA,MACJ,UAAA;AAAA,MACA,IAAA;AAAA,MACA,QAAA;AAAA,MACA,SAAA;AAAA,MACA,eAAA;AAAA,MACA,eAAA;AAAA,MACA;AAAA,KACF,GAAIC,sBAAW,SAAS,CAAA;AAExB,IAAA,MAAM,UAAa,GAAAC,qBAAA,CAAWC,qCAAmB,CAAA,QAAQ,GAAG,SAAS,CAAA;AAErE,IAAM,MAAA,WAAA,GAAcD,qBAA2B,CAAA,QAAA,EAAU,GAAG,CAAA;AAC5D,IAAM,MAAA,UAAA,GAAa,OAAY,KAAA,MAAA,IAAa,OAAY,KAAA,EAAA;AAExD,IAAA,uBAEKE,eAAA,CAAAC,mBAAA,EAAA,EAAA,QAAA,EAAA;AAAA,MAAeC,oBAAA,CAAA,QAAQ,CACtB,IAAAC,kBAAA,CAAa,QAAU,EAAA;AAAA,QACrB,GAAGC,qBAAA,CAAW,eAAgB,EAAA,EAAG,SAAS,KAAK,CAAA;AAAA,QAC/C,GAAK,EAAA;AAAA,OACN,CAAA;AAAA,sBAEHC,cAAA;AAAA,QAAC,iBAAA;AAAA,QAAA;AAAA,UACC,SAAW,EAAAC,SAAA;AAAA,YACT,YAAa,EAAA;AAAA,YACb,EAAE,CAAC,YAAA,CAAa,UAAU,EAAE,CAAC,GAAG,MAAO,EAAA;AAAA,YACvC;AAAA,WACF;AAAA,UACA,IAAA,EAAM,IAAQ,IAAA,CAAC,QAAY,IAAA,UAAA;AAAA,UAC1B,GAAG,eAAgB,EAAA;AAAA,UACpB,GAAK,EAAA,WAAA;AAAA,UACJ,GAAG,kBAAmB,EAAA;AAAA,UAEvB,QAAA,kBAAAD,cAAA;AAAA,YAACE,uBAAA;AAAA,YAAA;AAAA,cACC,QAAA;AAAA,cACA,MAAA;AAAA,cACA,OAAA;AAAA,cACA,SAAA;AAAA,cACA;AAAA;AAAA;AACF;AAAA;AACF,KACF,EAAA,CAAA;AAAA;AAGN;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TooltipBase.js","sources":["../src/tooltip/TooltipBase.tsx"],"sourcesContent":["import { FloatingArrow, type FloatingArrowProps } from \"@floating-ui/react\";\nimport { useFormFieldProps } from \"../form-field-context\";\nimport { StatusIndicator, type ValidationStatus } from \"../status-indicator\";\nimport { makePrefixer } from \"../utils\";\nimport type { TooltipProps } from \"./Tooltip\";\n\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport tooltipCss from \"./Tooltip.css\";\n\nconst withBaseName = makePrefixer(\"saltTooltip\");\n\ninterface TooltipBaseProps extends Omit<TooltipProps, \"children\"> {\n arrowProps: FloatingArrowProps;\n /**\n * Optional string to determine the status of the Tooltip.\n */\n status?: ValidationStatus;\n}\n\nexport const TooltipBase = (props: TooltipBaseProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-tooltip\",\n css: tooltipCss,\n window: targetWindow,\n });\n\n const { a11yProps } = useFormFieldProps();\n\n const { arrowProps, content, hideArrow, hideIcon, status } = props;\n\n return (\n <>\n <div className={withBaseName(\"container\")}>\n {!hideIcon && status && (\n <StatusIndicator\n status={status}\n size={1}\n className={withBaseName(\"icon\")}\n />\n )}\n <span\n id={a11yProps?.[\"aria-describedby\"]}\n className={withBaseName(\"content\")}\n >\n {content}\n </span>\n </div>\n {!hideArrow && (\n <FloatingArrow\n {...arrowProps}\n className={withBaseName(\"arrow\")}\n strokeWidth={1}\n fill=\"var(--salt-container-primary-background)\"\n stroke=\"var(--tooltip-status-borderColor)\"\n height={5}\n width={10}\n />\n )}\n </>\n );\n};\n"],"names":["makePrefixer","useWindow","useComponentCssInjection","tooltipCss","useFormFieldProps","jsxs","Fragment","jsx","StatusIndicator","FloatingArrow"],"mappings":";;;;;;;;;;;;;;;;;;AAUA,MAAM,YAAA,GAAeA,0BAAa,aAAa,CAAA;AAUlC,MAAA,WAAA,GAAc,CAAC,KAA4B,KAAA;AACtD,EAAA,MAAM,eAAeC,gBAAU,EAAA;AAC/B,EAAyBC,+BAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,cAAA;AAAA,IACR,GAAK,EAAAC,OAAA;AAAA,IACL,MAAQ,EAAA;AAAA,GACT,CAAA;AAED,EAAM,MAAA,EAAE,SAAU,EAAA,GAAIC,mCAAkB,EAAA;AAExC,EAAA,MAAM,EAAE,UAAY,EAAA,OAAA,EAAS,SAAW,EAAA,QAAA,EAAU,QAAW,GAAA,KAAA;AAE7D,EAAA,uBAEIC,eAAA,CAAAC,mBAAA,EAAA,EAAA,QAAA,EAAA;AAAA,oBAAAD,eAAA,CAAC,KAAI,EAAA,EAAA,SAAA,EAAW,YAAa,CAAA,WAAW,CACrC,EAAA,QAAA,EAAA;AAAA,MAAA,CAAC,YAAY,MACZ,oBAAAE,cAAA;AAAA,QAACC,+BAAA;AAAA,QAAA;AAAA,UACC,MAAA;AAAA,UACA,IAAM,EAAA,CAAA;AAAA,UACN,SAAA,EAAW,aAAa,MAAM;AAAA;AAAA,OAChC;AAAA,sBAEFD,cAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,IAAI,SAAY,IAAA,IAAA,GAAA,
|
|
1
|
+
{"version":3,"file":"TooltipBase.js","sources":["../src/tooltip/TooltipBase.tsx"],"sourcesContent":["import { FloatingArrow, type FloatingArrowProps } from \"@floating-ui/react\";\nimport { useFormFieldProps } from \"../form-field-context\";\nimport { StatusIndicator, type ValidationStatus } from \"../status-indicator\";\nimport { makePrefixer } from \"../utils\";\nimport type { TooltipProps } from \"./Tooltip\";\n\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport tooltipCss from \"./Tooltip.css\";\n\nconst withBaseName = makePrefixer(\"saltTooltip\");\n\ninterface TooltipBaseProps extends Omit<TooltipProps, \"children\"> {\n arrowProps: FloatingArrowProps;\n /**\n * Optional string to determine the status of the Tooltip.\n */\n status?: ValidationStatus;\n}\n\nexport const TooltipBase = (props: TooltipBaseProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-tooltip\",\n css: tooltipCss,\n window: targetWindow,\n });\n\n const { a11yProps } = useFormFieldProps();\n\n const { arrowProps, content, hideArrow, hideIcon, status } = props;\n\n return (\n <>\n <div className={withBaseName(\"container\")}>\n {!hideIcon && status && (\n <StatusIndicator\n status={status}\n size={1}\n className={withBaseName(\"icon\")}\n />\n )}\n <span\n id={a11yProps?.[\"aria-describedby\"]}\n className={withBaseName(\"content\")}\n >\n {content}\n </span>\n </div>\n {!hideArrow && (\n <FloatingArrow\n {...arrowProps}\n className={withBaseName(\"arrow\")}\n strokeWidth={1}\n fill=\"var(--salt-container-primary-background)\"\n stroke=\"var(--tooltip-status-borderColor)\"\n height={5}\n width={10}\n />\n )}\n </>\n );\n};\n"],"names":["makePrefixer","useWindow","useComponentCssInjection","tooltipCss","useFormFieldProps","jsxs","Fragment","jsx","StatusIndicator","FloatingArrow"],"mappings":";;;;;;;;;;;;;;;;;;AAUA,MAAM,YAAA,GAAeA,0BAAa,aAAa,CAAA;AAUlC,MAAA,WAAA,GAAc,CAAC,KAA4B,KAAA;AACtD,EAAA,MAAM,eAAeC,gBAAU,EAAA;AAC/B,EAAyBC,+BAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,cAAA;AAAA,IACR,GAAK,EAAAC,OAAA;AAAA,IACL,MAAQ,EAAA;AAAA,GACT,CAAA;AAED,EAAM,MAAA,EAAE,SAAU,EAAA,GAAIC,mCAAkB,EAAA;AAExC,EAAA,MAAM,EAAE,UAAY,EAAA,OAAA,EAAS,SAAW,EAAA,QAAA,EAAU,QAAW,GAAA,KAAA;AAE7D,EAAA,uBAEIC,eAAA,CAAAC,mBAAA,EAAA,EAAA,QAAA,EAAA;AAAA,oBAAAD,eAAA,CAAC,KAAI,EAAA,EAAA,SAAA,EAAW,YAAa,CAAA,WAAW,CACrC,EAAA,QAAA,EAAA;AAAA,MAAA,CAAC,YAAY,MACZ,oBAAAE,cAAA;AAAA,QAACC,+BAAA;AAAA,QAAA;AAAA,UACC,MAAA;AAAA,UACA,IAAM,EAAA,CAAA;AAAA,UACN,SAAA,EAAW,aAAa,MAAM;AAAA;AAAA,OAChC;AAAA,sBAEFD,cAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,IAAI,SAAY,IAAA,IAAA,GAAA,MAAA,GAAA,SAAA,CAAA,kBAAA,CAAA;AAAA,UAChB,SAAA,EAAW,aAAa,SAAS,CAAA;AAAA,UAEhC,QAAA,EAAA;AAAA;AAAA;AACH,KACF,EAAA,CAAA;AAAA,IACC,CAAC,SACA,oBAAAA,cAAA;AAAA,MAACE,mBAAA;AAAA,MAAA;AAAA,QACE,GAAG,UAAA;AAAA,QACJ,SAAA,EAAW,aAAa,OAAO,CAAA;AAAA,QAC/B,WAAa,EAAA,CAAA;AAAA,QACb,IAAK,EAAA,0CAAA;AAAA,QACL,MAAO,EAAA,mCAAA;AAAA,QACP,MAAQ,EAAA,CAAA;AAAA,QACR,KAAO,EAAA;AAAA;AAAA;AACT,GAEJ,EAAA,CAAA;AAEJ;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAriaAnnounce.js","sources":["../src/tooltip/useAriaAnnounce.ts"],"sourcesContent":["import type { ElementProps, FloatingContext } from \"@floating-ui/react\";\nimport { type PointerEvent, useEffect, useRef } from \"react\";\nimport { useAriaAnnouncer } from \"../aria-announcer\";\nimport { useIsomorphicLayoutEffect } from \"../utils\";\n\nfunction getDocument(floating: HTMLElement | null) {\n return floating?.ownerDocument ?? document;\n}\n\n// TODO: Check whether can be anything more restrictive than `any`\n// biome-ignore lint/suspicious/noExplicitAny: see comment above\nfunction getWindow(value: any) {\n return getDocument(value).defaultView ?? window;\n}\n\nfunction isElement(value: unknown): value is HTMLElement {\n return value ? value instanceof getWindow(value).Element : false;\n}\n\nfunction getDelay(\n value: Props[\"delay\"],\n prop: \"open\" | \"close\",\n pointerType?: PointerEvent[\"pointerType\"],\n) {\n if (pointerType && pointerType !== \"mouse\") {\n return 0;\n }\n\n if (typeof value === \"number\") {\n return value;\n }\n\n return value?.[prop];\n}\n\ntype Props = {\n delay?: number | Partial<{ open: number; close: number }>;\n};\n\nexport const useAriaAnnounce = (\n context: FloatingContext,\n { delay = 0 }: Props,\n): ElementProps => {\n const { open, dataRef, refs } = context;\n\n const pointerTypeRef = useRef<PointerEvent[\"pointerType\"]>();\n const timeoutRef = useRef<number>();\n const blockMouseMoveRef = useRef(true);\n const { announce } = useAriaAnnouncer();\n\n useIsomorphicLayoutEffect(() => {\n if (!open) {\n pointerTypeRef.current = undefined;\n }\n });\n\n useEffect(() => {\n const reference = refs.reference.current;\n function announceFloating() {\n const tooltipContent = refs.floating.current?.innerText;\n\n if (tooltipContent) {\n announce(tooltipContent);\n }\n }\n\n function onMouseEnter(event: MouseEvent) {\n clearTimeout(timeoutRef.current);\n\n if (open) {\n return;\n }\n\n blockMouseMoveRef.current = false;\n dataRef.current.openEvent = event;\n\n if (delay) {\n timeoutRef.current = window.setTimeout(\n () => {\n announceFloating();\n },\n getDelay(delay, \"open\", pointerTypeRef.current),\n );\n } else {\n announceFloating();\n }\n }\n\n if (isElement(reference)) {\n reference.addEventListener(\"mouseenter\", onMouseEnter);\n return () => {\n reference.removeEventListener(\"mouseenter\", onMouseEnter);\n };\n }\n }, [dataRef, delay, open, refs.reference, refs.floating, announce]);\n\n function setPointerRef(event: PointerEvent) {\n pointerTypeRef.current = event.pointerType;\n }\n\n return {\n reference: {\n onPointerDown: setPointerRef,\n onPointerEnter: setPointerRef,\n },\n floating: {\n onMouseEnter() {\n clearTimeout(timeoutRef.current);\n },\n },\n };\n};\n"],"names":["useRef","useAriaAnnouncer","useIsomorphicLayoutEffect","useEffect"],"mappings":";;;;;;;;;;;;;AAKA,SAAS,YAAY,QAA8B,EAAA;AACjD,EAAA,OAAA,CAAO,qCAAU,aAAiB,KAAA,QAAA;AACpC;AAIA,SAAS,UAAU,KAAY,EAAA;AAC7B,EAAO,OAAA,WAAA,CAAY,KAAK,CAAA,CAAE,WAAe,IAAA,MAAA;AAC3C;AAEA,SAAS,UAAU,KAAsC,EAAA;AACvD,EAAA,OAAO,KAAQ,GAAA,KAAA,YAAiB,SAAU,CAAA,KAAK,EAAE,OAAU,GAAA,KAAA;AAC7D;AAEA,SAAS,QAAA,CACP,KACA,EAAA,IAAA,EACA,WACA,EAAA;AACA,EAAI,IAAA,WAAA,IAAe,gBAAgB,OAAS,EAAA;AAC1C,IAAO,OAAA,CAAA;AAAA;AAGT,EAAI,IAAA,OAAO,UAAU,QAAU,EAAA;AAC7B,IAAO,OAAA,KAAA;AAAA;AAGT,EAAA,OAAO,KAAQ,IAAA,IAAA,GAAA,
|
|
1
|
+
{"version":3,"file":"useAriaAnnounce.js","sources":["../src/tooltip/useAriaAnnounce.ts"],"sourcesContent":["import type { ElementProps, FloatingContext } from \"@floating-ui/react\";\nimport { type PointerEvent, useEffect, useRef } from \"react\";\nimport { useAriaAnnouncer } from \"../aria-announcer\";\nimport { useIsomorphicLayoutEffect } from \"../utils\";\n\nfunction getDocument(floating: HTMLElement | null) {\n return floating?.ownerDocument ?? document;\n}\n\n// TODO: Check whether can be anything more restrictive than `any`\n// biome-ignore lint/suspicious/noExplicitAny: see comment above\nfunction getWindow(value: any) {\n return getDocument(value).defaultView ?? window;\n}\n\nfunction isElement(value: unknown): value is HTMLElement {\n return value ? value instanceof getWindow(value).Element : false;\n}\n\nfunction getDelay(\n value: Props[\"delay\"],\n prop: \"open\" | \"close\",\n pointerType?: PointerEvent[\"pointerType\"],\n) {\n if (pointerType && pointerType !== \"mouse\") {\n return 0;\n }\n\n if (typeof value === \"number\") {\n return value;\n }\n\n return value?.[prop];\n}\n\ntype Props = {\n delay?: number | Partial<{ open: number; close: number }>;\n};\n\nexport const useAriaAnnounce = (\n context: FloatingContext,\n { delay = 0 }: Props,\n): ElementProps => {\n const { open, dataRef, refs } = context;\n\n const pointerTypeRef = useRef<PointerEvent[\"pointerType\"]>();\n const timeoutRef = useRef<number>();\n const blockMouseMoveRef = useRef(true);\n const { announce } = useAriaAnnouncer();\n\n useIsomorphicLayoutEffect(() => {\n if (!open) {\n pointerTypeRef.current = undefined;\n }\n });\n\n useEffect(() => {\n const reference = refs.reference.current;\n function announceFloating() {\n const tooltipContent = refs.floating.current?.innerText;\n\n if (tooltipContent) {\n announce(tooltipContent);\n }\n }\n\n function onMouseEnter(event: MouseEvent) {\n clearTimeout(timeoutRef.current);\n\n if (open) {\n return;\n }\n\n blockMouseMoveRef.current = false;\n dataRef.current.openEvent = event;\n\n if (delay) {\n timeoutRef.current = window.setTimeout(\n () => {\n announceFloating();\n },\n getDelay(delay, \"open\", pointerTypeRef.current),\n );\n } else {\n announceFloating();\n }\n }\n\n if (isElement(reference)) {\n reference.addEventListener(\"mouseenter\", onMouseEnter);\n return () => {\n reference.removeEventListener(\"mouseenter\", onMouseEnter);\n };\n }\n }, [dataRef, delay, open, refs.reference, refs.floating, announce]);\n\n function setPointerRef(event: PointerEvent) {\n pointerTypeRef.current = event.pointerType;\n }\n\n return {\n reference: {\n onPointerDown: setPointerRef,\n onPointerEnter: setPointerRef,\n },\n floating: {\n onMouseEnter() {\n clearTimeout(timeoutRef.current);\n },\n },\n };\n};\n"],"names":["useRef","useAriaAnnouncer","useIsomorphicLayoutEffect","useEffect"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTooltip.js","sources":["../src/tooltip/useTooltip.ts"],"sourcesContent":["import {\n arrow,\n flip,\n limitShift,\n offset,\n safePolygon,\n shift,\n useDismiss,\n useFocus,\n useHover,\n useInteractions,\n useRole,\n} from \"@floating-ui/react\";\nimport { type HTMLProps, useRef } from \"react\";\nimport {\n type UseFloatingUIProps,\n useControlled,\n useFloatingUI,\n} from \"../utils\";\nimport { useAriaAnnounce } from \"./useAriaAnnounce\";\n\nexport interface UseTooltipProps\n extends Partial<\n Pick<UseFloatingUIProps, \"onOpenChange\" | \"open\" | \"placement\">\n > {\n /**\n * When `true`, the tooltip will be disabled.\n */\n disabled?: boolean;\n /**\n * Do not respond to focus events.\n */\n disableFocusListener?: boolean;\n /**\n * Do not respond to hover events.\n */\n disableHoverListener?: boolean;\n /**\n * The number of milliseconds to wait before showing the tooltip.\n * This prop won't impact the enter touch delay (`enterTouchDelay`).\n */\n enterDelay?: number;\n /**\n * The number of milliseconds to wait before hiding the tooltip.\n * This prop won't impact the leave touch delay (`leaveTouchDelay`).\n */\n leaveDelay?: number;\n}\n\nexport function useTooltip(props?: UseTooltipProps) {\n const {\n enterDelay,\n disabled,\n leaveDelay,\n open: openProp,\n onOpenChange,\n placement: placementProp,\n disableHoverListener,\n disableFocusListener,\n } = props ?? {};\n\n const arrowRef = useRef<SVGSVGElement | null>(null);\n\n const [open, setOpen] = useControlled({\n controlled: openProp,\n default: false,\n name: \"Tooltip\",\n state: \"open\",\n });\n const handleOpenChange = (open: boolean) => {\n setOpen(open);\n onOpenChange?.(open);\n };\n\n const { floating, reference, x, y, strategy, placement, context, elements } =\n useFloatingUI({\n open: disabled ? false : open,\n onOpenChange: handleOpenChange,\n placement: placementProp,\n middleware: [\n offset(8),\n shift({ limiter: limitShift() }),\n flip({\n fallbackAxisSideDirection: \"end\",\n fallbackStrategy: \"initialPlacement\",\n }),\n arrow({ element: arrowRef }),\n ],\n });\n\n const { getReferenceProps, getFloatingProps } = useInteractions([\n useHover(context, {\n delay: {\n open: enterDelay,\n close: leaveDelay,\n },\n enabled: !(disableHoverListener || disabled),\n handleClose: safePolygon(),\n }),\n useFocus(context, { enabled: !(disableFocusListener || disabled) }),\n useRole(context, { role: \"tooltip\" }),\n useDismiss(context, { enabled: !disabled }),\n useAriaAnnounce(context, {\n delay: {\n open: enterDelay,\n close: leaveDelay,\n },\n }),\n ]);\n\n const arrowProps = {\n ref: arrowRef,\n context,\n };\n\n const getTooltipProps = (): HTMLProps<HTMLDivElement> => {\n // tabIndex raises false positives because it is set to \"-1\".\n const { tabIndex, ...tooltipProps } = getFloatingProps({\n // @ts-expect-error - `data-*` props need extra typing when not used on a DOM element.\n \"data-placement\": placement,\n ref: floating,\n });\n\n return tooltipProps;\n };\n\n const getTriggerProps = () =>\n getReferenceProps({\n ref: reference,\n });\n\n const getTooltipPosition = () => ({\n top: y ?? 0,\n left: x ?? 0,\n position: strategy,\n width: elements.floating?.offsetWidth,\n height: elements.floating?.offsetHeight,\n });\n\n return {\n arrowProps,\n open,\n floating,\n reference,\n getTooltipProps,\n getTriggerProps,\n getTooltipPosition,\n };\n}\n"],"names":["useRef","useControlled","open","useFloatingUI","offset","shift","limitShift","flip","arrow","useInteractions","useHover","safePolygon","useFocus","useRole","useDismiss","useAriaAnnounce"],"mappings":";;;;;;;;;;;;;AAiDO,SAAS,WAAW,KAAyB,EAAA;AAClD,EAAM,MAAA;AAAA,IACJ,UAAA;AAAA,IACA,QAAA;AAAA,IACA,UAAA;AAAA,IACA,IAAM,EAAA,QAAA;AAAA,IACN,YAAA;AAAA,IACA,SAAW,EAAA,aAAA;AAAA,IACX,oBAAA;AAAA,IACA;AAAA,GACF,GAAI,SAAS,EAAC;AAEd,EAAM,MAAA,QAAA,GAAWA,aAA6B,IAAI,CAAA;AAElD,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIC,2BAAc,CAAA;AAAA,IACpC,UAAY,EAAA,QAAA;AAAA,IACZ,OAAS,EAAA,KAAA;AAAA,IACT,IAAM,EAAA,SAAA;AAAA,IACN,KAAO,EAAA;AAAA,GACR,CAAA;AACD,EAAM,MAAA,gBAAA,GAAmB,CAACC,KAAkB,KAAA;AAC1C,IAAA,OAAA,CAAQA,KAAI,CAAA;AACZ,IAAeA,YAAAA,IAAAA,IAAAA,GAAAA,
|
|
1
|
+
{"version":3,"file":"useTooltip.js","sources":["../src/tooltip/useTooltip.ts"],"sourcesContent":["import {\n arrow,\n flip,\n limitShift,\n offset,\n safePolygon,\n shift,\n useDismiss,\n useFocus,\n useHover,\n useInteractions,\n useRole,\n} from \"@floating-ui/react\";\nimport { type HTMLProps, useRef } from \"react\";\nimport {\n type UseFloatingUIProps,\n useControlled,\n useFloatingUI,\n} from \"../utils\";\nimport { useAriaAnnounce } from \"./useAriaAnnounce\";\n\nexport interface UseTooltipProps\n extends Partial<\n Pick<UseFloatingUIProps, \"onOpenChange\" | \"open\" | \"placement\">\n > {\n /**\n * When `true`, the tooltip will be disabled.\n */\n disabled?: boolean;\n /**\n * Do not respond to focus events.\n */\n disableFocusListener?: boolean;\n /**\n * Do not respond to hover events.\n */\n disableHoverListener?: boolean;\n /**\n * The number of milliseconds to wait before showing the tooltip.\n * This prop won't impact the enter touch delay (`enterTouchDelay`).\n */\n enterDelay?: number;\n /**\n * The number of milliseconds to wait before hiding the tooltip.\n * This prop won't impact the leave touch delay (`leaveTouchDelay`).\n */\n leaveDelay?: number;\n}\n\nexport function useTooltip(props?: UseTooltipProps) {\n const {\n enterDelay,\n disabled,\n leaveDelay,\n open: openProp,\n onOpenChange,\n placement: placementProp,\n disableHoverListener,\n disableFocusListener,\n } = props ?? {};\n\n const arrowRef = useRef<SVGSVGElement | null>(null);\n\n const [open, setOpen] = useControlled({\n controlled: openProp,\n default: false,\n name: \"Tooltip\",\n state: \"open\",\n });\n const handleOpenChange = (open: boolean) => {\n setOpen(open);\n onOpenChange?.(open);\n };\n\n const { floating, reference, x, y, strategy, placement, context, elements } =\n useFloatingUI({\n open: disabled ? false : open,\n onOpenChange: handleOpenChange,\n placement: placementProp,\n middleware: [\n offset(8),\n shift({ limiter: limitShift() }),\n flip({\n fallbackAxisSideDirection: \"end\",\n fallbackStrategy: \"initialPlacement\",\n }),\n arrow({ element: arrowRef }),\n ],\n });\n\n const { getReferenceProps, getFloatingProps } = useInteractions([\n useHover(context, {\n delay: {\n open: enterDelay,\n close: leaveDelay,\n },\n enabled: !(disableHoverListener || disabled),\n handleClose: safePolygon(),\n }),\n useFocus(context, { enabled: !(disableFocusListener || disabled) }),\n useRole(context, { role: \"tooltip\" }),\n useDismiss(context, { enabled: !disabled }),\n useAriaAnnounce(context, {\n delay: {\n open: enterDelay,\n close: leaveDelay,\n },\n }),\n ]);\n\n const arrowProps = {\n ref: arrowRef,\n context,\n };\n\n const getTooltipProps = (): HTMLProps<HTMLDivElement> => {\n // tabIndex raises false positives because it is set to \"-1\".\n const { tabIndex, ...tooltipProps } = getFloatingProps({\n // @ts-expect-error - `data-*` props need extra typing when not used on a DOM element.\n \"data-placement\": placement,\n ref: floating,\n });\n\n return tooltipProps;\n };\n\n const getTriggerProps = () =>\n getReferenceProps({\n ref: reference,\n });\n\n const getTooltipPosition = () => ({\n top: y ?? 0,\n left: x ?? 0,\n position: strategy,\n width: elements.floating?.offsetWidth,\n height: elements.floating?.offsetHeight,\n });\n\n return {\n arrowProps,\n open,\n floating,\n reference,\n getTooltipProps,\n getTriggerProps,\n getTooltipPosition,\n };\n}\n"],"names":["useRef","useControlled","open","useFloatingUI","offset","shift","limitShift","flip","arrow","useInteractions","useHover","safePolygon","useFocus","useRole","useDismiss","useAriaAnnounce"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mergeProps.js","sources":["../src/utils/mergeProps.ts"],"sourcesContent":["import { clsx } from \"clsx\";\nimport { createChainedFunction } from \"./createChainedFunction\";\n\ninterface Props {\n [key: string]: unknown;\n}\n\n/**\n * This utility merges two prop objects according to the following rules:\n *\n * - If the prop is a function and begins with \"on\" then chain the functions together\n * - If the prop key is \"className\" then merge them using `clsx`\n * - If the prop is anything else, then use the value from the second parameter unless it's undefined then use the value from the first parameter\n */\nexport function mergeProps(\n propsA: Props,\n propsB: Props,\n): Record<string, unknown> {\n const props = { ...propsA };\n\n Object.keys(propsB).forEach((key) => {\n const a: any = props[key];\n const b: any = propsB[key];\n\n if (\n typeof a === \"function\" &&\n typeof b === \"function\" &&\n key.indexOf(\"on\") === 0\n ) {\n props[key] = createChainedFunction(a, b);\n } else if (\n typeof a === \"string\" &&\n typeof b === \"string\" &&\n key === \"className\"\n ) {\n props[key] = clsx(a, b);\n } else {\n props[key] = b !== undefined ? b : a;\n }\n });\n\n return props;\n}\n"],"names":["createChainedFunction","clsx"],"mappings":";;;;;AAcgB,SAAA,UAAA,CACd,QACA,MACyB,EAAA;AACzB,EAAM,MAAA,KAAA,GAAQ,EAAE,GAAG,MAAO,EAAA;AAE1B,EAAA,MAAA,CAAO,IAAK,CAAA,MAAM,CAAE,CAAA,OAAA,CAAQ,CAAC,GAAQ,KAAA;AACnC,IAAM,MAAA,CAAA,GAAS,MAAM,GAAG,CAAA;AACxB,IAAM,MAAA,CAAA,GAAS,OAAO,GAAG,CAAA;AAEzB,IACE,IAAA,OAAO,CAAM,KAAA,UAAA,IACb,OAAO,CAAA,KAAM,cACb,GAAI,CAAA,OAAA,CAAQ,IAAI,CAAA,KAAM,CACtB,EAAA;AACA,MAAA,KAAA,CAAM,GAAG,CAAA,GAAIA,2CAAsB,CAAA,CAAA,EAAG,CAAC,CAAA;AAAA,KACzC,MAAA,IACE,OAAO,CAAM,KAAA,QAAA,IACb,OAAO,CAAM,KAAA,QAAA,IACb,QAAQ,WACR,EAAA;AACA,MAAA,KAAA,CAAM,GAAG,CAAA,GAAIC,SAAK,CAAA,CAAA,EAAG,CAAC,CAAA;AAAA,KACjB,MAAA;AACL,MAAA,KAAA,CAAM,GAAG,CAAA,GAAI,CAAM,KAAA,
|
|
1
|
+
{"version":3,"file":"mergeProps.js","sources":["../src/utils/mergeProps.ts"],"sourcesContent":["import { clsx } from \"clsx\";\nimport { createChainedFunction } from \"./createChainedFunction\";\n\ninterface Props {\n [key: string]: unknown;\n}\n\n/**\n * This utility merges two prop objects according to the following rules:\n *\n * - If the prop is a function and begins with \"on\" then chain the functions together\n * - If the prop key is \"className\" then merge them using `clsx`\n * - If the prop is anything else, then use the value from the second parameter unless it's undefined then use the value from the first parameter\n */\nexport function mergeProps(\n propsA: Props,\n propsB: Props,\n): Record<string, unknown> {\n const props = { ...propsA };\n\n Object.keys(propsB).forEach((key) => {\n const a: any = props[key];\n const b: any = propsB[key];\n\n if (\n typeof a === \"function\" &&\n typeof b === \"function\" &&\n key.indexOf(\"on\") === 0\n ) {\n props[key] = createChainedFunction(a, b);\n } else if (\n typeof a === \"string\" &&\n typeof b === \"string\" &&\n key === \"className\"\n ) {\n props[key] = clsx(a, b);\n } else {\n props[key] = b !== undefined ? b : a;\n }\n });\n\n return props;\n}\n"],"names":["createChainedFunction","clsx"],"mappings":";;;;;AAcgB,SAAA,UAAA,CACd,QACA,MACyB,EAAA;AACzB,EAAM,MAAA,KAAA,GAAQ,EAAE,GAAG,MAAO,EAAA;AAE1B,EAAA,MAAA,CAAO,IAAK,CAAA,MAAM,CAAE,CAAA,OAAA,CAAQ,CAAC,GAAQ,KAAA;AACnC,IAAM,MAAA,CAAA,GAAS,MAAM,GAAG,CAAA;AACxB,IAAM,MAAA,CAAA,GAAS,OAAO,GAAG,CAAA;AAEzB,IACE,IAAA,OAAO,CAAM,KAAA,UAAA,IACb,OAAO,CAAA,KAAM,cACb,GAAI,CAAA,OAAA,CAAQ,IAAI,CAAA,KAAM,CACtB,EAAA;AACA,MAAA,KAAA,CAAM,GAAG,CAAA,GAAIA,2CAAsB,CAAA,CAAA,EAAG,CAAC,CAAA;AAAA,KACzC,MAAA,IACE,OAAO,CAAM,KAAA,QAAA,IACb,OAAO,CAAM,KAAA,QAAA,IACb,QAAQ,WACR,EAAA;AACA,MAAA,KAAA,CAAM,GAAG,CAAA,GAAIC,SAAK,CAAA,CAAA,EAAG,CAAC,CAAA;AAAA,KACjB,MAAA;AACL,MAAA,KAAA,CAAM,GAAG,CAAA,GAAI,CAAM,KAAA,MAAA,GAAY,CAAI,GAAA,CAAA;AAAA;AACrC,GACD,CAAA;AAED,EAAO,OAAA,KAAA;AACT;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useControlled.js","sources":["../src/utils/useControlled.ts"],"sourcesContent":["import {\n type Dispatch,\n type SetStateAction,\n isValidElement,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\n\nexport interface UseControlledProps<T> {\n /**\n * Holds the component value when it's controlled.\n */\n controlled?: T;\n /**\n * The default value when uncontrolled.\n */\n default: T;\n /**\n * The component name displayed in warnings.\n */\n name: string;\n /**\n * The name of the state variable displayed in warnings.\n */\n state?: string;\n}\n\n/**\n * Copied from MUI (v5) useControlled hook with one additional returned value\n * @see https://github.com/mui-org/material-ui/blob/0979e6a54ba47c278d1f535953c0520a86349811/packages/material-ui-utils/src/useControlled.js\n */\nexport function useControlled<S>({\n controlled,\n default: defaultProp,\n name,\n state = \"value\",\n}: UseControlledProps<S>): [S, Dispatch<SetStateAction<S>>, boolean] {\n const { current: isControlled } = useRef(controlled !== undefined);\n const [valueState, setValue] = useState<S>(defaultProp);\n const value = controlled !== undefined ? controlled : valueState;\n const { current: defaultValue } = useRef(defaultProp);\n\n useEffect(() => {\n if (process.env.NODE_ENV !== \"production\") {\n if (isControlled !== (controlled !== undefined)) {\n console.error(\n [\n `Salt: A component is changing the ${\n isControlled ? \"\" : \"un\"\n }controlled ${state} state of ${name} to be ${\n isControlled ? \"un\" : \"\"\n }controlled.`,\n \"Elements should not switch from uncontrolled to controlled (or vice versa).\",\n `Decide between using a controlled or uncontrolled ${name} element for the lifetime of the component.`,\n \"The nature of the state is determined during the first render, it's considered controlled if the value is not `undefined`.\",\n \"More info: https://reactjs.org/link/controlled-components\",\n ].join(\"\\n\"),\n );\n }\n }\n return undefined;\n }, [state, name, controlled]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: uses JSON.stringify to compare defaultProp\n useEffect(() => {\n if (process.env.NODE_ENV !== \"production\") {\n if (!isControlled && defaultValue !== defaultProp) {\n console.error(\n [\n `Salt: A component is changing the default ${state} state of an uncontrolled ${name} after being initialized. ` +\n `To suppress this warning opt to use a controlled ${name}.`,\n ].join(\"\\n\"),\n );\n }\n }\n return undefined;\n }, [JSON.stringify(defaultProp, ignoreReactElements)]);\n\n const setValueIfUncontrolled: Dispatch<SetStateAction<S>> = useCallback(\n (newValue) => {\n if (!isControlled) {\n setValue(newValue);\n }\n },\n [],\n );\n\n return [value, setValueIfUncontrolled, isControlled];\n}\n\n// Ignore ReactElements in JSON, they contain circular refs\nfunction ignoreReactElements<T>(key: string, value: T): T | null {\n return isValidElement(value) ? null : value;\n}\n"],"names":["useRef","useState","useEffect","useCallback","isValidElement"],"mappings":";;;;AAiCO,SAAS,aAAiB,CAAA;AAAA,EAC/B,UAAA;AAAA,EACA,OAAS,EAAA,WAAA;AAAA,EACT,IAAA;AAAA,EACA,KAAQ,GAAA;AACV,CAAqE,EAAA;AACnE,EAAA,MAAM,EAAE,OAAS,EAAA,YAAA,EAAiB,GAAAA,YAAA,CAAO,eAAe,
|
|
1
|
+
{"version":3,"file":"useControlled.js","sources":["../src/utils/useControlled.ts"],"sourcesContent":["import {\n type Dispatch,\n type SetStateAction,\n isValidElement,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\n\nexport interface UseControlledProps<T> {\n /**\n * Holds the component value when it's controlled.\n */\n controlled?: T;\n /**\n * The default value when uncontrolled.\n */\n default: T;\n /**\n * The component name displayed in warnings.\n */\n name: string;\n /**\n * The name of the state variable displayed in warnings.\n */\n state?: string;\n}\n\n/**\n * Copied from MUI (v5) useControlled hook with one additional returned value\n * @see https://github.com/mui-org/material-ui/blob/0979e6a54ba47c278d1f535953c0520a86349811/packages/material-ui-utils/src/useControlled.js\n */\nexport function useControlled<S>({\n controlled,\n default: defaultProp,\n name,\n state = \"value\",\n}: UseControlledProps<S>): [S, Dispatch<SetStateAction<S>>, boolean] {\n const { current: isControlled } = useRef(controlled !== undefined);\n const [valueState, setValue] = useState<S>(defaultProp);\n const value = controlled !== undefined ? controlled : valueState;\n const { current: defaultValue } = useRef(defaultProp);\n\n useEffect(() => {\n if (process.env.NODE_ENV !== \"production\") {\n if (isControlled !== (controlled !== undefined)) {\n console.error(\n [\n `Salt: A component is changing the ${\n isControlled ? \"\" : \"un\"\n }controlled ${state} state of ${name} to be ${\n isControlled ? \"un\" : \"\"\n }controlled.`,\n \"Elements should not switch from uncontrolled to controlled (or vice versa).\",\n `Decide between using a controlled or uncontrolled ${name} element for the lifetime of the component.`,\n \"The nature of the state is determined during the first render, it's considered controlled if the value is not `undefined`.\",\n \"More info: https://reactjs.org/link/controlled-components\",\n ].join(\"\\n\"),\n );\n }\n }\n return undefined;\n }, [state, name, controlled]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: uses JSON.stringify to compare defaultProp\n useEffect(() => {\n if (process.env.NODE_ENV !== \"production\") {\n if (!isControlled && defaultValue !== defaultProp) {\n console.error(\n [\n `Salt: A component is changing the default ${state} state of an uncontrolled ${name} after being initialized. ` +\n `To suppress this warning opt to use a controlled ${name}.`,\n ].join(\"\\n\"),\n );\n }\n }\n return undefined;\n }, [JSON.stringify(defaultProp, ignoreReactElements)]);\n\n const setValueIfUncontrolled: Dispatch<SetStateAction<S>> = useCallback(\n (newValue) => {\n if (!isControlled) {\n setValue(newValue);\n }\n },\n [],\n );\n\n return [value, setValueIfUncontrolled, isControlled];\n}\n\n// Ignore ReactElements in JSON, they contain circular refs\nfunction ignoreReactElements<T>(key: string, value: T): T | null {\n return isValidElement(value) ? null : value;\n}\n"],"names":["useRef","useState","useEffect","useCallback","isValidElement"],"mappings":";;;;AAiCO,SAAS,aAAiB,CAAA;AAAA,EAC/B,UAAA;AAAA,EACA,OAAS,EAAA,WAAA;AAAA,EACT,IAAA;AAAA,EACA,KAAQ,GAAA;AACV,CAAqE,EAAA;AACnE,EAAA,MAAM,EAAE,OAAS,EAAA,YAAA,EAAiB,GAAAA,YAAA,CAAO,eAAe,MAAS,CAAA;AACjE,EAAA,MAAM,CAAC,UAAA,EAAY,QAAQ,CAAA,GAAIC,eAAY,WAAW,CAAA;AACtD,EAAM,MAAA,KAAA,GAAQ,UAAe,KAAA,MAAA,GAAY,UAAa,GAAA,UAAA;AACtD,EAAA,MAAM,EAAE,OAAA,EAAS,YAAa,EAAA,GAAID,aAAO,WAAW,CAAA;AAEpD,EAAAE,eAAA,CAAU,MAAM;AACd,IAAI,IAAA,OAAA,CAAQ,GAAI,CAAA,QAAA,KAAa,YAAc,EAAA;AACzC,MAAI,IAAA,YAAA,MAAkB,eAAe,MAAY,CAAA,EAAA;AAC/C,QAAQ,OAAA,CAAA,KAAA;AAAA,UACN;AAAA,YACE,CAAA,kCAAA,EACE,YAAe,GAAA,EAAA,GAAK,IACtB,CAAA,WAAA,EAAc,KAAK,CAAA,UAAA,EAAa,IAAI,CAAA,OAAA,EAClC,YAAe,GAAA,IAAA,GAAO,EACxB,CAAA,WAAA,CAAA;AAAA,YACA,6EAAA;AAAA,YACA,qDAAqD,IAAI,CAAA,2CAAA,CAAA;AAAA,YACzD,4HAAA;AAAA,YACA;AAAA,WACF,CAAE,KAAK,IAAI;AAAA,SACb;AAAA;AACF;AAEF,IAAO,OAAA,MAAA;AAAA,GACN,EAAA,CAAC,KAAO,EAAA,IAAA,EAAM,UAAU,CAAC,CAAA;AAG5B,EAAAA,eAAA,CAAU,MAAM;AACd,IAAI,IAAA,OAAA,CAAQ,GAAI,CAAA,QAAA,KAAa,YAAc,EAAA;AACzC,MAAI,IAAA,CAAC,YAAgB,IAAA,YAAA,KAAiB,WAAa,EAAA;AACjD,QAAQ,OAAA,CAAA,KAAA;AAAA,UACN;AAAA,YACE,CAA6C,0CAAA,EAAA,KAAK,CAA6B,0BAAA,EAAA,IAAI,8EAC7B,IAAI,CAAA,CAAA;AAAA,WAC5D,CAAE,KAAK,IAAI;AAAA,SACb;AAAA;AACF;AAEF,IAAO,OAAA,MAAA;AAAA,KACN,CAAC,IAAA,CAAK,UAAU,WAAa,EAAA,mBAAmB,CAAC,CAAC,CAAA;AAErD,EAAA,MAAM,sBAAsD,GAAAC,iBAAA;AAAA,IAC1D,CAAC,QAAa,KAAA;AACZ,MAAA,IAAI,CAAC,YAAc,EAAA;AACjB,QAAA,QAAA,CAAS,QAAQ,CAAA;AAAA;AACnB,KACF;AAAA,IACA;AAAC,GACH;AAEA,EAAO,OAAA,CAAC,KAAO,EAAA,sBAAA,EAAwB,YAAY,CAAA;AACrD;AAGA,SAAS,mBAAA,CAAuB,KAAa,KAAoB,EAAA;AAC/D,EAAO,OAAAC,oBAAA,CAAe,KAAK,CAAA,GAAI,IAAO,GAAA,KAAA;AACxC;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFloatingUI.js","sources":["../src/utils/useFloatingUI/useFloatingUI.tsx"],"sourcesContent":["import {\n FloatingFocusManager,\n type FloatingFocusManagerProps,\n FloatingPortal,\n type Middleware,\n type Platform,\n type Strategy,\n type UseFloatingOptions,\n autoUpdate,\n flip,\n limitShift,\n platform,\n shift,\n useFloating,\n} from \"@floating-ui/react\";\nimport {\n type ComponentPropsWithoutRef,\n type ReactNode,\n createContext,\n forwardRef,\n useContext,\n useMemo,\n} from \"react\";\nimport { SaltProvider, SaltProviderNext, useTheme } from \"../../salt-provider\";\nimport { usePreventScroll } from \"../usePreventScroll\";\n\nexport interface FloatingComponentProps\n extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * Whether the floating component is open (used for determining whether to show the component)\n * We pass this as a prop rather than not rendering the component to allow more advanced use-cases e.g.\n * for caching windows and reusing them, rather than always spawning a new one\n */\n open: boolean;\n /**\n * Use this prop when `FloatingFocusManager` is needed for floating component\n */\n focusManagerProps?: Omit<FloatingFocusManagerProps, \"children\">;\n /**\n * Position and sizing optional props for the floating component. `top`, `left`, and `position` for floating elements where they aren't positioned with relative to the trigger.\n * `width` and `height` are used to define the size of the floating element.\n *\n */\n top?: number;\n left?: number;\n width?: number;\n height?: number;\n position?: Strategy;\n /**\n * Makes the page unscrollable when the floating component is open.\n */\n lockScroll?: boolean;\n}\n\nconst DefaultFloatingComponent = forwardRef<\n HTMLDivElement,\n FloatingComponentProps\n>(function DefaultFloatingComponent(props, ref) {\n const {\n open,\n top,\n left,\n position,\n width,\n height,\n focusManagerProps,\n lockScroll,\n ...rest\n } = props;\n const style = {\n top,\n left,\n position,\n };\n\n const { themeNext } = useTheme();\n usePreventScroll({ isDisabled: !lockScroll || !open });\n\n const ChosenSaltProvider = themeNext ? SaltProviderNext : SaltProvider;\n\n if (focusManagerProps && open) {\n return (\n <FloatingPortal>\n <ChosenSaltProvider applyClassesTo=\"scope\">\n <FloatingFocusManager {...focusManagerProps}>\n <div style={style} {...rest} ref={ref} />\n </FloatingFocusManager>\n </ChosenSaltProvider>\n </FloatingPortal>\n );\n }\n\n return open ? (\n <FloatingPortal>\n <ChosenSaltProvider applyClassesTo=\"scope\">\n <div style={style} {...rest} ref={ref} />\n </ChosenSaltProvider>\n </FloatingPortal>\n ) : null;\n});\n\nexport interface FloatingComponentContextType {\n Component: typeof DefaultFloatingComponent;\n}\n\nconst FloatingComponentContext = createContext<FloatingComponentContextType>({\n Component: DefaultFloatingComponent,\n});\n\nif (process.env.NODE_ENV !== \"production\") {\n FloatingComponentContext.displayName = \"FloatingComponentContext\";\n}\n\nexport interface FloatingComponentProviderProps\n extends FloatingComponentContextType {\n children: ReactNode;\n}\n\nexport function FloatingComponentProvider(\n props: FloatingComponentProviderProps,\n) {\n const { Component, children } = props;\n const value = useMemo(() => ({ Component }), [Component]);\n\n return (\n <FloatingComponentContext.Provider value={value}>\n {children}\n </FloatingComponentContext.Provider>\n );\n}\n\nexport function useFloatingComponent() {\n return useContext(FloatingComponentContext);\n}\n\nexport interface UseFloatingUIProps\n extends Pick<\n UseFloatingOptions,\n \"placement\" | \"strategy\" | \"open\" | \"onOpenChange\" | \"nodeId\"\n > {\n /**\n * Function to update the default middleware used to extend or replace it\n */\n middleware?: Middleware[];\n}\n\ntype GetMiddleware = (middleware: Middleware[]) => Middleware[];\n\nconst defaultGetMiddleware: GetMiddleware = (defaultMiddleware) =>\n defaultMiddleware;\n\ninterface FloatingPlatformContextType {\n platform: Platform;\n middleware: GetMiddleware;\n animationFrame: boolean;\n}\n\nconst defaultFloatingPlaform: FloatingPlatformContextType = {\n platform,\n middleware: defaultGetMiddleware,\n animationFrame: false,\n};\n\nconst FloatingPlatformContext = createContext<FloatingPlatformContextType>(\n defaultFloatingPlaform,\n);\n\nexport interface FloatingPlatformProviderProps {\n platform?: Platform;\n middleware?: GetMiddleware;\n children: ReactNode;\n animationFrame?: boolean;\n}\n\nexport function FloatingPlatformProvider(props: FloatingPlatformProviderProps) {\n const {\n platform: platformProp,\n middleware,\n animationFrame,\n children,\n } = props;\n\n const floatingPlatformContextValue = useMemo<FloatingPlatformContextType>(\n () => ({\n platform: platformProp ?? platform,\n middleware: middleware ?? defaultGetMiddleware,\n animationFrame: animationFrame || false,\n }),\n [platformProp, middleware, animationFrame],\n );\n\n return (\n <FloatingPlatformContext.Provider value={floatingPlatformContextValue}>\n {children}\n </FloatingPlatformContext.Provider>\n );\n}\n\nexport function useFloatingPlatform() {\n return useContext(FloatingPlatformContext);\n}\n\nexport const DEFAULT_FLOATING_UI_MIDDLEWARE = [\n flip(),\n shift({ limiter: limitShift() }),\n];\n\ntype UseFloatingRefs = ReturnType<typeof useFloating>[\"refs\"];\n\nexport interface UseFloatingUIReturn extends ReturnType<typeof useFloating> {\n reference: UseFloatingRefs[\"setReference\"];\n floating: UseFloatingRefs[\"setFloating\"];\n}\n\nexport function useFloatingUI(props: UseFloatingUIProps): UseFloatingUIReturn {\n const {\n middleware = DEFAULT_FLOATING_UI_MIDDLEWARE,\n open = false,\n onOpenChange,\n ...other\n } = props;\n\n const handleOpenChange: UseFloatingUIProps[\"onOpenChange\"] = (\n open,\n boolean,\n reason,\n ) => {\n update();\n onOpenChange?.(open, boolean, reason);\n };\n\n const {\n platform: contextPlatform,\n middleware: contextMiddleware,\n animationFrame,\n } = useFloatingPlatform();\n\n const { refs, update, ...rest } = useFloating({\n ...other,\n middleware: contextMiddleware(middleware),\n open,\n onOpenChange: handleOpenChange,\n whileElementsMounted: (...args) => {\n const cleanup = autoUpdate(...args, { animationFrame });\n\n return cleanup;\n },\n platform: contextPlatform,\n });\n\n return {\n reference: refs.setReference,\n floating: refs.setFloating,\n refs,\n update,\n ...rest,\n };\n}\n"],"names":["forwardRef","DefaultFloatingComponent","useTheme","usePreventScroll","SaltProviderNext","SaltProvider","FloatingPortal","jsx","FloatingFocusManager","createContext","useMemo","useContext","platform","flip","shift","limitShift","open","useFloating","autoUpdate"],"mappings":";;;;;;;;AAsDA,MAAM,wBAA2B,GAAAA,gBAAA,CAG/B,SAASC,yBAAAA,CAAyB,OAAO,GAAK,EAAA;AAC9C,EAAM,MAAA;AAAA,IACJ,IAAA;AAAA,IACA,GAAA;AAAA,IACA,IAAA;AAAA,IACA,QAAA;AAAA,IACA,KAAA;AAAA,IACA,MAAA;AAAA,IACA,iBAAA;AAAA,IACA,UAAA;AAAA,IACA,GAAG;AAAA,GACD,GAAA,KAAA;AACJ,EAAA,MAAM,KAAQ,GAAA;AAAA,IACZ,GAAA;AAAA,IACA,IAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAM,MAAA,EAAE,SAAU,EAAA,GAAIC,qBAAS,EAAA;AAC/B,EAAAC,iCAAA,CAAiB,EAAE,UAAY,EAAA,CAAC,UAAc,IAAA,CAAC,MAAM,CAAA;AAErD,EAAM,MAAA,kBAAA,GAAqB,YAAYC,6BAAmB,GAAAC,yBAAA;AAE1D,EAAA,IAAI,qBAAqB,IAAM,EAAA;AAC7B,IAAA,sCACGC,oBACC,EAAA,EAAA,QAAA,kBAAAC,cAAA,CAAC,sBAAmB,cAAe,EAAA,OAAA,EACjC,yCAACC,0BAAsB,EAAA,EAAA,GAAG,iBACxB,EAAA,QAAA,kBAAAD,cAAA,CAAC,SAAI,KAAe,EAAA,GAAG,MAAM,GAAU,EAAA,CAAA,EACzC,GACF,CACF,EAAA,CAAA;AAAA;AAIJ,EAAA,OAAO,IACL,mBAAAA,cAAA,CAACD,oBACC,EAAA,EAAA,QAAA,kBAAAC,cAAA,CAAC,sBAAmB,cAAe,EAAA,OAAA,EACjC,QAAC,kBAAAA,cAAA,CAAA,KAAA,EAAA,EAAI,OAAe,GAAG,IAAA,EAAM,GAAU,EAAA,CAAA,EACzC,GACF,CACE,GAAA,IAAA;AACN,CAAC,CAAA;AAMD,MAAM,2BAA2BE,mBAA4C,CAAA;AAAA,EAC3E,SAAW,EAAA;AACb,CAAC,CAAA;AAED,IAAI,OAAA,CAAQ,GAAI,CAAA,QAAA,KAAa,YAAc,EAAA;AACzC,EAAA,wBAAA,CAAyB,WAAc,GAAA,0BAAA;AACzC;AAOO,SAAS,0BACd,KACA,EAAA;AACA,EAAM,MAAA,EAAE,SAAW,EAAA,QAAA,EAAa,GAAA,KAAA;AAChC,EAAM,MAAA,KAAA,GAAQC,cAAQ,OAAO,EAAE,WAAc,CAAA,EAAA,CAAC,SAAS,CAAC,CAAA;AAExD,EAAA,uBACGH,cAAA,CAAA,wBAAA,CAAyB,QAAzB,EAAA,EAAkC,OAChC,QACH,EAAA,CAAA;AAEJ;AAEO,SAAS,oBAAuB,GAAA;AACrC,EAAA,OAAOI,iBAAW,wBAAwB,CAAA;AAC5C;AAeA,MAAM,oBAAA,GAAsC,CAAC,iBAC3C,KAAA,iBAAA;AAQF,MAAM,sBAAsD,GAAA;AAAA,YAC1DC,cAAA;AAAA,EACA,UAAY,EAAA,oBAAA;AAAA,EACZ,cAAgB,EAAA;AAClB,CAAA;AAEA,MAAM,uBAA0B,GAAAH,mBAAA;AAAA,EAC9B;AACF,CAAA;AASO,SAAS,yBAAyB,KAAsC,EAAA;AAC7E,EAAM,MAAA;AAAA,IACJ,QAAU,EAAA,YAAA;AAAA,IACV,UAAA;AAAA,IACA,cAAA;AAAA,IACA;AAAA,GACE,GAAA,KAAA;AAEJ,EAAA,MAAM,4BAA+B,GAAAC,aAAA;AAAA,IACnC,OAAO;AAAA,MACL,UAAU,YAAgB,IAAAE,cAAA;AAAA,MAC1B,YAAY,UAAc,IAAA,oBAAA;AAAA,MAC1B,gBAAgB,cAAkB,IAAA;AAAA,KACpC,CAAA;AAAA,IACA,CAAC,YAAc,EAAA,UAAA,EAAY,cAAc;AAAA,GAC3C;AAEA,EAAA,sCACG,uBAAwB,CAAA,QAAA,EAAxB,EAAiC,KAAA,EAAO,8BACtC,QACH,EAAA,CAAA;AAEJ;AAEO,SAAS,mBAAsB,GAAA;AACpC,EAAA,OAAOD,iBAAW,uBAAuB,CAAA;AAC3C;AAEO,MAAM,8BAAiC,GAAA;AAAA,EAC5CE,UAAK,EAAA;AAAA,EACLC,WAAM,CAAA,EAAE,OAAS,EAAAC,gBAAA,IAAc;AACjC;AASO,SAAS,cAAc,KAAgD,EAAA;AAC5E,EAAM,MAAA;AAAA,IACJ,UAAa,GAAA,8BAAA;AAAA,IACb,IAAO,GAAA,KAAA;AAAA,IACP,YAAA;AAAA,IACA,GAAG;AAAA,GACD,GAAA,KAAA;AAEJ,EAAA,MAAM,gBAAuD,GAAA,CAC3DC,KACA,EAAA,OAAA,EACA,MACG,KAAA;AACH,IAAO,MAAA,EAAA;AACP,IAAA,YAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,YAAA,CAAeA,OAAM,OAAS,EAAA,MAAA,CAAA;AAAA,GAChC;AAEA,EAAM,MAAA;AAAA,IACJ,QAAU,EAAA,eAAA;AAAA,IACV,UAAY,EAAA,iBAAA;AAAA,IACZ;AAAA,MACE,mBAAoB,EAAA;AAExB,EAAA,MAAM,EAAE,IAAM,EAAA,MAAA,EAAQ,GAAG,IAAA,KAASC,iBAAY,CAAA;AAAA,IAC5C,GAAG,KAAA;AAAA,IACH,UAAA,EAAY,kBAAkB,UAAU,CAAA;AAAA,IACxC,IAAA;AAAA,IACA,YAAc,EAAA,gBAAA;AAAA,IACd,oBAAA,EAAsB,IAAI,IAAS,KAAA;AACjC,MAAA,MAAM,UAAUC,gBAAW,CAAA,GAAG,IAAM,EAAA,EAAE,gBAAgB,CAAA;AAEtD,MAAO,OAAA,OAAA;AAAA,KACT;AAAA,IACA,QAAU,EAAA;AAAA,GACX,CAAA;AAED,EAAO,OAAA;AAAA,IACL,WAAW,IAAK,CAAA,YAAA;AAAA,IAChB,UAAU,IAAK,CAAA,WAAA;AAAA,IACf,IAAA;AAAA,IACA,MAAA;AAAA,IACA,GAAG;AAAA,GACL;AACF;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"useFloatingUI.js","sources":["../src/utils/useFloatingUI/useFloatingUI.tsx"],"sourcesContent":["import {\n FloatingFocusManager,\n type FloatingFocusManagerProps,\n FloatingPortal,\n type Middleware,\n type Platform,\n type Strategy,\n type UseFloatingOptions,\n autoUpdate,\n flip,\n limitShift,\n platform,\n shift,\n useFloating,\n} from \"@floating-ui/react\";\nimport {\n type ComponentPropsWithoutRef,\n type ReactNode,\n createContext,\n forwardRef,\n useContext,\n useMemo,\n} from \"react\";\nimport { SaltProvider, SaltProviderNext, useTheme } from \"../../salt-provider\";\nimport { usePreventScroll } from \"../usePreventScroll\";\n\nexport interface FloatingComponentProps\n extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * Whether the floating component is open (used for determining whether to show the component)\n * We pass this as a prop rather than not rendering the component to allow more advanced use-cases e.g.\n * for caching windows and reusing them, rather than always spawning a new one\n */\n open: boolean;\n /**\n * Use this prop when `FloatingFocusManager` is needed for floating component\n */\n focusManagerProps?: Omit<FloatingFocusManagerProps, \"children\">;\n /**\n * Position and sizing optional props for the floating component. `top`, `left`, and `position` for floating elements where they aren't positioned with relative to the trigger.\n * `width` and `height` are used to define the size of the floating element.\n *\n */\n top?: number;\n left?: number;\n width?: number;\n height?: number;\n position?: Strategy;\n /**\n * Makes the page unscrollable when the floating component is open.\n */\n lockScroll?: boolean;\n}\n\nconst DefaultFloatingComponent = forwardRef<\n HTMLDivElement,\n FloatingComponentProps\n>(function DefaultFloatingComponent(props, ref) {\n const {\n open,\n top,\n left,\n position,\n width,\n height,\n focusManagerProps,\n lockScroll,\n ...rest\n } = props;\n const style = {\n top,\n left,\n position,\n };\n\n const { themeNext } = useTheme();\n usePreventScroll({ isDisabled: !lockScroll || !open });\n\n const ChosenSaltProvider = themeNext ? SaltProviderNext : SaltProvider;\n\n if (focusManagerProps && open) {\n return (\n <FloatingPortal>\n <ChosenSaltProvider applyClassesTo=\"scope\">\n <FloatingFocusManager {...focusManagerProps}>\n <div style={style} {...rest} ref={ref} />\n </FloatingFocusManager>\n </ChosenSaltProvider>\n </FloatingPortal>\n );\n }\n\n return open ? (\n <FloatingPortal>\n <ChosenSaltProvider applyClassesTo=\"scope\">\n <div style={style} {...rest} ref={ref} />\n </ChosenSaltProvider>\n </FloatingPortal>\n ) : null;\n});\n\nexport interface FloatingComponentContextType {\n Component: typeof DefaultFloatingComponent;\n}\n\nconst FloatingComponentContext = createContext<FloatingComponentContextType>({\n Component: DefaultFloatingComponent,\n});\n\nif (process.env.NODE_ENV !== \"production\") {\n FloatingComponentContext.displayName = \"FloatingComponentContext\";\n}\n\nexport interface FloatingComponentProviderProps\n extends FloatingComponentContextType {\n children: ReactNode;\n}\n\nexport function FloatingComponentProvider(\n props: FloatingComponentProviderProps,\n) {\n const { Component, children } = props;\n const value = useMemo(() => ({ Component }), [Component]);\n\n return (\n <FloatingComponentContext.Provider value={value}>\n {children}\n </FloatingComponentContext.Provider>\n );\n}\n\nexport function useFloatingComponent() {\n return useContext(FloatingComponentContext);\n}\n\nexport interface UseFloatingUIProps\n extends Pick<\n UseFloatingOptions,\n \"placement\" | \"strategy\" | \"open\" | \"onOpenChange\" | \"nodeId\"\n > {\n /**\n * Function to update the default middleware used to extend or replace it\n */\n middleware?: Middleware[];\n}\n\ntype GetMiddleware = (middleware: Middleware[]) => Middleware[];\n\nconst defaultGetMiddleware: GetMiddleware = (defaultMiddleware) =>\n defaultMiddleware;\n\ninterface FloatingPlatformContextType {\n platform: Platform;\n middleware: GetMiddleware;\n animationFrame: boolean;\n}\n\nconst defaultFloatingPlaform: FloatingPlatformContextType = {\n platform,\n middleware: defaultGetMiddleware,\n animationFrame: false,\n};\n\nconst FloatingPlatformContext = createContext<FloatingPlatformContextType>(\n defaultFloatingPlaform,\n);\n\nexport interface FloatingPlatformProviderProps {\n platform?: Platform;\n middleware?: GetMiddleware;\n children: ReactNode;\n animationFrame?: boolean;\n}\n\nexport function FloatingPlatformProvider(props: FloatingPlatformProviderProps) {\n const {\n platform: platformProp,\n middleware,\n animationFrame,\n children,\n } = props;\n\n const floatingPlatformContextValue = useMemo<FloatingPlatformContextType>(\n () => ({\n platform: platformProp ?? platform,\n middleware: middleware ?? defaultGetMiddleware,\n animationFrame: animationFrame || false,\n }),\n [platformProp, middleware, animationFrame],\n );\n\n return (\n <FloatingPlatformContext.Provider value={floatingPlatformContextValue}>\n {children}\n </FloatingPlatformContext.Provider>\n );\n}\n\nexport function useFloatingPlatform() {\n return useContext(FloatingPlatformContext);\n}\n\nexport const DEFAULT_FLOATING_UI_MIDDLEWARE = [\n flip(),\n shift({ limiter: limitShift() }),\n];\n\ntype UseFloatingRefs = ReturnType<typeof useFloating>[\"refs\"];\n\nexport interface UseFloatingUIReturn extends ReturnType<typeof useFloating> {\n reference: UseFloatingRefs[\"setReference\"];\n floating: UseFloatingRefs[\"setFloating\"];\n}\n\nexport function useFloatingUI(props: UseFloatingUIProps): UseFloatingUIReturn {\n const {\n middleware = DEFAULT_FLOATING_UI_MIDDLEWARE,\n open = false,\n onOpenChange,\n ...other\n } = props;\n\n const handleOpenChange: UseFloatingUIProps[\"onOpenChange\"] = (\n open,\n boolean,\n reason,\n ) => {\n update();\n onOpenChange?.(open, boolean, reason);\n };\n\n const {\n platform: contextPlatform,\n middleware: contextMiddleware,\n animationFrame,\n } = useFloatingPlatform();\n\n const { refs, update, ...rest } = useFloating({\n ...other,\n middleware: contextMiddleware(middleware),\n open,\n onOpenChange: handleOpenChange,\n whileElementsMounted: (...args) => {\n const cleanup = autoUpdate(...args, { animationFrame });\n\n return cleanup;\n },\n platform: contextPlatform,\n });\n\n return {\n reference: refs.setReference,\n floating: refs.setFloating,\n refs,\n update,\n ...rest,\n };\n}\n"],"names":["forwardRef","DefaultFloatingComponent","useTheme","usePreventScroll","SaltProviderNext","SaltProvider","FloatingPortal","jsx","FloatingFocusManager","createContext","useMemo","useContext","platform","flip","shift","limitShift","open","useFloating","autoUpdate"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useId.js","sources":["../src/utils/useId.ts"],"sourcesContent":["import * as React from \"react\";\n\n// Workaround for https://github.com/webpack/webpack/issues/14814#issuecomment-1536757985\n// Without `toString()`, downstream library using webpack to re-bundle will error\nconst maybeReactUseId: undefined | (() => string) = (React as any)[\n \"useId\".toString()\n];\n\nlet globalId = BigInt(0);\nfunction useIdLegacy(idOverride?: string): string | undefined {\n const [defaultId, setDefaultId] = React.useState(idOverride);\n const id = idOverride || defaultId;\n React.useEffect(() => {\n if (defaultId == null) {\n setDefaultId(`salt-${++globalId}`);\n }\n }, [defaultId]);\n return id;\n}\n\nexport function useId(idOverride?: string): string | undefined {\n if (maybeReactUseId !== undefined) {\n const reactId = maybeReactUseId();\n return idOverride ?? reactId;\n }\n // `React.useId` is invariant at runtime.\n return useIdLegacy(idOverride);\n}\n\n// Note: Some usages require that an id is returned on first call, not only post-first-render\n// (as with the useEffect solution). This can go away once we totally move to React 18\nexport function useIdMemo(idOverride?: string): string {\n return React.useMemo(() => {\n return idOverride ?? `salt-${++globalId}`;\n }, [idOverride]);\n}\n"],"names":["React"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAIA,MAAM,eAA+C,GAAAA,gBAAA,CACnD,OAAQ,CAAA,QAAA,EACV,CAAA;AAEA,IAAI,QAAA,GAAW,OAAO,CAAC,CAAA;AACvB,SAAS,YAAY,UAAyC,EAAA;AAC5D,EAAA,MAAM,CAAC,SAAW,EAAA,YAAY,CAAI,GAAAA,gBAAA,CAAM,SAAS,UAAU,CAAA;AAC3D,EAAA,MAAM,KAAK,UAAc,IAAA,SAAA;AACzB,EAAAA,gBAAA,CAAM,UAAU,MAAM;AACpB,IAAA,IAAI,aAAa,IAAM,EAAA;AACrB,MAAa,YAAA,CAAA,CAAA,KAAA,EAAQ,EAAE,QAAQ,CAAE,CAAA,CAAA;AAAA;AACnC,GACF,EAAG,CAAC,SAAS,CAAC,CAAA;AACd,EAAO,OAAA,EAAA;AACT;AAEO,SAAS,MAAM,UAAyC,EAAA;AAC7D,EAAA,IAAI,oBAAoB,
|
|
1
|
+
{"version":3,"file":"useId.js","sources":["../src/utils/useId.ts"],"sourcesContent":["import * as React from \"react\";\n\n// Workaround for https://github.com/webpack/webpack/issues/14814#issuecomment-1536757985\n// Without `toString()`, downstream library using webpack to re-bundle will error\nconst maybeReactUseId: undefined | (() => string) = (React as any)[\n \"useId\".toString()\n];\n\nlet globalId = BigInt(0);\nfunction useIdLegacy(idOverride?: string): string | undefined {\n const [defaultId, setDefaultId] = React.useState(idOverride);\n const id = idOverride || defaultId;\n React.useEffect(() => {\n if (defaultId == null) {\n setDefaultId(`salt-${++globalId}`);\n }\n }, [defaultId]);\n return id;\n}\n\nexport function useId(idOverride?: string): string | undefined {\n if (maybeReactUseId !== undefined) {\n const reactId = maybeReactUseId();\n return idOverride ?? reactId;\n }\n // `React.useId` is invariant at runtime.\n return useIdLegacy(idOverride);\n}\n\n// Note: Some usages require that an id is returned on first call, not only post-first-render\n// (as with the useEffect solution). This can go away once we totally move to React 18\nexport function useIdMemo(idOverride?: string): string {\n return React.useMemo(() => {\n return idOverride ?? `salt-${++globalId}`;\n }, [idOverride]);\n}\n"],"names":["React"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAIA,MAAM,eAA+C,GAAAA,gBAAA,CACnD,OAAQ,CAAA,QAAA,EACV,CAAA;AAEA,IAAI,QAAA,GAAW,OAAO,CAAC,CAAA;AACvB,SAAS,YAAY,UAAyC,EAAA;AAC5D,EAAA,MAAM,CAAC,SAAW,EAAA,YAAY,CAAI,GAAAA,gBAAA,CAAM,SAAS,UAAU,CAAA;AAC3D,EAAA,MAAM,KAAK,UAAc,IAAA,SAAA;AACzB,EAAAA,gBAAA,CAAM,UAAU,MAAM;AACpB,IAAA,IAAI,aAAa,IAAM,EAAA;AACrB,MAAa,YAAA,CAAA,CAAA,KAAA,EAAQ,EAAE,QAAQ,CAAE,CAAA,CAAA;AAAA;AACnC,GACF,EAAG,CAAC,SAAS,CAAC,CAAA;AACd,EAAO,OAAA,EAAA;AACT;AAEO,SAAS,MAAM,UAAyC,EAAA;AAC7D,EAAA,IAAI,oBAAoB,MAAW,EAAA;AACjC,IAAA,MAAM,UAAU,eAAgB,EAAA;AAChC,IAAA,OAAO,UAAc,IAAA,OAAA;AAAA;AAGvB,EAAA,OAAO,YAAY,UAAU,CAAA;AAC/B;AAIO,SAAS,UAAU,UAA6B,EAAA;AACrD,EAAO,OAAAA,gBAAA,CAAM,QAAQ,MAAM;AACzB,IAAO,OAAA,UAAA,IAAc,CAAQ,KAAA,EAAA,EAAE,QAAQ,CAAA,CAAA;AAAA,GACzC,EAAG,CAAC,UAAU,CAAC,CAAA;AACjB;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePreventScroll.js","sources":["../src/utils/usePreventScroll.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n/**\n * Taken from https://github.com/adobe/react-spectrum/blob/cc08a8dbc95d3648eee47bc9b8e0ed48448e0da2/packages/%40react-aria/overlays/src/usePreventScroll.ts#L44 but refactored.\n * This hook currently doesn't use `useWindow` because in a desktop environment the main window is only the window they typically want locked.\n * If we need to in the future we can add an option to specify which window should be affected.\n */\n\nimport { createChainedFunction } from \"./createChainedFunction\";\nimport { useIsomorphicLayoutEffect } from \"./useIsomorphicLayoutEffect\";\n\ninterface PreventScrollOptions {\n /** Whether the scroll lock is disabled. */\n isDisabled?: boolean;\n}\n\nconst visualViewport = typeof document !== \"undefined\" && window.visualViewport;\n\n// HTML input types that do not cause the software keyboard to appear.\nconst nonTextInputTypes = new Set([\n \"checkbox\",\n \"radio\",\n \"range\",\n \"color\",\n \"file\",\n \"image\",\n \"button\",\n \"submit\",\n \"reset\",\n]);\n\n// The number of active usePreventScroll calls. Used to determine whether to revert back to the original page style/scroll position\nlet preventScrollCount = 0;\nlet restore: () => void;\n\n/**\n * Prevents scrolling on the document body on mount, and\n * restores it on unmount. Also ensures that content does not\n * shift due to the scrollbars disappearing.\n */\nexport function usePreventScroll(options: PreventScrollOptions = {}) {\n const { isDisabled } = options;\n\n useIsomorphicLayoutEffect(() => {\n if (isDisabled) {\n return;\n }\n\n preventScrollCount++;\n if (preventScrollCount === 1) {\n if (isIOS()) {\n restore = preventScrollMobileSafari();\n } else {\n restore = preventScrollStandard();\n }\n }\n\n return () => {\n preventScrollCount--;\n if (preventScrollCount === 0) {\n restore();\n }\n };\n }, [isDisabled]);\n}\n\n// For most browsers, all we need to do is set `overflow: hidden` on the root element, and\n// add some padding to prevent the page from shifting when the scrollbar is hidden.\nfunction preventScrollStandard() {\n return createChainedFunction(\n setStyle(\n document.documentElement,\n \"paddingRight\",\n `${window.innerWidth - document.documentElement.clientWidth}px`,\n ),\n setStyle(document.documentElement, \"overflow\", \"hidden\"),\n );\n}\n\n// Mobile Safari is a whole different beast. Even with overflow: hidden,\n// it still scrolls the page in many situations:\n//\n// 1. When the bottom toolbar and address bar are collapsed, page scrolling is always allowed.\n// 2. When the keyboard is visible, the viewport does not resize. Instead, the keyboard covers part of\n// it, so it becomes scrollable.\n// 3. When tapping on an input, the page always scrolls so that the input is centered in the visual viewport.\n// This may cause even fixed position elements to scroll off the screen.\n// 4. When using the next/previous buttons in the keyboard to navigate between inputs, the whole page always\n// scrolls, even if the input is inside a nested scrollable element that could be scrolled instead.\n//\n// In order to work around these cases, and prevent scrolling without jankiness, we do a few things:\n//\n// 1. Prevent default on `touchmove` events that are not in a scrollable element. This prevents touch scrolling\n// on the window.\n// 2. Set `overscroll-behavior: contain` on nested scrollable regions so they do not scroll the page when at\n// the top or bottom. Work around a bug where this does not work when the element does not actually overflow\n// by preventing default in a `touchmove` event.\n// 3. Prevent default on `touchend` events on input elements and handle focusing the element ourselves.\n// 4. When focusing an input, apply a transform to trick Safari into thinking the input is at the top\n// of the page, which prevents it from scrolling the page. After the input is focused, scroll the element\n// into view ourselves, without scrolling the whole page.\n// 5. Offset the body by the scroll position using a negative margin and scroll to the top. This should appear the\n// same visually, but makes the actual scroll position always zero. This is required to make all of the\n// above work or Safari will still try to scroll the page when focusing an input.\n// 6. As a last resort, handle window scroll events, and scroll back to the top. This can happen when attempting\n// to navigate to an input with the next/previous buttons that's outside a modal.\nfunction preventScrollMobileSafari() {\n let scrollable: Element;\n let restoreScrollableStyles: () => void;\n const onTouchStart = (e: TouchEvent) => {\n // Store the nearest scrollable parent element from the element that the user touched.\n scrollable = getScrollParent(e.target as Element, true);\n if (\n scrollable === document.documentElement &&\n scrollable === document.body\n ) {\n return;\n }\n\n // Prevent scrolling up when at the top and scrolling down when at the bottom\n // of a nested scrollable area, otherwise mobile Safari will start scrolling\n // the window instead.\n if (\n scrollable instanceof HTMLElement &&\n window.getComputedStyle(scrollable).overscrollBehavior === \"auto\"\n ) {\n restoreScrollableStyles = setStyle(\n scrollable,\n \"overscrollBehavior\",\n \"contain\",\n );\n }\n };\n\n const onTouchMove = (e: TouchEvent) => {\n // Prevent scrolling the window.\n if (\n !scrollable ||\n scrollable === document.documentElement ||\n scrollable === document.body\n ) {\n e.preventDefault();\n return;\n }\n\n // overscroll-behavior should prevent scroll chaining, but currently does not\n // if the element doesn't actually overflow. https://bugs.webkit.org/show_bug.cgi?id=243452\n // This checks that both the width and height do not overflow, otherwise we might\n // block horizontal scrolling too. In that case, adding `touch-action: pan-x` to\n // the element will prevent vertical page scrolling. We can't add that automatically\n // because it must be set before the touchstart event.\n if (\n scrollable.scrollHeight === scrollable.clientHeight &&\n scrollable.scrollWidth === scrollable.clientWidth\n ) {\n e.preventDefault();\n }\n };\n\n const onTouchEnd = () => {\n if (restoreScrollableStyles) {\n restoreScrollableStyles();\n }\n };\n\n const onFocus = (e: FocusEvent) => {\n const target = e.target as HTMLElement;\n if (willOpenKeyboard(target)) {\n setupStyles();\n\n // Apply a transform to trick Safari into thinking the input is at the top of the page\n // so it doesn't try to scroll it into view.\n target.style.transform = \"translateY(-2000px)\";\n requestAnimationFrame(() => {\n target.style.transform = \"\";\n\n // This will have prevented the browser from scrolling the focused element into view,\n // so we need to do this ourselves in a way that doesn't cause the whole page to scroll.\n if (visualViewport) {\n if (visualViewport.height < window.innerHeight) {\n // If the keyboard is already visible, do this after one additional frame\n // to wait for the transform to be removed.\n requestAnimationFrame(() => {\n scrollIntoView(target);\n });\n } else {\n // Otherwise, wait for the visual viewport to resize before scrolling so we can\n // measure the correct position to scroll to.\n visualViewport.addEventListener(\n \"resize\",\n () => scrollIntoView(target),\n { once: true },\n );\n }\n }\n });\n }\n };\n\n let restoreStyles: null | (() => void) = null;\n const setupStyles = () => {\n if (restoreStyles) {\n return;\n }\n\n const onWindowScroll = () => {\n // Last resort. If the window scrolled, scroll it back to the top.\n // It should always be at the top because the body will have a negative margin (see below).\n window.scrollTo(0, 0);\n };\n\n // Record the original scroll position so we can restore it.\n // Then apply a negative margin to the body to offset it by the scroll position. This will\n // enable us to scroll the window to the top, which is required for the rest of this to work.\n const scrollX = window.pageXOffset;\n const scrollY = window.pageYOffset;\n\n restoreStyles = createChainedFunction(\n addEvent(window, \"scroll\", onWindowScroll),\n setStyle(\n document.documentElement,\n \"paddingRight\",\n `${window.innerWidth - document.documentElement.clientWidth}px`,\n ),\n setStyle(document.documentElement, \"overflow\", \"hidden\"),\n setStyle(document.body, \"marginTop\", `-${scrollY}px`),\n () => {\n window.scrollTo(scrollX, scrollY);\n },\n );\n\n // Scroll to the top. The negative margin on the body will make this appear the same.\n window.scrollTo(0, 0);\n };\n\n const removeEvents = createChainedFunction(\n addEvent(document, \"touchstart\", onTouchStart, {\n passive: false,\n capture: true,\n }),\n addEvent(document, \"touchmove\", onTouchMove, {\n passive: false,\n capture: true,\n }),\n addEvent(document, \"touchend\", onTouchEnd, {\n passive: false,\n capture: true,\n }),\n addEvent(document, \"focus\", onFocus, true),\n );\n\n return () => {\n // Restore styles and scroll the page back to where it was.\n restoreScrollableStyles?.();\n restoreStyles?.();\n removeEvents();\n };\n}\n\n// Sets a CSS property on an element, and returns a function to revert it to the previous value.\nfunction setStyle(element: HTMLElement, style: string, value: string) {\n const cur = element.style[style as any];\n element.style[style as any] = value;\n\n return () => {\n element.style[style as any] = cur;\n };\n}\n\n// Adds an event listener to an element, and returns a function to remove it.\nfunction addEvent<K extends keyof GlobalEventHandlersEventMap>(\n target: Document | Window,\n event: K,\n handler: (this: Document | Window, ev: GlobalEventHandlersEventMap[K]) => any,\n options?: boolean | AddEventListenerOptions,\n) {\n // internal function, so it's ok to ignore the difficult to fix type error\n // @ts-ignore\n target.addEventListener(event, handler, options);\n return () => {\n // @ts-ignore\n target.removeEventListener(event, handler, options);\n };\n}\n\nfunction scrollIntoView(target: Element) {\n const root = document.scrollingElement || document.documentElement;\n let nextTarget: Element | null = target;\n while (nextTarget && nextTarget !== root) {\n // Find the parent scrollable element and adjust the scroll position if the target is not already in view.\n const scrollable = getScrollParent(nextTarget);\n if (\n scrollable !== document.documentElement &&\n scrollable !== document.body &&\n scrollable !== nextTarget\n ) {\n const scrollableTop = scrollable.getBoundingClientRect().top;\n const targetTop = nextTarget.getBoundingClientRect().top;\n if (targetTop > scrollableTop + nextTarget.clientHeight) {\n scrollable.scrollTop += targetTop - scrollableTop;\n }\n }\n\n nextTarget = scrollable.parentElement;\n }\n}\n\nfunction willOpenKeyboard(target: Element) {\n return (\n (target instanceof HTMLInputElement &&\n !nonTextInputTypes.has(target.type)) ||\n target instanceof HTMLTextAreaElement ||\n (target instanceof HTMLElement && target.isContentEditable)\n );\n}\n\nfunction isScrollable(\n node: Element | null,\n checkForOverflow?: boolean,\n): boolean {\n if (!node) {\n return false;\n }\n const style = window.getComputedStyle(node);\n let isScrollable = /(auto|scroll)/.test(\n style.overflow + style.overflowX + style.overflowY,\n );\n\n if (isScrollable && checkForOverflow) {\n isScrollable =\n node.scrollHeight !== node.clientHeight ||\n node.scrollWidth !== node.clientWidth;\n }\n\n return isScrollable;\n}\n\nfunction getScrollParent(node: Element, checkForOverflow?: boolean): Element {\n let scrollableNode: Element | null = node;\n if (isScrollable(scrollableNode, checkForOverflow)) {\n scrollableNode = scrollableNode.parentElement;\n }\n\n while (scrollableNode && !isScrollable(scrollableNode, checkForOverflow)) {\n scrollableNode = scrollableNode.parentElement;\n }\n\n return (\n scrollableNode || document.scrollingElement || document.documentElement\n );\n}\n\nfunction testPlatform(re: RegExp) {\n return typeof window !== \"undefined\" && window.navigator != null\n ? re.test(\n // @ts-expect-error userAgentData is only supported in Chrome 90+\n window.navigator.userAgentData?.platform || window.navigator.platform,\n )\n : false;\n}\n\nfunction cached(fn: () => boolean) {\n if (process.env.NODE_ENV === \"test\") {\n return fn;\n }\n\n let res: boolean | null = null;\n return () => {\n if (res == null) {\n res = fn();\n }\n return res;\n };\n}\n\nconst isMac = cached(() => testPlatform(/^Mac/i));\n\nconst isIPhone = cached(() => testPlatform(/^iPhone/i));\n\nconst isIPad = cached(\n () =>\n testPlatform(/^iPad/i) ||\n // iPadOS 13 lies and says it's a Mac, but we can distinguish by detecting touch support.\n (isMac() && navigator.maxTouchPoints > 1),\n);\n\nconst isIOS = cached(() => isIPhone() || isIPad());\n"],"names":["useIsomorphicLayoutEffect","createChainedFunction","isScrollable"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"usePreventScroll.js","sources":["../src/utils/usePreventScroll.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n/**\n * Taken from https://github.com/adobe/react-spectrum/blob/cc08a8dbc95d3648eee47bc9b8e0ed48448e0da2/packages/%40react-aria/overlays/src/usePreventScroll.ts#L44 but refactored.\n * This hook currently doesn't use `useWindow` because in a desktop environment the main window is only the window they typically want locked.\n * If we need to in the future we can add an option to specify which window should be affected.\n */\n\nimport { createChainedFunction } from \"./createChainedFunction\";\nimport { useIsomorphicLayoutEffect } from \"./useIsomorphicLayoutEffect\";\n\ninterface PreventScrollOptions {\n /** Whether the scroll lock is disabled. */\n isDisabled?: boolean;\n}\n\nconst visualViewport = typeof document !== \"undefined\" && window.visualViewport;\n\n// HTML input types that do not cause the software keyboard to appear.\nconst nonTextInputTypes = new Set([\n \"checkbox\",\n \"radio\",\n \"range\",\n \"color\",\n \"file\",\n \"image\",\n \"button\",\n \"submit\",\n \"reset\",\n]);\n\n// The number of active usePreventScroll calls. Used to determine whether to revert back to the original page style/scroll position\nlet preventScrollCount = 0;\nlet restore: () => void;\n\n/**\n * Prevents scrolling on the document body on mount, and\n * restores it on unmount. Also ensures that content does not\n * shift due to the scrollbars disappearing.\n */\nexport function usePreventScroll(options: PreventScrollOptions = {}) {\n const { isDisabled } = options;\n\n useIsomorphicLayoutEffect(() => {\n if (isDisabled) {\n return;\n }\n\n preventScrollCount++;\n if (preventScrollCount === 1) {\n if (isIOS()) {\n restore = preventScrollMobileSafari();\n } else {\n restore = preventScrollStandard();\n }\n }\n\n return () => {\n preventScrollCount--;\n if (preventScrollCount === 0) {\n restore();\n }\n };\n }, [isDisabled]);\n}\n\n// For most browsers, all we need to do is set `overflow: hidden` on the root element, and\n// add some padding to prevent the page from shifting when the scrollbar is hidden.\nfunction preventScrollStandard() {\n return createChainedFunction(\n setStyle(\n document.documentElement,\n \"paddingRight\",\n `${window.innerWidth - document.documentElement.clientWidth}px`,\n ),\n setStyle(document.documentElement, \"overflow\", \"hidden\"),\n );\n}\n\n// Mobile Safari is a whole different beast. Even with overflow: hidden,\n// it still scrolls the page in many situations:\n//\n// 1. When the bottom toolbar and address bar are collapsed, page scrolling is always allowed.\n// 2. When the keyboard is visible, the viewport does not resize. Instead, the keyboard covers part of\n// it, so it becomes scrollable.\n// 3. When tapping on an input, the page always scrolls so that the input is centered in the visual viewport.\n// This may cause even fixed position elements to scroll off the screen.\n// 4. When using the next/previous buttons in the keyboard to navigate between inputs, the whole page always\n// scrolls, even if the input is inside a nested scrollable element that could be scrolled instead.\n//\n// In order to work around these cases, and prevent scrolling without jankiness, we do a few things:\n//\n// 1. Prevent default on `touchmove` events that are not in a scrollable element. This prevents touch scrolling\n// on the window.\n// 2. Set `overscroll-behavior: contain` on nested scrollable regions so they do not scroll the page when at\n// the top or bottom. Work around a bug where this does not work when the element does not actually overflow\n// by preventing default in a `touchmove` event.\n// 3. Prevent default on `touchend` events on input elements and handle focusing the element ourselves.\n// 4. When focusing an input, apply a transform to trick Safari into thinking the input is at the top\n// of the page, which prevents it from scrolling the page. After the input is focused, scroll the element\n// into view ourselves, without scrolling the whole page.\n// 5. Offset the body by the scroll position using a negative margin and scroll to the top. This should appear the\n// same visually, but makes the actual scroll position always zero. This is required to make all of the\n// above work or Safari will still try to scroll the page when focusing an input.\n// 6. As a last resort, handle window scroll events, and scroll back to the top. This can happen when attempting\n// to navigate to an input with the next/previous buttons that's outside a modal.\nfunction preventScrollMobileSafari() {\n let scrollable: Element;\n let restoreScrollableStyles: () => void;\n const onTouchStart = (e: TouchEvent) => {\n // Store the nearest scrollable parent element from the element that the user touched.\n scrollable = getScrollParent(e.target as Element, true);\n if (\n scrollable === document.documentElement &&\n scrollable === document.body\n ) {\n return;\n }\n\n // Prevent scrolling up when at the top and scrolling down when at the bottom\n // of a nested scrollable area, otherwise mobile Safari will start scrolling\n // the window instead.\n if (\n scrollable instanceof HTMLElement &&\n window.getComputedStyle(scrollable).overscrollBehavior === \"auto\"\n ) {\n restoreScrollableStyles = setStyle(\n scrollable,\n \"overscrollBehavior\",\n \"contain\",\n );\n }\n };\n\n const onTouchMove = (e: TouchEvent) => {\n // Prevent scrolling the window.\n if (\n !scrollable ||\n scrollable === document.documentElement ||\n scrollable === document.body\n ) {\n e.preventDefault();\n return;\n }\n\n // overscroll-behavior should prevent scroll chaining, but currently does not\n // if the element doesn't actually overflow. https://bugs.webkit.org/show_bug.cgi?id=243452\n // This checks that both the width and height do not overflow, otherwise we might\n // block horizontal scrolling too. In that case, adding `touch-action: pan-x` to\n // the element will prevent vertical page scrolling. We can't add that automatically\n // because it must be set before the touchstart event.\n if (\n scrollable.scrollHeight === scrollable.clientHeight &&\n scrollable.scrollWidth === scrollable.clientWidth\n ) {\n e.preventDefault();\n }\n };\n\n const onTouchEnd = () => {\n if (restoreScrollableStyles) {\n restoreScrollableStyles();\n }\n };\n\n const onFocus = (e: FocusEvent) => {\n const target = e.target as HTMLElement;\n if (willOpenKeyboard(target)) {\n setupStyles();\n\n // Apply a transform to trick Safari into thinking the input is at the top of the page\n // so it doesn't try to scroll it into view.\n target.style.transform = \"translateY(-2000px)\";\n requestAnimationFrame(() => {\n target.style.transform = \"\";\n\n // This will have prevented the browser from scrolling the focused element into view,\n // so we need to do this ourselves in a way that doesn't cause the whole page to scroll.\n if (visualViewport) {\n if (visualViewport.height < window.innerHeight) {\n // If the keyboard is already visible, do this after one additional frame\n // to wait for the transform to be removed.\n requestAnimationFrame(() => {\n scrollIntoView(target);\n });\n } else {\n // Otherwise, wait for the visual viewport to resize before scrolling so we can\n // measure the correct position to scroll to.\n visualViewport.addEventListener(\n \"resize\",\n () => scrollIntoView(target),\n { once: true },\n );\n }\n }\n });\n }\n };\n\n let restoreStyles: null | (() => void) = null;\n const setupStyles = () => {\n if (restoreStyles) {\n return;\n }\n\n const onWindowScroll = () => {\n // Last resort. If the window scrolled, scroll it back to the top.\n // It should always be at the top because the body will have a negative margin (see below).\n window.scrollTo(0, 0);\n };\n\n // Record the original scroll position so we can restore it.\n // Then apply a negative margin to the body to offset it by the scroll position. This will\n // enable us to scroll the window to the top, which is required for the rest of this to work.\n const scrollX = window.pageXOffset;\n const scrollY = window.pageYOffset;\n\n restoreStyles = createChainedFunction(\n addEvent(window, \"scroll\", onWindowScroll),\n setStyle(\n document.documentElement,\n \"paddingRight\",\n `${window.innerWidth - document.documentElement.clientWidth}px`,\n ),\n setStyle(document.documentElement, \"overflow\", \"hidden\"),\n setStyle(document.body, \"marginTop\", `-${scrollY}px`),\n () => {\n window.scrollTo(scrollX, scrollY);\n },\n );\n\n // Scroll to the top. The negative margin on the body will make this appear the same.\n window.scrollTo(0, 0);\n };\n\n const removeEvents = createChainedFunction(\n addEvent(document, \"touchstart\", onTouchStart, {\n passive: false,\n capture: true,\n }),\n addEvent(document, \"touchmove\", onTouchMove, {\n passive: false,\n capture: true,\n }),\n addEvent(document, \"touchend\", onTouchEnd, {\n passive: false,\n capture: true,\n }),\n addEvent(document, \"focus\", onFocus, true),\n );\n\n return () => {\n // Restore styles and scroll the page back to where it was.\n restoreScrollableStyles?.();\n restoreStyles?.();\n removeEvents();\n };\n}\n\n// Sets a CSS property on an element, and returns a function to revert it to the previous value.\nfunction setStyle(element: HTMLElement, style: string, value: string) {\n const cur = element.style[style as any];\n element.style[style as any] = value;\n\n return () => {\n element.style[style as any] = cur;\n };\n}\n\n// Adds an event listener to an element, and returns a function to remove it.\nfunction addEvent<K extends keyof GlobalEventHandlersEventMap>(\n target: Document | Window,\n event: K,\n handler: (this: Document | Window, ev: GlobalEventHandlersEventMap[K]) => any,\n options?: boolean | AddEventListenerOptions,\n) {\n // internal function, so it's ok to ignore the difficult to fix type error\n // @ts-ignore\n target.addEventListener(event, handler, options);\n return () => {\n // @ts-ignore\n target.removeEventListener(event, handler, options);\n };\n}\n\nfunction scrollIntoView(target: Element) {\n const root = document.scrollingElement || document.documentElement;\n let nextTarget: Element | null = target;\n while (nextTarget && nextTarget !== root) {\n // Find the parent scrollable element and adjust the scroll position if the target is not already in view.\n const scrollable = getScrollParent(nextTarget);\n if (\n scrollable !== document.documentElement &&\n scrollable !== document.body &&\n scrollable !== nextTarget\n ) {\n const scrollableTop = scrollable.getBoundingClientRect().top;\n const targetTop = nextTarget.getBoundingClientRect().top;\n if (targetTop > scrollableTop + nextTarget.clientHeight) {\n scrollable.scrollTop += targetTop - scrollableTop;\n }\n }\n\n nextTarget = scrollable.parentElement;\n }\n}\n\nfunction willOpenKeyboard(target: Element) {\n return (\n (target instanceof HTMLInputElement &&\n !nonTextInputTypes.has(target.type)) ||\n target instanceof HTMLTextAreaElement ||\n (target instanceof HTMLElement && target.isContentEditable)\n );\n}\n\nfunction isScrollable(\n node: Element | null,\n checkForOverflow?: boolean,\n): boolean {\n if (!node) {\n return false;\n }\n const style = window.getComputedStyle(node);\n let isScrollable = /(auto|scroll)/.test(\n style.overflow + style.overflowX + style.overflowY,\n );\n\n if (isScrollable && checkForOverflow) {\n isScrollable =\n node.scrollHeight !== node.clientHeight ||\n node.scrollWidth !== node.clientWidth;\n }\n\n return isScrollable;\n}\n\nfunction getScrollParent(node: Element, checkForOverflow?: boolean): Element {\n let scrollableNode: Element | null = node;\n if (isScrollable(scrollableNode, checkForOverflow)) {\n scrollableNode = scrollableNode.parentElement;\n }\n\n while (scrollableNode && !isScrollable(scrollableNode, checkForOverflow)) {\n scrollableNode = scrollableNode.parentElement;\n }\n\n return (\n scrollableNode || document.scrollingElement || document.documentElement\n );\n}\n\nfunction testPlatform(re: RegExp) {\n return typeof window !== \"undefined\" && window.navigator != null\n ? re.test(\n // @ts-expect-error userAgentData is only supported in Chrome 90+\n window.navigator.userAgentData?.platform || window.navigator.platform,\n )\n : false;\n}\n\nfunction cached(fn: () => boolean) {\n if (process.env.NODE_ENV === \"test\") {\n return fn;\n }\n\n let res: boolean | null = null;\n return () => {\n if (res == null) {\n res = fn();\n }\n return res;\n };\n}\n\nconst isMac = cached(() => testPlatform(/^Mac/i));\n\nconst isIPhone = cached(() => testPlatform(/^iPhone/i));\n\nconst isIPad = cached(\n () =>\n testPlatform(/^iPad/i) ||\n // iPadOS 13 lies and says it's a Mac, but we can distinguish by detecting touch support.\n (isMac() && navigator.maxTouchPoints > 1),\n);\n\nconst isIOS = cached(() => isIPhone() || isIPad());\n"],"names":["useIsomorphicLayoutEffect","createChainedFunction","isScrollable"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useResizeObserver.js","sources":["../src/utils/useResizeObserver.ts"],"sourcesContent":["import { type RefObject, useEffect } from \"react\";\nimport { ownerWindow } from \"./ownerWindow\";\n\nexport interface UseResizeObserverProps {\n ref: RefObject<HTMLElement>;\n onResize: () => void;\n}\n\nexport function useResizeObserver({ ref, onResize }: UseResizeObserverProps) {\n useEffect(() => {\n const element = ref?.current;\n if (!element) return;\n\n const win = ownerWindow(element);\n\n const resizeObserver = new win.ResizeObserver((entries) => {\n requestAnimationFrame(() => {\n if (entries.length === 0) return;\n\n onResize();\n });\n });\n resizeObserver.observe(element);\n\n return () => {\n if (element) {\n resizeObserver.unobserve(element);\n }\n };\n }, [ref, onResize]);\n}\n"],"names":["useEffect","ownerWindow"],"mappings":";;;;;AAQO,SAAS,iBAAkB,CAAA,EAAE,GAAK,EAAA,QAAA,EAAoC,EAAA;AAC3E,EAAAA,eAAA,CAAU,MAAM;AACd,IAAA,MAAM,UAAU,GAAK,IAAA,IAAA,GAAA,
|
|
1
|
+
{"version":3,"file":"useResizeObserver.js","sources":["../src/utils/useResizeObserver.ts"],"sourcesContent":["import { type RefObject, useEffect } from \"react\";\nimport { ownerWindow } from \"./ownerWindow\";\n\nexport interface UseResizeObserverProps {\n ref: RefObject<HTMLElement>;\n onResize: () => void;\n}\n\nexport function useResizeObserver({ ref, onResize }: UseResizeObserverProps) {\n useEffect(() => {\n const element = ref?.current;\n if (!element) return;\n\n const win = ownerWindow(element);\n\n const resizeObserver = new win.ResizeObserver((entries) => {\n requestAnimationFrame(() => {\n if (entries.length === 0) return;\n\n onResize();\n });\n });\n resizeObserver.observe(element);\n\n return () => {\n if (element) {\n resizeObserver.unobserve(element);\n }\n };\n }, [ref, onResize]);\n}\n"],"names":["useEffect","ownerWindow"],"mappings":";;;;;AAQO,SAAS,iBAAkB,CAAA,EAAE,GAAK,EAAA,QAAA,EAAoC,EAAA;AAC3E,EAAAA,eAAA,CAAU,MAAM;AACd,IAAA,MAAM,UAAU,GAAK,IAAA,IAAA,GAAA,MAAA,GAAA,GAAA,CAAA,OAAA;AACrB,IAAA,IAAI,CAAC,OAAS,EAAA;AAEd,IAAM,MAAA,GAAA,GAAMC,wBAAY,OAAO,CAAA;AAE/B,IAAA,MAAM,cAAiB,GAAA,IAAI,GAAI,CAAA,cAAA,CAAe,CAAC,OAAY,KAAA;AACzD,MAAA,qBAAA,CAAsB,MAAM;AAC1B,QAAI,IAAA,OAAA,CAAQ,WAAW,CAAG,EAAA;AAE1B,QAAS,QAAA,EAAA;AAAA,OACV,CAAA;AAAA,KACF,CAAA;AACD,IAAA,cAAA,CAAe,QAAQ,OAAO,CAAA;AAE9B,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,OAAS,EAAA;AACX,QAAA,cAAA,CAAe,UAAU,OAAO,CAAA;AAAA;AAClC,KACF;AAAA,GACC,EAAA,CAAC,GAAK,EAAA,QAAQ,CAAC,CAAA;AACpB;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useResponsiveProp.js","sources":["../src/utils/useResponsiveProp.ts"],"sourcesContent":["import type { Breakpoints } from \"../breakpoints\";\nimport { useBreakpoints } from \"../salt-provider\";\nimport { useViewport } from \"../viewport\";\n\ntype BreakpointProp<T> = {\n [K in keyof Breakpoints]?: T;\n};\n\nexport type ResponsiveProp<T> = T | BreakpointProp<T>;\n\nexport const getCurrentBreakpoint = (\n breakpoints: Breakpoints,\n width: number,\n) => {\n const breakpointList = Object.entries(breakpoints).sort(\n ([, a], [, b]) => a - b,\n );\n const [currentBreakpoint] = (\n breakpointList as [keyof Breakpoints, number][]\n ).reduce(\n (acc, val) => {\n const [, accWidth] = acc;\n const [breakpoint, breakpointWidth] = val;\n if (breakpointWidth <= width && breakpointWidth > accWidth) {\n return [breakpoint, breakpointWidth];\n }\n return acc;\n },\n breakpointList[0] as [keyof Breakpoints, number],\n );\n\n return currentBreakpoint;\n};\n\nexport const useCurrentBreakpoint = () => {\n const viewport = useViewport();\n\n const breakpoints = useBreakpoints();\n\n return getCurrentBreakpoint(breakpoints, viewport);\n};\n\nexport const useOrderedBreakpoints = () => {\n const breakpoints = useBreakpoints();\n\n return Object.entries(breakpoints)\n .sort(([, a], [, b]) => a - b)\n .map(([key]) => key);\n};\n\nconst isObject = <T>(\n value: T,\n): value is Record<string | number | symbol, any> => {\n const type = typeof value;\n return value !== null && (type === \"object\" || type === \"function\");\n};\n\nconst hasBreakpointValues = <T>(\n value: ResponsiveProp<T>,\n breakpoints: Breakpoints,\n): value is BreakpointProp<T> => {\n return (\n isObject(value) && Object.keys(value).every((key) => key in breakpoints)\n );\n};\n\nconst getResponsiveValue = <T>(\n breakpointValues: BreakpointProp<T>,\n breakpoints: Breakpoints,\n viewport: keyof Breakpoints,\n defaultValue: T,\n) => {\n return Object.entries(breakpointValues).reduce<[number, T]>(\n (acc, val) => {\n const [accWidth] = acc;\n const [breakpoint, breakpointValue] = val;\n\n const breakpointWidth =\n breakpoints[breakpoint as keyof typeof breakpoints];\n\n if (\n breakpointWidth >= accWidth &&\n breakpointWidth <= breakpoints[viewport]\n ) {\n return [breakpointWidth, breakpointValue];\n }\n\n return acc;\n },\n [0, defaultValue],\n )[1];\n};\n\nexport const useResponsiveProp = <T>(\n value: ResponsiveProp<T>,\n defaultValue: T,\n) => {\n const breakpoints = useBreakpoints();\n const viewport = useViewport();\n // return early if the values are the same\n if (value === defaultValue) return defaultValue;\n\n const currentViewport = getCurrentBreakpoint(breakpoints, viewport);\n if (hasBreakpointValues(value, breakpoints)) {\n return getResponsiveValue(\n value,\n breakpoints,\n currentViewport,\n defaultValue,\n );\n }\n return value;\n};\n\nfunction isBreakpointProp<T>(\n value: ResponsiveProp<T>,\n): value is BreakpointProp<T> {\n return typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function resolveResponsiveValue<Value>(\n value: ResponsiveProp<Value>,\n matchedBreakpoints: (keyof Breakpoints)[],\n) {\n if (value && isBreakpointProp(value)) {\n for (const breakpoint of matchedBreakpoints) {\n if (value[breakpoint] != null) {\n return value[breakpoint];\n }\n }\n return undefined;\n }\n return value;\n}\n"],"names":["useViewport","useBreakpoints"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"useResponsiveProp.js","sources":["../src/utils/useResponsiveProp.ts"],"sourcesContent":["import type { Breakpoints } from \"../breakpoints\";\nimport { useBreakpoints } from \"../salt-provider\";\nimport { useViewport } from \"../viewport\";\n\ntype BreakpointProp<T> = {\n [K in keyof Breakpoints]?: T;\n};\n\nexport type ResponsiveProp<T> = T | BreakpointProp<T>;\n\nexport const getCurrentBreakpoint = (\n breakpoints: Breakpoints,\n width: number,\n) => {\n const breakpointList = Object.entries(breakpoints).sort(\n ([, a], [, b]) => a - b,\n );\n const [currentBreakpoint] = (\n breakpointList as [keyof Breakpoints, number][]\n ).reduce(\n (acc, val) => {\n const [, accWidth] = acc;\n const [breakpoint, breakpointWidth] = val;\n if (breakpointWidth <= width && breakpointWidth > accWidth) {\n return [breakpoint, breakpointWidth];\n }\n return acc;\n },\n breakpointList[0] as [keyof Breakpoints, number],\n );\n\n return currentBreakpoint;\n};\n\nexport const useCurrentBreakpoint = () => {\n const viewport = useViewport();\n\n const breakpoints = useBreakpoints();\n\n return getCurrentBreakpoint(breakpoints, viewport);\n};\n\nexport const useOrderedBreakpoints = () => {\n const breakpoints = useBreakpoints();\n\n return Object.entries(breakpoints)\n .sort(([, a], [, b]) => a - b)\n .map(([key]) => key);\n};\n\nconst isObject = <T>(\n value: T,\n): value is Record<string | number | symbol, any> => {\n const type = typeof value;\n return value !== null && (type === \"object\" || type === \"function\");\n};\n\nconst hasBreakpointValues = <T>(\n value: ResponsiveProp<T>,\n breakpoints: Breakpoints,\n): value is BreakpointProp<T> => {\n return (\n isObject(value) && Object.keys(value).every((key) => key in breakpoints)\n );\n};\n\nconst getResponsiveValue = <T>(\n breakpointValues: BreakpointProp<T>,\n breakpoints: Breakpoints,\n viewport: keyof Breakpoints,\n defaultValue: T,\n) => {\n return Object.entries(breakpointValues).reduce<[number, T]>(\n (acc, val) => {\n const [accWidth] = acc;\n const [breakpoint, breakpointValue] = val;\n\n const breakpointWidth =\n breakpoints[breakpoint as keyof typeof breakpoints];\n\n if (\n breakpointWidth >= accWidth &&\n breakpointWidth <= breakpoints[viewport]\n ) {\n return [breakpointWidth, breakpointValue];\n }\n\n return acc;\n },\n [0, defaultValue],\n )[1];\n};\n\nexport const useResponsiveProp = <T>(\n value: ResponsiveProp<T>,\n defaultValue: T,\n) => {\n const breakpoints = useBreakpoints();\n const viewport = useViewport();\n // return early if the values are the same\n if (value === defaultValue) return defaultValue;\n\n const currentViewport = getCurrentBreakpoint(breakpoints, viewport);\n if (hasBreakpointValues(value, breakpoints)) {\n return getResponsiveValue(\n value,\n breakpoints,\n currentViewport,\n defaultValue,\n );\n }\n return value;\n};\n\nfunction isBreakpointProp<T>(\n value: ResponsiveProp<T>,\n): value is BreakpointProp<T> {\n return typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function resolveResponsiveValue<Value>(\n value: ResponsiveProp<Value>,\n matchedBreakpoints: (keyof Breakpoints)[],\n) {\n if (value && isBreakpointProp(value)) {\n for (const breakpoint of matchedBreakpoints) {\n if (value[breakpoint] != null) {\n return value[breakpoint];\n }\n }\n return undefined;\n }\n return value;\n}\n"],"names":["useViewport","useBreakpoints"],"mappings":";;;;;AAUa,MAAA,oBAAA,GAAuB,CAClC,WAAA,EACA,KACG,KAAA;AACH,EAAA,MAAM,cAAiB,GAAA,MAAA,CAAO,OAAQ,CAAA,WAAW,CAAE,CAAA,IAAA;AAAA,IACjD,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAA,KAAM,CAAI,GAAA;AAAA,GACxB;AACA,EAAM,MAAA,CAAC,iBAAiB,CAAA,GACtB,cACA,CAAA,MAAA;AAAA,IACA,CAAC,KAAK,GAAQ,KAAA;AACZ,MAAM,MAAA,GAAG,QAAQ,CAAI,GAAA,GAAA;AACrB,MAAM,MAAA,CAAC,UAAY,EAAA,eAAe,CAAI,GAAA,GAAA;AACtC,MAAI,IAAA,eAAA,IAAmB,KAAS,IAAA,eAAA,GAAkB,QAAU,EAAA;AAC1D,QAAO,OAAA,CAAC,YAAY,eAAe,CAAA;AAAA;AAErC,MAAO,OAAA,GAAA;AAAA,KACT;AAAA,IACA,eAAe,CAAC;AAAA,GAClB;AAEA,EAAO,OAAA,iBAAA;AACT;AAEO,MAAM,uBAAuB,MAAM;AACxC,EAAA,MAAM,WAAWA,4BAAY,EAAA;AAE7B,EAAA,MAAM,cAAcC,2BAAe,EAAA;AAEnC,EAAO,OAAA,oBAAA,CAAqB,aAAa,QAAQ,CAAA;AACnD;AAEO,MAAM,wBAAwB,MAAM;AACzC,EAAA,MAAM,cAAcA,2BAAe,EAAA;AAEnC,EAAO,OAAA,MAAA,CAAO,QAAQ,WAAW,CAAA,CAC9B,KAAK,CAAC,GAAG,CAAC,CAAG,EAAA,GAAG,CAAC,CAAA,KAAM,IAAI,CAAC,CAAA,CAC5B,IAAI,CAAC,CAAC,GAAG,CAAA,KAAM,GAAG,CAAA;AACvB;AAEA,MAAM,QAAA,GAAW,CACf,KACmD,KAAA;AACnD,EAAA,MAAM,OAAO,OAAO,KAAA;AACpB,EAAA,OAAO,KAAU,KAAA,IAAA,KAAS,IAAS,KAAA,QAAA,IAAY,IAAS,KAAA,UAAA,CAAA;AAC1D,CAAA;AAEA,MAAM,mBAAA,GAAsB,CAC1B,KAAA,EACA,WAC+B,KAAA;AAC/B,EACE,OAAA,QAAA,CAAS,KAAK,CAAA,IAAK,MAAO,CAAA,IAAA,CAAK,KAAK,CAAA,CAAE,KAAM,CAAA,CAAC,GAAQ,KAAA,GAAA,IAAO,WAAW,CAAA;AAE3E,CAAA;AAEA,MAAM,kBAAqB,GAAA,CACzB,gBACA,EAAA,WAAA,EACA,UACA,YACG,KAAA;AACH,EAAO,OAAA,MAAA,CAAO,OAAQ,CAAA,gBAAgB,CAAE,CAAA,MAAA;AAAA,IACtC,CAAC,KAAK,GAAQ,KAAA;AACZ,MAAM,MAAA,CAAC,QAAQ,CAAI,GAAA,GAAA;AACnB,MAAM,MAAA,CAAC,UAAY,EAAA,eAAe,CAAI,GAAA,GAAA;AAEtC,MAAM,MAAA,eAAA,GACJ,YAAY,UAAsC,CAAA;AAEpD,MAAA,IACE,eAAmB,IAAA,QAAA,IACnB,eAAmB,IAAA,WAAA,CAAY,QAAQ,CACvC,EAAA;AACA,QAAO,OAAA,CAAC,iBAAiB,eAAe,CAAA;AAAA;AAG1C,MAAO,OAAA,GAAA;AAAA,KACT;AAAA,IACA,CAAC,GAAG,YAAY;AAAA,IAChB,CAAC,CAAA;AACL,CAAA;AAEa,MAAA,iBAAA,GAAoB,CAC/B,KAAA,EACA,YACG,KAAA;AACH,EAAA,MAAM,cAAcA,2BAAe,EAAA;AACnC,EAAA,MAAM,WAAWD,4BAAY,EAAA;AAE7B,EAAI,IAAA,KAAA,KAAU,cAAqB,OAAA,YAAA;AAEnC,EAAM,MAAA,eAAA,GAAkB,oBAAqB,CAAA,WAAA,EAAa,QAAQ,CAAA;AAClE,EAAI,IAAA,mBAAA,CAAoB,KAAO,EAAA,WAAW,CAAG,EAAA;AAC3C,IAAO,OAAA,kBAAA;AAAA,MACL,KAAA;AAAA,MACA,WAAA;AAAA,MACA,eAAA;AAAA,MACA;AAAA,KACF;AAAA;AAEF,EAAO,OAAA,KAAA;AACT;AAEA,SAAS,iBACP,KAC4B,EAAA;AAC5B,EAAA,OAAO,OAAO,KAAU,KAAA,QAAA,IAAY,CAAC,KAAA,CAAM,QAAQ,KAAK,CAAA;AAC1D;AAEgB,SAAA,sBAAA,CACd,OACA,kBACA,EAAA;AACA,EAAI,IAAA,KAAA,IAAS,gBAAiB,CAAA,KAAK,CAAG,EAAA;AACpC,IAAA,KAAA,MAAW,cAAc,kBAAoB,EAAA;AAC3C,MAAI,IAAA,KAAA,CAAM,UAAU,CAAA,IAAK,IAAM,EAAA;AAC7B,QAAA,OAAO,MAAM,UAAU,CAAA;AAAA;AACzB;AAEF,IAAO,OAAA,MAAA;AAAA;AAET,EAAO,OAAA,KAAA;AACT;;;;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Accordion.js","sources":["../src/accordion/Accordion.tsx"],"sourcesContent":["import { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n type SyntheticEvent,\n forwardRef,\n useState,\n} from \"react\";\nimport { makePrefixer, useControlled, useId } from \"../utils\";\nimport accordionCss from \"./Accordion.css\";\nimport { AccordionContext } from \"./AccordionContext\";\nexport interface AccordionProps\n extends Omit<ComponentPropsWithoutRef<\"div\">, \"onToggle\"> {\n /**\n * AccordionGroup value.\n */\n value: string;\n /**\n * Whether the accordion is expanded.\n */\n expanded?: boolean;\n /**\n * Whether the accordion is expanded by default.\n */\n defaultExpanded?: boolean;\n /**\n * Side to align the Accordion's indicator. Defaults to `left`.\n */\n indicatorSide?: \"left\" | \"right\";\n /**\n * Callback fired when the accordion is toggled.\n */\n onToggle?: (event: SyntheticEvent<HTMLButtonElement>) => void;\n /**\n * Whether the accordion is disabled.\n */\n disabled?: boolean;\n /**\n * The status of the accordion.\n */\n status?: \"error\" | \"warning\" | \"success\";\n}\n\nconst withBaseName = makePrefixer(\"saltAccordion\");\n\nexport const Accordion = forwardRef<HTMLDivElement, AccordionProps>(\n function Accordion(props, ref) {\n const {\n className,\n defaultExpanded,\n expanded: expandedProp,\n disabled,\n indicatorSide = \"left\",\n id: idProp,\n onToggle,\n status,\n value,\n ...rest\n } = props;\n\n const id = useId(idProp);\n const [headerId, setHeaderId] = useState(`${id}-header`);\n const [panelId, setPanelId] = useState(`${id}-panel`);\n\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-accordion\",\n css: accordionCss,\n window: targetWindow,\n });\n\n const [expanded, setExpanded] = useControlled({\n controlled: expandedProp,\n default: Boolean(defaultExpanded),\n name: \"Accordion\",\n state: \"expanded\",\n });\n\n const toggle = (event: SyntheticEvent<HTMLButtonElement>) => {\n setExpanded((prev) => !prev);\n onToggle?.(event);\n };\n\n return (\n <AccordionContext.Provider\n value={{\n value,\n toggle,\n expanded,\n indicatorSide,\n disabled: Boolean(disabled),\n headerId,\n setHeaderId,\n panelId,\n setPanelId,\n status,\n }}\n >\n <div\n ref={ref}\n className={clsx(\n withBaseName(),\n {\n [withBaseName(status ?? \"\")]: status,\n [withBaseName(\"disabled\")]: disabled,\n },\n className,\n )}\n {...rest}\n />\n </AccordionContext.Provider>\n );\n },\n);\n"],"names":["Accordion","accordionCss"],"mappings":";;;;;;;;;;;;;;AA4CA,MAAM,YAAA,GAAe,aAAa,eAAe,CAAA;AAE1C,MAAM,SAAY,GAAA,UAAA;AAAA,EACvB,SAASA,UAAU,CAAA,KAAA,EAAO,GAAK,EAAA;AAC7B,IAAM,MAAA;AAAA,MACJ,SAAA;AAAA,MACA,eAAA;AAAA,MACA,QAAU,EAAA,YAAA;AAAA,MACV,QAAA;AAAA,MACA,aAAgB,GAAA,MAAA;AAAA,MAChB,EAAI,EAAA,MAAA;AAAA,MACJ,QAAA;AAAA,MACA,MAAA;AAAA,MACA,KAAA;AAAA,MACA,GAAG;AAAA,KACD,GAAA,KAAA;AAEJ,IAAM,MAAA,EAAA,GAAK,MAAM,MAAM,CAAA;AACvB,IAAA,MAAM,CAAC,QAAU,EAAA,WAAW,IAAI,QAAS,CAAA,CAAA,EAAG,EAAE,CAAS,OAAA,CAAA,CAAA;AACvD,IAAA,MAAM,CAAC,OAAS,EAAA,UAAU,IAAI,QAAS,CAAA,CAAA,EAAG,EAAE,CAAQ,MAAA,CAAA,CAAA;AAEpD,IAAA,MAAM,eAAe,SAAU,EAAA;AAC/B,IAAyB,wBAAA,CAAA;AAAA,MACvB,MAAQ,EAAA,gBAAA;AAAA,MACR,GAAK,EAAAC,QAAA;AAAA,MACL,MAAQ,EAAA;AAAA,KACT,CAAA;AAED,IAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,aAAc,CAAA;AAAA,MAC5C,UAAY,EAAA,YAAA;AAAA,MACZ,OAAA,EAAS,QAAQ,eAAe,CAAA;AAAA,MAChC,IAAM,EAAA,WAAA;AAAA,MACN,KAAO,EAAA;AAAA,KACR,CAAA;AAED,IAAM,MAAA,MAAA,GAAS,CAAC,KAA6C,KAAA;AAC3D,MAAY,WAAA,CAAA,CAAC,IAAS,KAAA,CAAC,IAAI,CAAA;AAC3B,MAAW,QAAA,IAAA,IAAA,GAAA,
|
|
1
|
+
{"version":3,"file":"Accordion.js","sources":["../src/accordion/Accordion.tsx"],"sourcesContent":["import { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n type SyntheticEvent,\n forwardRef,\n useState,\n} from \"react\";\nimport { makePrefixer, useControlled, useId } from \"../utils\";\nimport accordionCss from \"./Accordion.css\";\nimport { AccordionContext } from \"./AccordionContext\";\nexport interface AccordionProps\n extends Omit<ComponentPropsWithoutRef<\"div\">, \"onToggle\"> {\n /**\n * AccordionGroup value.\n */\n value: string;\n /**\n * Whether the accordion is expanded.\n */\n expanded?: boolean;\n /**\n * Whether the accordion is expanded by default.\n */\n defaultExpanded?: boolean;\n /**\n * Side to align the Accordion's indicator. Defaults to `left`.\n */\n indicatorSide?: \"left\" | \"right\";\n /**\n * Callback fired when the accordion is toggled.\n */\n onToggle?: (event: SyntheticEvent<HTMLButtonElement>) => void;\n /**\n * Whether the accordion is disabled.\n */\n disabled?: boolean;\n /**\n * The status of the accordion.\n */\n status?: \"error\" | \"warning\" | \"success\";\n}\n\nconst withBaseName = makePrefixer(\"saltAccordion\");\n\nexport const Accordion = forwardRef<HTMLDivElement, AccordionProps>(\n function Accordion(props, ref) {\n const {\n className,\n defaultExpanded,\n expanded: expandedProp,\n disabled,\n indicatorSide = \"left\",\n id: idProp,\n onToggle,\n status,\n value,\n ...rest\n } = props;\n\n const id = useId(idProp);\n const [headerId, setHeaderId] = useState(`${id}-header`);\n const [panelId, setPanelId] = useState(`${id}-panel`);\n\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-accordion\",\n css: accordionCss,\n window: targetWindow,\n });\n\n const [expanded, setExpanded] = useControlled({\n controlled: expandedProp,\n default: Boolean(defaultExpanded),\n name: \"Accordion\",\n state: \"expanded\",\n });\n\n const toggle = (event: SyntheticEvent<HTMLButtonElement>) => {\n setExpanded((prev) => !prev);\n onToggle?.(event);\n };\n\n return (\n <AccordionContext.Provider\n value={{\n value,\n toggle,\n expanded,\n indicatorSide,\n disabled: Boolean(disabled),\n headerId,\n setHeaderId,\n panelId,\n setPanelId,\n status,\n }}\n >\n <div\n ref={ref}\n className={clsx(\n withBaseName(),\n {\n [withBaseName(status ?? \"\")]: status,\n [withBaseName(\"disabled\")]: disabled,\n },\n className,\n )}\n {...rest}\n />\n </AccordionContext.Provider>\n );\n },\n);\n"],"names":["Accordion","accordionCss"],"mappings":";;;;;;;;;;;;;;AA4CA,MAAM,YAAA,GAAe,aAAa,eAAe,CAAA;AAE1C,MAAM,SAAY,GAAA,UAAA;AAAA,EACvB,SAASA,UAAU,CAAA,KAAA,EAAO,GAAK,EAAA;AAC7B,IAAM,MAAA;AAAA,MACJ,SAAA;AAAA,MACA,eAAA;AAAA,MACA,QAAU,EAAA,YAAA;AAAA,MACV,QAAA;AAAA,MACA,aAAgB,GAAA,MAAA;AAAA,MAChB,EAAI,EAAA,MAAA;AAAA,MACJ,QAAA;AAAA,MACA,MAAA;AAAA,MACA,KAAA;AAAA,MACA,GAAG;AAAA,KACD,GAAA,KAAA;AAEJ,IAAM,MAAA,EAAA,GAAK,MAAM,MAAM,CAAA;AACvB,IAAA,MAAM,CAAC,QAAU,EAAA,WAAW,IAAI,QAAS,CAAA,CAAA,EAAG,EAAE,CAAS,OAAA,CAAA,CAAA;AACvD,IAAA,MAAM,CAAC,OAAS,EAAA,UAAU,IAAI,QAAS,CAAA,CAAA,EAAG,EAAE,CAAQ,MAAA,CAAA,CAAA;AAEpD,IAAA,MAAM,eAAe,SAAU,EAAA;AAC/B,IAAyB,wBAAA,CAAA;AAAA,MACvB,MAAQ,EAAA,gBAAA;AAAA,MACR,GAAK,EAAAC,QAAA;AAAA,MACL,MAAQ,EAAA;AAAA,KACT,CAAA;AAED,IAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,aAAc,CAAA;AAAA,MAC5C,UAAY,EAAA,YAAA;AAAA,MACZ,OAAA,EAAS,QAAQ,eAAe,CAAA;AAAA,MAChC,IAAM,EAAA,WAAA;AAAA,MACN,KAAO,EAAA;AAAA,KACR,CAAA;AAED,IAAM,MAAA,MAAA,GAAS,CAAC,KAA6C,KAAA;AAC3D,MAAY,WAAA,CAAA,CAAC,IAAS,KAAA,CAAC,IAAI,CAAA;AAC3B,MAAW,QAAA,IAAA,IAAA,GAAA,MAAA,GAAA,QAAA,CAAA,KAAA,CAAA;AAAA,KACb;AAEA,IACE,uBAAA,GAAA;AAAA,MAAC,gBAAiB,CAAA,QAAA;AAAA,MAAjB;AAAA,QACC,KAAO,EAAA;AAAA,UACL,KAAA;AAAA,UACA,MAAA;AAAA,UACA,QAAA;AAAA,UACA,aAAA;AAAA,UACA,QAAA,EAAU,QAAQ,QAAQ,CAAA;AAAA,UAC1B,QAAA;AAAA,UACA,WAAA;AAAA,UACA,OAAA;AAAA,UACA,UAAA;AAAA,UACA;AAAA,SACF;AAAA,QAEA,QAAA,kBAAA,GAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,GAAA;AAAA,YACA,SAAW,EAAA,IAAA;AAAA,cACT,YAAa,EAAA;AAAA,cACb;AAAA,gBACE,CAAC,YAAA,CAAa,MAAU,IAAA,EAAE,CAAC,GAAG,MAAA;AAAA,gBAC9B,CAAC,YAAA,CAAa,UAAU,CAAC,GAAG;AAAA,eAC9B;AAAA,cACA;AAAA,aACF;AAAA,YACC,GAAG;AAAA;AAAA;AACN;AAAA,KACF;AAAA;AAGN;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccordionContext.js","sources":["../src/accordion/AccordionContext.ts"],"sourcesContent":["import { type SyntheticEvent, useContext } from \"react\";\nimport { createContext } from \"../utils\";\n\nexport interface AccordionContextValue {\n value: string;\n expanded: boolean;\n toggle: (event: SyntheticEvent<HTMLButtonElement>) => void;\n disabled: boolean;\n indicatorSide: \"left\" | \"right\";\n headerId: string;\n setHeaderId: (id: string) => void;\n panelId: string;\n setPanelId: (id: string) => void;\n status?: \"error\" | \"warning\" | \"success\";\n}\n\nexport const AccordionContext = createContext<AccordionContextValue>(\n \"AccordionContext\",\n {\n value: \"\",\n expanded: false,\n toggle: () => undefined,\n disabled: false,\n indicatorSide: \"left\",\n headerId: \"\",\n setHeaderId: () => undefined,\n panelId: \"\",\n setPanelId: () => undefined,\n },\n);\n\nexport function useAccordion() {\n return useContext(AccordionContext);\n}\n"],"names":[],"mappings":";;;;;;;;;AAgBO,MAAM,gBAAmB,GAAA,aAAA;AAAA,EAC9B,kBAAA;AAAA,EACA;AAAA,IACE,KAAO,EAAA,EAAA;AAAA,IACP,QAAU,EAAA,KAAA;AAAA,IACV,QAAQ,MAAM,
|
|
1
|
+
{"version":3,"file":"AccordionContext.js","sources":["../src/accordion/AccordionContext.ts"],"sourcesContent":["import { type SyntheticEvent, useContext } from \"react\";\nimport { createContext } from \"../utils\";\n\nexport interface AccordionContextValue {\n value: string;\n expanded: boolean;\n toggle: (event: SyntheticEvent<HTMLButtonElement>) => void;\n disabled: boolean;\n indicatorSide: \"left\" | \"right\";\n headerId: string;\n setHeaderId: (id: string) => void;\n panelId: string;\n setPanelId: (id: string) => void;\n status?: \"error\" | \"warning\" | \"success\";\n}\n\nexport const AccordionContext = createContext<AccordionContextValue>(\n \"AccordionContext\",\n {\n value: \"\",\n expanded: false,\n toggle: () => undefined,\n disabled: false,\n indicatorSide: \"left\",\n headerId: \"\",\n setHeaderId: () => undefined,\n panelId: \"\",\n setPanelId: () => undefined,\n },\n);\n\nexport function useAccordion() {\n return useContext(AccordionContext);\n}\n"],"names":[],"mappings":";;;;;;;;;AAgBO,MAAM,gBAAmB,GAAA,aAAA;AAAA,EAC9B,kBAAA;AAAA,EACA;AAAA,IACE,KAAO,EAAA,EAAA;AAAA,IACP,QAAU,EAAA,KAAA;AAAA,IACV,QAAQ,MAAM,MAAA;AAAA,IACd,QAAU,EAAA,KAAA;AAAA,IACV,aAAe,EAAA,MAAA;AAAA,IACf,QAAU,EAAA,EAAA;AAAA,IACV,aAAa,MAAM,MAAA;AAAA,IACnB,OAAS,EAAA,EAAA;AAAA,IACT,YAAY,MAAM;AAAA;AAEtB;AAEO,SAAS,YAAe,GAAA;AAC7B,EAAA,OAAO,WAAW,gBAAgB,CAAA;AACpC;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccordionHeader.js","sources":["../src/accordion/AccordionHeader.tsx"],"sourcesContent":["import { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n type MouseEvent,\n type ReactNode,\n forwardRef,\n} from \"react\";\nimport { useIcon } from \"../semantic-icon-provider\";\nimport { StatusIndicator } from \"../status-indicator\";\nimport { makePrefixer, useIsomorphicLayoutEffect } from \"../utils\";\n\nimport { useAccordion } from \"./AccordionContext\";\nimport accordionHeaderCss from \"./AccordionHeader.css\";\n\nexport interface AccordionHeaderProps\n extends ComponentPropsWithoutRef<\"button\"> {\n /**\n * The content of the Accordion Header\n */\n children?: ReactNode;\n}\n\nconst withBaseName = makePrefixer(\"saltAccordionHeader\");\n\nfunction ExpansionIcon({ expanded }: { expanded: boolean }) {\n const { CollapseIcon, ExpandIcon } = useIcon();\n if (expanded) {\n return <CollapseIcon aria-hidden className={withBaseName(\"icon\")} />;\n }\n\n return <ExpandIcon aria-hidden className={withBaseName(\"icon\")} />;\n}\n\nexport const AccordionHeader = forwardRef<\n HTMLButtonElement,\n AccordionHeaderProps\n>(function AccordionHeader(props, ref) {\n const { children, className, onClick, id, ...rest } = props;\n const {\n value,\n expanded,\n toggle,\n indicatorSide,\n disabled,\n headerId,\n panelId,\n setHeaderId,\n status,\n } = useAccordion();\n\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-accordion-header\",\n css: accordionHeaderCss,\n window: targetWindow,\n });\n\n const handleClick = (event: MouseEvent<HTMLButtonElement>) => {\n toggle(event);\n onClick?.(event);\n };\n\n useIsomorphicLayoutEffect(() => {\n if (id) {\n setHeaderId(id);\n }\n }, [id, setHeaderId]);\n\n return (\n <button\n ref={ref}\n className={clsx(\n withBaseName(),\n { [withBaseName(status ?? \"\")]: status },\n className,\n )}\n disabled={disabled}\n onClick={handleClick}\n aria-expanded={expanded}\n id={headerId}\n aria-controls={panelId}\n value={value}\n type=\"button\"\n {...rest}\n >\n {indicatorSide === \"left\" && <ExpansionIcon expanded={expanded} />}\n <span className={withBaseName(\"content\")}>{children}</span>\n {status && !disabled && (\n <StatusIndicator\n className={withBaseName(\"statusIndicator\")}\n status={status}\n />\n )}\n {indicatorSide === \"right\" && <ExpansionIcon expanded={expanded} />}\n </button>\n );\n});\n"],"names":["AccordionHeader","accordionHeaderCss"],"mappings":";;;;;;;;;;;;;;;;AAwBA,MAAM,YAAA,GAAe,aAAa,qBAAqB,CAAA;AAEvD,SAAS,aAAA,CAAc,EAAE,QAAA,EAAmC,EAAA;AAC1D,EAAA,MAAM,EAAE,YAAA,EAAc,UAAW,EAAA,GAAI,OAAQ,EAAA;AAC7C,EAAA,IAAI,QAAU,EAAA;AACZ,IAAA,2BAAQ,YAAa,EAAA,EAAA,aAAA,EAAW,MAAC,SAAW,EAAA,YAAA,CAAa,MAAM,CAAG,EAAA,CAAA;AAAA;AAGpE,EAAA,2BAAQ,UAAW,EAAA,EAAA,aAAA,EAAW,MAAC,SAAW,EAAA,YAAA,CAAa,MAAM,CAAG,EAAA,CAAA;AAClE;AAEO,MAAM,eAAkB,GAAA,UAAA,CAG7B,SAASA,gBAAAA,CAAgB,OAAO,GAAK,EAAA;AACrC,EAAA,MAAM,EAAE,QAAU,EAAA,SAAA,EAAW,SAAS,EAAI,EAAA,GAAG,MAAS,GAAA,KAAA;AACtD,EAAM,MAAA;AAAA,IACJ,KAAA;AAAA,IACA,QAAA;AAAA,IACA,MAAA;AAAA,IACA,aAAA;AAAA,IACA,QAAA;AAAA,IACA,QAAA;AAAA,IACA,OAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,MACE,YAAa,EAAA;AAEjB,EAAA,MAAM,eAAe,SAAU,EAAA;AAC/B,EAAyB,wBAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,uBAAA;AAAA,IACR,GAAK,EAAAC,QAAA;AAAA,IACL,MAAQ,EAAA;AAAA,GACT,CAAA;AAED,EAAM,MAAA,WAAA,GAAc,CAAC,KAAyC,KAAA;AAC5D,IAAA,MAAA,CAAO,KAAK,CAAA;AACZ,IAAU,OAAA,IAAA,IAAA,GAAA,
|
|
1
|
+
{"version":3,"file":"AccordionHeader.js","sources":["../src/accordion/AccordionHeader.tsx"],"sourcesContent":["import { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n type MouseEvent,\n type ReactNode,\n forwardRef,\n} from \"react\";\nimport { useIcon } from \"../semantic-icon-provider\";\nimport { StatusIndicator } from \"../status-indicator\";\nimport { makePrefixer, useIsomorphicLayoutEffect } from \"../utils\";\n\nimport { useAccordion } from \"./AccordionContext\";\nimport accordionHeaderCss from \"./AccordionHeader.css\";\n\nexport interface AccordionHeaderProps\n extends ComponentPropsWithoutRef<\"button\"> {\n /**\n * The content of the Accordion Header\n */\n children?: ReactNode;\n}\n\nconst withBaseName = makePrefixer(\"saltAccordionHeader\");\n\nfunction ExpansionIcon({ expanded }: { expanded: boolean }) {\n const { CollapseIcon, ExpandIcon } = useIcon();\n if (expanded) {\n return <CollapseIcon aria-hidden className={withBaseName(\"icon\")} />;\n }\n\n return <ExpandIcon aria-hidden className={withBaseName(\"icon\")} />;\n}\n\nexport const AccordionHeader = forwardRef<\n HTMLButtonElement,\n AccordionHeaderProps\n>(function AccordionHeader(props, ref) {\n const { children, className, onClick, id, ...rest } = props;\n const {\n value,\n expanded,\n toggle,\n indicatorSide,\n disabled,\n headerId,\n panelId,\n setHeaderId,\n status,\n } = useAccordion();\n\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-accordion-header\",\n css: accordionHeaderCss,\n window: targetWindow,\n });\n\n const handleClick = (event: MouseEvent<HTMLButtonElement>) => {\n toggle(event);\n onClick?.(event);\n };\n\n useIsomorphicLayoutEffect(() => {\n if (id) {\n setHeaderId(id);\n }\n }, [id, setHeaderId]);\n\n return (\n <button\n ref={ref}\n className={clsx(\n withBaseName(),\n { [withBaseName(status ?? \"\")]: status },\n className,\n )}\n disabled={disabled}\n onClick={handleClick}\n aria-expanded={expanded}\n id={headerId}\n aria-controls={panelId}\n value={value}\n type=\"button\"\n {...rest}\n >\n {indicatorSide === \"left\" && <ExpansionIcon expanded={expanded} />}\n <span className={withBaseName(\"content\")}>{children}</span>\n {status && !disabled && (\n <StatusIndicator\n className={withBaseName(\"statusIndicator\")}\n status={status}\n />\n )}\n {indicatorSide === \"right\" && <ExpansionIcon expanded={expanded} />}\n </button>\n );\n});\n"],"names":["AccordionHeader","accordionHeaderCss"],"mappings":";;;;;;;;;;;;;;;;AAwBA,MAAM,YAAA,GAAe,aAAa,qBAAqB,CAAA;AAEvD,SAAS,aAAA,CAAc,EAAE,QAAA,EAAmC,EAAA;AAC1D,EAAA,MAAM,EAAE,YAAA,EAAc,UAAW,EAAA,GAAI,OAAQ,EAAA;AAC7C,EAAA,IAAI,QAAU,EAAA;AACZ,IAAA,2BAAQ,YAAa,EAAA,EAAA,aAAA,EAAW,MAAC,SAAW,EAAA,YAAA,CAAa,MAAM,CAAG,EAAA,CAAA;AAAA;AAGpE,EAAA,2BAAQ,UAAW,EAAA,EAAA,aAAA,EAAW,MAAC,SAAW,EAAA,YAAA,CAAa,MAAM,CAAG,EAAA,CAAA;AAClE;AAEO,MAAM,eAAkB,GAAA,UAAA,CAG7B,SAASA,gBAAAA,CAAgB,OAAO,GAAK,EAAA;AACrC,EAAA,MAAM,EAAE,QAAU,EAAA,SAAA,EAAW,SAAS,EAAI,EAAA,GAAG,MAAS,GAAA,KAAA;AACtD,EAAM,MAAA;AAAA,IACJ,KAAA;AAAA,IACA,QAAA;AAAA,IACA,MAAA;AAAA,IACA,aAAA;AAAA,IACA,QAAA;AAAA,IACA,QAAA;AAAA,IACA,OAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,MACE,YAAa,EAAA;AAEjB,EAAA,MAAM,eAAe,SAAU,EAAA;AAC/B,EAAyB,wBAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,uBAAA;AAAA,IACR,GAAK,EAAAC,QAAA;AAAA,IACL,MAAQ,EAAA;AAAA,GACT,CAAA;AAED,EAAM,MAAA,WAAA,GAAc,CAAC,KAAyC,KAAA;AAC5D,IAAA,MAAA,CAAO,KAAK,CAAA;AACZ,IAAU,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAA,KAAA,CAAA;AAAA,GACZ;AAEA,EAAA,yBAAA,CAA0B,MAAM;AAC9B,IAAA,IAAI,EAAI,EAAA;AACN,MAAA,WAAA,CAAY,EAAE,CAAA;AAAA;AAChB,GACC,EAAA,CAAC,EAAI,EAAA,WAAW,CAAC,CAAA;AAEpB,EACE,uBAAA,IAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,GAAA;AAAA,MACA,SAAW,EAAA,IAAA;AAAA,QACT,YAAa,EAAA;AAAA,QACb,EAAE,CAAC,YAAA,CAAa,UAAU,EAAE,CAAC,GAAG,MAAO,EAAA;AAAA,QACvC;AAAA,OACF;AAAA,MACA,QAAA;AAAA,MACA,OAAS,EAAA,WAAA;AAAA,MACT,eAAe,EAAA,QAAA;AAAA,MACf,EAAI,EAAA,QAAA;AAAA,MACJ,eAAe,EAAA,OAAA;AAAA,MACf,KAAA;AAAA,MACA,IAAK,EAAA,QAAA;AAAA,MACJ,GAAG,IAAA;AAAA,MAEH,QAAA,EAAA;AAAA,QAAkB,aAAA,KAAA,MAAA,oBAAW,GAAA,CAAA,aAAA,EAAA,EAAc,QAAoB,EAAA,CAAA;AAAA,4BAC/D,MAAK,EAAA,EAAA,SAAA,EAAW,YAAa,CAAA,SAAS,GAAI,QAAS,EAAA,CAAA;AAAA,QACnD,MAAA,IAAU,CAAC,QACV,oBAAA,GAAA;AAAA,UAAC,eAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAW,aAAa,iBAAiB,CAAA;AAAA,YACzC;AAAA;AAAA,SACF;AAAA,QAED,aAAkB,KAAA,OAAA,oBAAY,GAAA,CAAA,aAAA,EAAA,EAAc,QAAoB,EAAA;AAAA;AAAA;AAAA,GACnE;AAEJ,CAAC;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccordionPanel.js","sources":["../src/accordion/AccordionPanel.tsx"],"sourcesContent":["import { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n type ReactNode,\n forwardRef,\n} from \"react\";\n\nimport { makePrefixer, useIsomorphicLayoutEffect } from \"../utils\";\nimport { useAccordion } from \"./AccordionContext\";\nimport accordionPanelCss from \"./AccordionPanel.css\";\n\nexport interface AccordionPanelProps extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * The content of the Accordion Panel\n */\n children?: ReactNode;\n}\n\nconst withBaseName = makePrefixer(\"saltAccordionPanel\");\n\nexport const AccordionPanel = forwardRef<HTMLDivElement, AccordionPanelProps>(\n function AccordionPanel(props, ref) {\n const { children, className, id, ...rest } = props;\n\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-accordion-panel\",\n css: accordionPanelCss,\n window: targetWindow,\n });\n\n const { headerId, panelId, setPanelId, expanded, indicatorSide } =\n useAccordion();\n\n useIsomorphicLayoutEffect(() => {\n if (id) {\n setPanelId(id);\n }\n }, [id, setPanelId]);\n\n return (\n <div\n ref={ref}\n className={clsx(withBaseName(), className)}\n role=\"region\"\n id={panelId}\n aria-labelledby={headerId}\n aria-hidden={!expanded ? \"true\" : undefined}\n hidden={!expanded}\n {...rest}\n >\n <div className={withBaseName(\"inner\")}>\n <div\n className={clsx(withBaseName(\"content\"), {\n [withBaseName(\"indentedContent\")]: indicatorSide === \"left\",\n })}\n >\n {children}\n </div>\n </div>\n </div>\n );\n },\n);\n"],"names":["AccordionPanel","accordionPanelCss"],"mappings":";;;;;;;;;;;;;;AAoBA,MAAM,YAAA,GAAe,aAAa,oBAAoB,CAAA;AAE/C,MAAM,cAAiB,GAAA,UAAA;AAAA,EAC5B,SAASA,eAAe,CAAA,KAAA,EAAO,GAAK,EAAA;AAClC,IAAA,MAAM,EAAE,QAAU,EAAA,SAAA,EAAW,EAAI,EAAA,GAAG,MAAS,GAAA,KAAA;AAE7C,IAAA,MAAM,eAAe,SAAU,EAAA;AAC/B,IAAyB,wBAAA,CAAA;AAAA,MACvB,MAAQ,EAAA,sBAAA;AAAA,MACR,GAAK,EAAAC,QAAA;AAAA,MACL,MAAQ,EAAA;AAAA,KACT,CAAA;AAED,IAAA,MAAM,EAAE,QAAU,EAAA,OAAA,EAAS,YAAY,QAAU,EAAA,aAAA,KAC/C,YAAa,EAAA;AAEf,IAAA,yBAAA,CAA0B,MAAM;AAC9B,MAAA,IAAI,EAAI,EAAA;AACN,QAAA,UAAA,CAAW,EAAE,CAAA;AAAA;AACf,KACC,EAAA,CAAC,EAAI,EAAA,UAAU,CAAC,CAAA;AAEnB,IACE,uBAAA,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,SAAW,EAAA,IAAA,CAAK,YAAa,EAAA,EAAG,SAAS,CAAA;AAAA,QACzC,IAAK,EAAA,QAAA;AAAA,QACL,EAAI,EAAA,OAAA;AAAA,QACJ,iBAAiB,EAAA,QAAA;AAAA,QACjB,aAAA,EAAa,CAAC,QAAA,GAAW,MAAS,GAAA,
|
|
1
|
+
{"version":3,"file":"AccordionPanel.js","sources":["../src/accordion/AccordionPanel.tsx"],"sourcesContent":["import { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n type ReactNode,\n forwardRef,\n} from \"react\";\n\nimport { makePrefixer, useIsomorphicLayoutEffect } from \"../utils\";\nimport { useAccordion } from \"./AccordionContext\";\nimport accordionPanelCss from \"./AccordionPanel.css\";\n\nexport interface AccordionPanelProps extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * The content of the Accordion Panel\n */\n children?: ReactNode;\n}\n\nconst withBaseName = makePrefixer(\"saltAccordionPanel\");\n\nexport const AccordionPanel = forwardRef<HTMLDivElement, AccordionPanelProps>(\n function AccordionPanel(props, ref) {\n const { children, className, id, ...rest } = props;\n\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-accordion-panel\",\n css: accordionPanelCss,\n window: targetWindow,\n });\n\n const { headerId, panelId, setPanelId, expanded, indicatorSide } =\n useAccordion();\n\n useIsomorphicLayoutEffect(() => {\n if (id) {\n setPanelId(id);\n }\n }, [id, setPanelId]);\n\n return (\n <div\n ref={ref}\n className={clsx(withBaseName(), className)}\n role=\"region\"\n id={panelId}\n aria-labelledby={headerId}\n aria-hidden={!expanded ? \"true\" : undefined}\n hidden={!expanded}\n {...rest}\n >\n <div className={withBaseName(\"inner\")}>\n <div\n className={clsx(withBaseName(\"content\"), {\n [withBaseName(\"indentedContent\")]: indicatorSide === \"left\",\n })}\n >\n {children}\n </div>\n </div>\n </div>\n );\n },\n);\n"],"names":["AccordionPanel","accordionPanelCss"],"mappings":";;;;;;;;;;;;;;AAoBA,MAAM,YAAA,GAAe,aAAa,oBAAoB,CAAA;AAE/C,MAAM,cAAiB,GAAA,UAAA;AAAA,EAC5B,SAASA,eAAe,CAAA,KAAA,EAAO,GAAK,EAAA;AAClC,IAAA,MAAM,EAAE,QAAU,EAAA,SAAA,EAAW,EAAI,EAAA,GAAG,MAAS,GAAA,KAAA;AAE7C,IAAA,MAAM,eAAe,SAAU,EAAA;AAC/B,IAAyB,wBAAA,CAAA;AAAA,MACvB,MAAQ,EAAA,sBAAA;AAAA,MACR,GAAK,EAAAC,QAAA;AAAA,MACL,MAAQ,EAAA;AAAA,KACT,CAAA;AAED,IAAA,MAAM,EAAE,QAAU,EAAA,OAAA,EAAS,YAAY,QAAU,EAAA,aAAA,KAC/C,YAAa,EAAA;AAEf,IAAA,yBAAA,CAA0B,MAAM;AAC9B,MAAA,IAAI,EAAI,EAAA;AACN,QAAA,UAAA,CAAW,EAAE,CAAA;AAAA;AACf,KACC,EAAA,CAAC,EAAI,EAAA,UAAU,CAAC,CAAA;AAEnB,IACE,uBAAA,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,SAAW,EAAA,IAAA,CAAK,YAAa,EAAA,EAAG,SAAS,CAAA;AAAA,QACzC,IAAK,EAAA,QAAA;AAAA,QACL,EAAI,EAAA,OAAA;AAAA,QACJ,iBAAiB,EAAA,QAAA;AAAA,QACjB,aAAA,EAAa,CAAC,QAAA,GAAW,MAAS,GAAA,MAAA;AAAA,QAClC,QAAQ,CAAC,QAAA;AAAA,QACR,GAAG,IAAA;AAAA,QAEJ,QAAC,kBAAA,GAAA,CAAA,KAAA,EAAA,EAAI,SAAW,EAAA,YAAA,CAAa,OAAO,CAClC,EAAA,QAAA,kBAAA,GAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,SAAW,EAAA,IAAA,CAAK,YAAa,CAAA,SAAS,CAAG,EAAA;AAAA,cACvC,CAAC,YAAA,CAAa,iBAAiB,CAAC,GAAG,aAAkB,KAAA;AAAA,aACtD,CAAA;AAAA,YAEA;AAAA;AAAA,SAEL,EAAA;AAAA;AAAA,KACF;AAAA;AAGN;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AriaAnnouncerContext.js","sources":["../src/aria-announcer/AriaAnnouncerContext.ts"],"sourcesContent":["import { createContext } from \"react\";\n\nexport type AnnounceFn = (announcement: string, delay?: number) => void;\n\nexport type AriaAnnouncer = {\n announce: AnnounceFn;\n};\n\nexport const AriaAnnouncerContext = createContext<AriaAnnouncer | undefined>(\n undefined,\n);\n"],"names":[],"mappings":";;AAQO,MAAM,oBAAuB,GAAA,aAAA;AAAA,EAClC
|
|
1
|
+
{"version":3,"file":"AriaAnnouncerContext.js","sources":["../src/aria-announcer/AriaAnnouncerContext.ts"],"sourcesContent":["import { createContext } from \"react\";\n\nexport type AnnounceFn = (announcement: string, delay?: number) => void;\n\nexport type AriaAnnouncer = {\n announce: AnnounceFn;\n};\n\nexport const AriaAnnouncerContext = createContext<AriaAnnouncer | undefined>(\n undefined,\n);\n"],"names":[],"mappings":";;AAQO,MAAM,oBAAuB,GAAA,aAAA;AAAA,EAClC;AACF;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AriaAnnouncerProvider.js","sources":["../src/aria-announcer/AriaAnnouncerProvider.tsx"],"sourcesContent":["import {\n type CSSProperties,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { AriaAnnouncerContext } from \"./AriaAnnouncerContext\";\n\nexport const ARIA_ANNOUNCE_DELAY = 150;\n\nexport interface AriaAnnouncerProviderProps {\n children?: ReactNode;\n /**\n * Style overrides for the aria-live element\n */\n style?: CSSProperties;\n}\n\nexport function AriaAnnouncerProvider({\n children,\n style,\n}: AriaAnnouncerProviderProps) {\n // announcement that gets rendered inside aria-live and read out by screen readers\n const [currentAnnouncement, setCurrentAnnouncement] = useState(\"\");\n // queue that stores all the requested announcements\n const announcementsRef = useRef<string[]>([]);\n // we use this variable to decide whether to start the announcement queue if one is not already in progress\n const isAnnouncingRef = useRef(false);\n // we need to keep track of the state of the component mount since all the async function calls\n // might trigger a setState after a component has been unmounted\n const mountedRef = useRef(true);\n\n // announceAll will get called recursively until all the announcements are rendered and cleared from the queue\n const announceAll = useCallback(() => {\n isAnnouncingRef.current = true;\n if (mountedRef.current) {\n setCurrentAnnouncement(\"\");\n requestAnimationFrame(() => {\n if (mountedRef.current && announcementsRef.current.length) {\n const announcement = announcementsRef.current.shift() as string;\n setCurrentAnnouncement(announcement);\n setTimeout(() => {\n announceAll();\n }, ARIA_ANNOUNCE_DELAY);\n } else {\n isAnnouncingRef.current = false;\n }\n });\n }\n }, []);\n\n const announce = useCallback(\n (announcement: string) => {\n announcementsRef.current.push(announcement);\n if (!isAnnouncingRef.current) {\n announceAll();\n }\n },\n [announceAll],\n );\n\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n };\n }, []);\n\n const value = useMemo(() => ({ announce }), [announce]);\n return (\n <AriaAnnouncerContext.Provider value={value}>\n {children}\n <div\n aria-atomic=\"true\"\n aria-live=\"assertive\"\n // hidden styling based on https://tailwindcss.com/docs/screen-readers\n style={{\n position: \"absolute\",\n height: 1,\n width: 1,\n padding: 0,\n margin: -1,\n overflow: \"hidden\",\n clip: \"rect(0, 0, 0, 0)\",\n whiteSpace: \"nowrap\",\n borderWidth: 0,\n ...style,\n }}\n >\n {currentAnnouncement}\n </div>\n </AriaAnnouncerContext.Provider>\n );\n}\n"],"names":[],"mappings":";;;;AAYO,MAAM,mBAAsB,GAAA;AAU5B,SAAS,qBAAsB,CAAA;AAAA,EACpC,QAAA;AAAA,EACA;AACF,CAA+B,EAAA;AAE7B,EAAA,MAAM,CAAC,mBAAA,EAAqB,sBAAsB,CAAA,GAAI,SAAS,EAAE,CAAA;AAEjE,EAAM,MAAA,gBAAA,GAAmB,MAAiB,CAAA,EAAE,CAAA;AAE5C,EAAM,MAAA,eAAA,GAAkB,OAAO,KAAK,CAAA;AAGpC,EAAM,MAAA,UAAA,GAAa,OAAO,IAAI,CAAA;AAG9B,EAAM,MAAA,WAAA,GAAc,YAAY,MAAM;AACpC,IAAA,eAAA,CAAgB,OAAU,GAAA,IAAA;AAC1B,IAAA,IAAI,WAAW,OAAS,EAAA;AACtB,MAAA,sBAAA,CAAuB,EAAE,CAAA;AACzB,MAAA,qBAAA,CAAsB,MAAM;AAC1B,QAAA,IAAI,UAAW,CAAA,OAAA,IAAW,gBAAiB,CAAA,OAAA,CAAQ,MAAQ,EAAA;AACzD,UAAM,MAAA,YAAA,GAAe,gBAAiB,CAAA,OAAA,CAAQ,KAAM,EAAA;AACpD,UAAA,sBAAA,CAAuB,YAAY,CAAA;AACnC,UAAA,UAAA,CAAW,MAAM;AACf,YAAY,WAAA,EAAA;AAAA,aACX,mBAAmB,CAAA;AAAA,SACjB,MAAA;AACL,UAAA,eAAA,CAAgB,OAAU,GAAA,KAAA;AAAA;AAC5B,OACD,CAAA;AAAA;AACH,GACF,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,QAAW,GAAA,WAAA;AAAA,IACf,CAAC,YAAyB,KAAA;AACxB,MAAiB,gBAAA,CAAA,OAAA,CAAQ,KAAK,YAAY,CAAA;AAC1C,MAAI,IAAA,CAAC,gBAAgB,OAAS,EAAA;AAC5B,QAAY,WAAA,EAAA;AAAA;AACd,KACF;AAAA,IACA,CAAC,WAAW;AAAA,GACd;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,UAAA,CAAW,OAAU,GAAA,IAAA;AACrB,IAAA,OAAO,MAAM;AACX,MAAA,UAAA,CAAW,OAAU,GAAA,KAAA;AAAA,KACvB;AAAA,GACF,EAAG,EAAE,CAAA;AAEL,EAAM,MAAA,KAAA,GAAQ,QAAQ,OAAO,EAAE,UAAa,CAAA,EAAA,CAAC,QAAQ,CAAC,CAAA;AACtD,EAAA,uBACG,IAAA,CAAA,oBAAA,CAAqB,QAArB,EAAA,EAA8B,KAC5B,EAAA,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,oBACD,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,aAAY,EAAA,MAAA;AAAA,QACZ,WAAU,EAAA,WAAA;AAAA,QAEV,KAAO,EAAA;AAAA,UACL,QAAU,EAAA,UAAA;AAAA,UACV,MAAQ,EAAA,CAAA;AAAA,UACR,KAAO,EAAA,CAAA;AAAA,UACP,OAAS,EAAA,CAAA;AAAA,UACT,MAAQ,EAAA,
|
|
1
|
+
{"version":3,"file":"AriaAnnouncerProvider.js","sources":["../src/aria-announcer/AriaAnnouncerProvider.tsx"],"sourcesContent":["import {\n type CSSProperties,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { AriaAnnouncerContext } from \"./AriaAnnouncerContext\";\n\nexport const ARIA_ANNOUNCE_DELAY = 150;\n\nexport interface AriaAnnouncerProviderProps {\n children?: ReactNode;\n /**\n * Style overrides for the aria-live element\n */\n style?: CSSProperties;\n}\n\nexport function AriaAnnouncerProvider({\n children,\n style,\n}: AriaAnnouncerProviderProps) {\n // announcement that gets rendered inside aria-live and read out by screen readers\n const [currentAnnouncement, setCurrentAnnouncement] = useState(\"\");\n // queue that stores all the requested announcements\n const announcementsRef = useRef<string[]>([]);\n // we use this variable to decide whether to start the announcement queue if one is not already in progress\n const isAnnouncingRef = useRef(false);\n // we need to keep track of the state of the component mount since all the async function calls\n // might trigger a setState after a component has been unmounted\n const mountedRef = useRef(true);\n\n // announceAll will get called recursively until all the announcements are rendered and cleared from the queue\n const announceAll = useCallback(() => {\n isAnnouncingRef.current = true;\n if (mountedRef.current) {\n setCurrentAnnouncement(\"\");\n requestAnimationFrame(() => {\n if (mountedRef.current && announcementsRef.current.length) {\n const announcement = announcementsRef.current.shift() as string;\n setCurrentAnnouncement(announcement);\n setTimeout(() => {\n announceAll();\n }, ARIA_ANNOUNCE_DELAY);\n } else {\n isAnnouncingRef.current = false;\n }\n });\n }\n }, []);\n\n const announce = useCallback(\n (announcement: string) => {\n announcementsRef.current.push(announcement);\n if (!isAnnouncingRef.current) {\n announceAll();\n }\n },\n [announceAll],\n );\n\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n };\n }, []);\n\n const value = useMemo(() => ({ announce }), [announce]);\n return (\n <AriaAnnouncerContext.Provider value={value}>\n {children}\n <div\n aria-atomic=\"true\"\n aria-live=\"assertive\"\n // hidden styling based on https://tailwindcss.com/docs/screen-readers\n style={{\n position: \"absolute\",\n height: 1,\n width: 1,\n padding: 0,\n margin: -1,\n overflow: \"hidden\",\n clip: \"rect(0, 0, 0, 0)\",\n whiteSpace: \"nowrap\",\n borderWidth: 0,\n ...style,\n }}\n >\n {currentAnnouncement}\n </div>\n </AriaAnnouncerContext.Provider>\n );\n}\n"],"names":[],"mappings":";;;;AAYO,MAAM,mBAAsB,GAAA;AAU5B,SAAS,qBAAsB,CAAA;AAAA,EACpC,QAAA;AAAA,EACA;AACF,CAA+B,EAAA;AAE7B,EAAA,MAAM,CAAC,mBAAA,EAAqB,sBAAsB,CAAA,GAAI,SAAS,EAAE,CAAA;AAEjE,EAAM,MAAA,gBAAA,GAAmB,MAAiB,CAAA,EAAE,CAAA;AAE5C,EAAM,MAAA,eAAA,GAAkB,OAAO,KAAK,CAAA;AAGpC,EAAM,MAAA,UAAA,GAAa,OAAO,IAAI,CAAA;AAG9B,EAAM,MAAA,WAAA,GAAc,YAAY,MAAM;AACpC,IAAA,eAAA,CAAgB,OAAU,GAAA,IAAA;AAC1B,IAAA,IAAI,WAAW,OAAS,EAAA;AACtB,MAAA,sBAAA,CAAuB,EAAE,CAAA;AACzB,MAAA,qBAAA,CAAsB,MAAM;AAC1B,QAAA,IAAI,UAAW,CAAA,OAAA,IAAW,gBAAiB,CAAA,OAAA,CAAQ,MAAQ,EAAA;AACzD,UAAM,MAAA,YAAA,GAAe,gBAAiB,CAAA,OAAA,CAAQ,KAAM,EAAA;AACpD,UAAA,sBAAA,CAAuB,YAAY,CAAA;AACnC,UAAA,UAAA,CAAW,MAAM;AACf,YAAY,WAAA,EAAA;AAAA,aACX,mBAAmB,CAAA;AAAA,SACjB,MAAA;AACL,UAAA,eAAA,CAAgB,OAAU,GAAA,KAAA;AAAA;AAC5B,OACD,CAAA;AAAA;AACH,GACF,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,QAAW,GAAA,WAAA;AAAA,IACf,CAAC,YAAyB,KAAA;AACxB,MAAiB,gBAAA,CAAA,OAAA,CAAQ,KAAK,YAAY,CAAA;AAC1C,MAAI,IAAA,CAAC,gBAAgB,OAAS,EAAA;AAC5B,QAAY,WAAA,EAAA;AAAA;AACd,KACF;AAAA,IACA,CAAC,WAAW;AAAA,GACd;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,UAAA,CAAW,OAAU,GAAA,IAAA;AACrB,IAAA,OAAO,MAAM;AACX,MAAA,UAAA,CAAW,OAAU,GAAA,KAAA;AAAA,KACvB;AAAA,GACF,EAAG,EAAE,CAAA;AAEL,EAAM,MAAA,KAAA,GAAQ,QAAQ,OAAO,EAAE,UAAa,CAAA,EAAA,CAAC,QAAQ,CAAC,CAAA;AACtD,EAAA,uBACG,IAAA,CAAA,oBAAA,CAAqB,QAArB,EAAA,EAA8B,KAC5B,EAAA,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,oBACD,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,aAAY,EAAA,MAAA;AAAA,QACZ,WAAU,EAAA,WAAA;AAAA,QAEV,KAAO,EAAA;AAAA,UACL,QAAU,EAAA,UAAA;AAAA,UACV,MAAQ,EAAA,CAAA;AAAA,UACR,KAAO,EAAA,CAAA;AAAA,UACP,OAAS,EAAA,CAAA;AAAA,UACT,MAAQ,EAAA,EAAA;AAAA,UACR,QAAU,EAAA,QAAA;AAAA,UACV,IAAM,EAAA,kBAAA;AAAA,UACN,UAAY,EAAA,QAAA;AAAA,UACZ,WAAa,EAAA,CAAA;AAAA,UACb,GAAG;AAAA,SACL;AAAA,QAEC,QAAA,EAAA;AAAA;AAAA;AACH,GACF,EAAA,CAAA;AAEJ;;;;"}
|
|
@@ -2,7 +2,6 @@ import { useContext, useRef, useCallback, useMemo, useEffect } from 'react';
|
|
|
2
2
|
import { debounce } from '../utils/debounce.js';
|
|
3
3
|
import { AriaAnnouncerContext } from './AriaAnnouncerContext.js';
|
|
4
4
|
|
|
5
|
-
let warnedOnce = false;
|
|
6
5
|
const useAriaAnnouncer = ({
|
|
7
6
|
debounce: debounceInterval = 0
|
|
8
7
|
} = {}) => {
|
|
@@ -11,14 +10,7 @@ const useAriaAnnouncer = ({
|
|
|
11
10
|
const baseAnnounce = useCallback(
|
|
12
11
|
(announcement, delay) => {
|
|
13
12
|
const isReactAnnouncerInstalled = context == null ? void 0 : context.announce;
|
|
14
|
-
if (process.env.NODE_ENV !== "production")
|
|
15
|
-
if (isReactAnnouncerInstalled && warnedOnce) {
|
|
16
|
-
console.warn(
|
|
17
|
-
"useAriaAnnouncer is being used without an AriaAnnouncerProvider. Your application should be wrapped in an AriaAnnouncerProvider"
|
|
18
|
-
);
|
|
19
|
-
warnedOnce = true;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
13
|
+
if (process.env.NODE_ENV !== "production") ;
|
|
22
14
|
function makeAnnouncement() {
|
|
23
15
|
if (mountedRef.current) {
|
|
24
16
|
if (isReactAnnouncerInstalled) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAriaAnnouncer.js","sources":["../src/aria-announcer/useAriaAnnouncer.ts"],"sourcesContent":["import { useCallback, useContext, useEffect, useMemo, useRef } from \"react\";\nimport { debounce } from \"../utils/debounce\";\nimport {\n type AriaAnnouncer,\n AriaAnnouncerContext,\n} from \"./AriaAnnouncerContext\";\n\nexport type useAnnouncerOptions = {\n debounce?: number;\n};\nexport type useAriaAnnouncerHook = (\n options?: useAnnouncerOptions,\n) => AriaAnnouncer;\n\nlet warnedOnce = false;\n\nexport const useAriaAnnouncer: useAriaAnnouncerHook = ({\n debounce: debounceInterval = 0,\n} = {}) => {\n const context = useContext(AriaAnnouncerContext);\n const mountedRef = useRef(true);\n const baseAnnounce = useCallback(\n (announcement: string, delay?: number) => {\n const isReactAnnouncerInstalled = context?.announce;\n\n if (process.env.NODE_ENV !== \"production\") {\n if (isReactAnnouncerInstalled && warnedOnce) {\n console.warn(\n \"useAriaAnnouncer is being used without an AriaAnnouncerProvider. Your application should be wrapped in an AriaAnnouncerProvider\",\n );\n warnedOnce = true;\n }\n }\n\n function makeAnnouncement() {\n if (mountedRef.current) {\n if (isReactAnnouncerInstalled) {\n context.announce(announcement);\n }\n }\n }\n\n if (delay) {\n setTimeout(makeAnnouncement, delay);\n } else {\n makeAnnouncement();\n }\n },\n [context],\n );\n\n const announce = useMemo(\n () =>\n debounceInterval > 0\n ? debounce(baseAnnounce, debounceInterval)\n : baseAnnounce,\n [baseAnnounce, debounceInterval],\n );\n\n const ariaAnnouncer = useMemo(\n () => ({\n ...context,\n announce,\n }),\n [context, announce],\n );\n\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n };\n }, []);\n\n return ariaAnnouncer;\n};\n"],"names":[],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"useAriaAnnouncer.js","sources":["../src/aria-announcer/useAriaAnnouncer.ts"],"sourcesContent":["import { useCallback, useContext, useEffect, useMemo, useRef } from \"react\";\nimport { debounce } from \"../utils/debounce\";\nimport {\n type AriaAnnouncer,\n AriaAnnouncerContext,\n} from \"./AriaAnnouncerContext\";\n\nexport type useAnnouncerOptions = {\n debounce?: number;\n};\nexport type useAriaAnnouncerHook = (\n options?: useAnnouncerOptions,\n) => AriaAnnouncer;\n\nlet warnedOnce = false;\n\nexport const useAriaAnnouncer: useAriaAnnouncerHook = ({\n debounce: debounceInterval = 0,\n} = {}) => {\n const context = useContext(AriaAnnouncerContext);\n const mountedRef = useRef(true);\n const baseAnnounce = useCallback(\n (announcement: string, delay?: number) => {\n const isReactAnnouncerInstalled = context?.announce;\n\n if (process.env.NODE_ENV !== \"production\") {\n if (isReactAnnouncerInstalled && warnedOnce) {\n console.warn(\n \"useAriaAnnouncer is being used without an AriaAnnouncerProvider. Your application should be wrapped in an AriaAnnouncerProvider\",\n );\n warnedOnce = true;\n }\n }\n\n function makeAnnouncement() {\n if (mountedRef.current) {\n if (isReactAnnouncerInstalled) {\n context.announce(announcement);\n }\n }\n }\n\n if (delay) {\n setTimeout(makeAnnouncement, delay);\n } else {\n makeAnnouncement();\n }\n },\n [context],\n );\n\n const announce = useMemo(\n () =>\n debounceInterval > 0\n ? debounce(baseAnnounce, debounceInterval)\n : baseAnnounce,\n [baseAnnounce, debounceInterval],\n );\n\n const ariaAnnouncer = useMemo(\n () => ({\n ...context,\n announce,\n }),\n [context, announce],\n );\n\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n };\n }, []);\n\n return ariaAnnouncer;\n};\n"],"names":[],"mappings":";;;;AAgBO,MAAM,mBAAyC,CAAC;AAAA,EACrD,UAAU,gBAAmB,GAAA;AAC/B,CAAA,GAAI,EAAO,KAAA;AACT,EAAM,MAAA,OAAA,GAAU,WAAW,oBAAoB,CAAA;AAC/C,EAAM,MAAA,UAAA,GAAa,OAAO,IAAI,CAAA;AAC9B,EAAA,MAAM,YAAe,GAAA,WAAA;AAAA,IACnB,CAAC,cAAsB,KAAmB,KAAA;AACxC,MAAA,MAAM,4BAA4B,OAAS,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAA,QAAA;AAE3C,MAAI,IAAA,OAAA,CAAQ,GAAI,CAAA,QAAA,KAAa,YAAc,EAAA;AAS3C,MAAA,SAAS,gBAAmB,GAAA;AAC1B,QAAA,IAAI,WAAW,OAAS,EAAA;AACtB,UAAA,IAAI,yBAA2B,EAAA;AAC7B,YAAA,OAAA,CAAQ,SAAS,YAAY,CAAA;AAAA;AAC/B;AACF;AAGF,MAAA,IAAI,KAAO,EAAA;AACT,QAAA,UAAA,CAAW,kBAAkB,KAAK,CAAA;AAAA,OAC7B,MAAA;AACL,QAAiB,gBAAA,EAAA;AAAA;AACnB,KACF;AAAA,IACA,CAAC,OAAO;AAAA,GACV;AAEA,EAAA,MAAM,QAAW,GAAA,OAAA;AAAA,IACf,MACE,gBAAmB,GAAA,CAAA,GACf,QAAS,CAAA,YAAA,EAAc,gBAAgB,CACvC,GAAA,YAAA;AAAA,IACN,CAAC,cAAc,gBAAgB;AAAA,GACjC;AAEA,EAAA,MAAM,aAAgB,GAAA,OAAA;AAAA,IACpB,OAAO;AAAA,MACL,GAAG,OAAA;AAAA,MACH;AAAA,KACF,CAAA;AAAA,IACA,CAAC,SAAS,QAAQ;AAAA,GACpB;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,UAAA,CAAW,OAAU,GAAA,IAAA;AACrB,IAAA,OAAO,MAAM;AACX,MAAA,UAAA,CAAW,OAAU,GAAA,KAAA;AAAA,KACvB;AAAA,GACF,EAAG,EAAE,CAAA;AAEL,EAAO,OAAA,aAAA;AACT;;;;"}
|