@frontify/fondue 9.11.1 → 9.12.2
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/dist/components/Dropdown/Dropdown.es.js +20 -19
- package/dist/components/Dropdown/Dropdown.es.js.map +1 -1
- package/dist/components/MultiSelect/MultiSelect.es.js +22 -22
- package/dist/components/MultiSelect/MultiSelect.es.js.map +1 -1
- package/dist/components/MultiSelect/helpers.d.ts +1 -1
- package/dist/components/MultiSelect/helpers.es.js +17 -3
- package/dist/components/MultiSelect/helpers.es.js.map +1 -1
- package/dist/components/Tooltip/Tooltip.es.js +26 -25
- package/dist/components/Tooltip/Tooltip.es.js.map +1 -1
- package/dist/index.cjs.js +15 -15
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.umd.js +12 -12
- package/dist/index.umd.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -9,8 +9,8 @@ import { useFocusRing as ot, FocusScope as rt } from "@react-aria/focus";
|
|
|
9
9
|
import { useOverlay as nt, DismissButton as L } from "@react-aria/overlays";
|
|
10
10
|
import { useSelect as st, HiddenSelect as lt } from "@react-aria/select";
|
|
11
11
|
import { mergeProps as at } from "@react-aria/utils";
|
|
12
|
-
import { useSelectState as
|
|
13
|
-
import { merge as
|
|
12
|
+
import { useSelectState as it } from "@react-stately/select";
|
|
13
|
+
import { merge as mt } from "../../utilities/merge.es.js";
|
|
14
14
|
import { AnimatePresence as pt, motion as ct } from "framer-motion";
|
|
15
15
|
import e, { useRef as d, useEffect as ut } from "react";
|
|
16
16
|
import { useDropdownAutoHeight as ft, DEFAULT_DROPDOWN_MAX_HEIGHT as dt } from "./useDropdownAutoHeight.es.js";
|
|
@@ -18,7 +18,7 @@ import { Validation as F } from "../../utilities/validation.es.js";
|
|
|
18
18
|
import { LoadingCircle as wt, LoadingCircleSize as gt } from "../LoadingCircle/LoadingCircle.es.js";
|
|
19
19
|
import { createPortal as St } from "react-dom";
|
|
20
20
|
import { usePopper as ht } from "react-popper";
|
|
21
|
-
var
|
|
21
|
+
var yt = /* @__PURE__ */ ((t) => (t.Small = "Small", t.Large = "Large", t))(yt || {}), Et = /* @__PURE__ */ ((t) => (t.Start = "Start", t.End = "End", t))(Et || {}), bt = /* @__PURE__ */ ((t) => (t.Top = "Top", t.Bottom = "Bottom", t))(bt || {});
|
|
22
22
|
const xt = (t, s) => K(A(t)).has(s) ? null : t.map(({ menuItems: o }) => o).flat().find(({ id: o }) => o.toString() === (s == null ? void 0 : s.toString())) || null, Gt = ({
|
|
23
23
|
id: t,
|
|
24
24
|
menuBlocks: s,
|
|
@@ -36,26 +36,27 @@ const xt = (t, s) => K(A(t)).has(s) ? null : t.map(({ menuItems: o }) => o).flat
|
|
|
36
36
|
position: O = "Bottom"
|
|
37
37
|
}) => {
|
|
38
38
|
var D;
|
|
39
|
-
const r = o ? xt(s, o) : null, S = J(R, s), n =
|
|
39
|
+
const r = o ? xt(s, o) : null, S = J(R, s), n = it({
|
|
40
40
|
...S,
|
|
41
41
|
defaultSelectedKey: o,
|
|
42
|
-
onSelectionChange: (
|
|
42
|
+
onSelectionChange: (m) => w(m),
|
|
43
43
|
disabledKeys: K(A(s))
|
|
44
|
-
}), l = d(null), { triggerProps: z, valueProps: V, menuProps: _ } = st({ ...S, isDisabled: a }, n, l), { buttonProps: h } = et({ ...z, isDisabled: a }, l), { isOpen:
|
|
44
|
+
}), l = d(null), { triggerProps: z, valueProps: V, menuProps: _ } = st({ ...S, isDisabled: a }, n, l), { buttonProps: h } = et({ ...z, isDisabled: a }, l), { isOpen: i } = n, { isFocusVisible: v, focusProps: W } = ot(), y = d(null), { overlayProps: $ } = nt({ isOpen: i, onClose: () => n.close(), shouldCloseOnBlur: !0, isDismissable: !0 }, y);
|
|
45
45
|
ut(() => {
|
|
46
46
|
n.disabledKeys.has(o) || n.setSelectedKey(o);
|
|
47
47
|
}, [o]);
|
|
48
|
-
const { maxHeight:
|
|
48
|
+
const { maxHeight: E } = ft(l, { isOpen: i, autoResize: u }), G = !u || E !== dt, U = r ? f.Active : f.Default, X = a ? f.Disabled : U, j = r ? Y[r.style || Z.Primary][X] : "tw-text-black-60", b = N ? () => {
|
|
49
49
|
n.setSelectedKey("");
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
} : void 0, x = !!r && !!
|
|
50
|
+
const m = n.collection.getFirstKey();
|
|
51
|
+
m && n.selectionManager.setFocusedKey(m);
|
|
52
|
+
} : void 0, x = !!r && !!b, C = d(null), q = {
|
|
53
53
|
["Top-Start"]: "top-start",
|
|
54
54
|
["Top-End"]: "top-end",
|
|
55
55
|
["Bottom-Start"]: "bottom-start",
|
|
56
56
|
["Bottom-End"]: "bottom-end"
|
|
57
57
|
}, P = ht(l == null ? void 0 : l.current, C.current, {
|
|
58
58
|
placement: q[`${O}-${H}`],
|
|
59
|
+
strategy: "fixed",
|
|
59
60
|
modifiers: [
|
|
60
61
|
{
|
|
61
62
|
name: "offset",
|
|
@@ -75,9 +76,9 @@ const xt = (t, s) => K(A(t)).has(s) ? null : t.map(({ menuItems: o }) => o).flat
|
|
|
75
76
|
disabled: a,
|
|
76
77
|
buttonProps: h,
|
|
77
78
|
isFocusVisible: !a && v,
|
|
78
|
-
isOpen:
|
|
79
|
+
isOpen: i,
|
|
79
80
|
size: p === "Large" ? M.Large : M.Small,
|
|
80
|
-
onClear:
|
|
81
|
+
onClear: b,
|
|
81
82
|
showClear: x,
|
|
82
83
|
validation: g
|
|
83
84
|
}, /* @__PURE__ */ e.createElement(lt, {
|
|
@@ -88,7 +89,7 @@ const xt = (t, s) => K(A(t)).has(s) ? null : t.map(({ menuItems: o }) => o).flat
|
|
|
88
89
|
id: tt(t),
|
|
89
90
|
ref: l,
|
|
90
91
|
"data-test-id": "dropdown-trigger",
|
|
91
|
-
className:
|
|
92
|
+
className: mt([
|
|
92
93
|
"tw-overflow-hidden tw-flex-auto tw-h-full tw-rounded tw-text-left tw-outline-none",
|
|
93
94
|
p === "Small" ? "tw-py-2 tw-pl-3 tw-min-h-[34px]" : "tw-pl-5 tw-py-4 tw-min-h-[60px]",
|
|
94
95
|
x ? "tw-pr-11" : "tw-pr-7",
|
|
@@ -99,7 +100,7 @@ const xt = (t, s) => K(A(t)).has(s) ? null : t.map(({ menuItems: o }) => o).flat
|
|
|
99
100
|
title: (r == null ? void 0 : r.title) || B,
|
|
100
101
|
decorator: c != null ? c : r == null ? void 0 : r.decorator,
|
|
101
102
|
size: p === "Small" ? T.Small : T.Large
|
|
102
|
-
}))), St(/* @__PURE__ */ e.createElement(pt, null, !a &&
|
|
103
|
+
}))), St(/* @__PURE__ */ e.createElement(pt, null, !a && i && G && /* @__PURE__ */ e.createElement(ct.div, {
|
|
103
104
|
ref: C,
|
|
104
105
|
style: {
|
|
105
106
|
...P.styles.popper,
|
|
@@ -116,8 +117,8 @@ const xt = (t, s) => K(A(t)).has(s) ? null : t.map(({ menuItems: o }) => o).flat
|
|
|
116
117
|
restoreFocus: !0
|
|
117
118
|
}, /* @__PURE__ */ e.createElement("div", {
|
|
118
119
|
...$,
|
|
119
|
-
ref:
|
|
120
|
-
style: u ? { maxHeight:
|
|
120
|
+
ref: y,
|
|
121
|
+
style: u ? { maxHeight: E } : {},
|
|
121
122
|
className: "tw-flex tw-flex-col",
|
|
122
123
|
"data-test-id": "dropdown-menu",
|
|
123
124
|
role: "dialog"
|
|
@@ -138,8 +139,8 @@ const xt = (t, s) => K(A(t)).has(s) ? null : t.map(({ menuItems: o }) => o).flat
|
|
|
138
139
|
};
|
|
139
140
|
export {
|
|
140
141
|
Gt as Dropdown,
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
142
|
+
Et as DropdownAlignment,
|
|
143
|
+
bt as DropdownPosition,
|
|
144
|
+
yt as DropdownSize
|
|
144
145
|
};
|
|
145
146
|
//# sourceMappingURL=Dropdown.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dropdown.es.js","sources":["../../../src/components/Dropdown/Dropdown.tsx"],"sourcesContent":["/* (c) Copyright Frontify Ltd., all rights reserved. */\n\nimport { getDisabledItemIds, getMenuItems, mapToAriaProps } from '@components/ActionMenu/Aria/helper';\nimport { MenuBlock, MenuItemType, SelectMenu } from '@components/Dropdown/SelectMenu/SelectMenu';\nimport { MenuItemStyle, MenuItemTextColorState, menuItemTextColorRecord } from '@components/MenuItem';\nimport { MenuItemContent, MenuItemContentSize } from '@components/MenuItem/MenuItemContent';\nimport { Trigger, TriggerSize } from '@components/Trigger/Trigger';\nimport { useMemoizedId } from '@hooks/useMemoizedId';\nimport { useButton } from '@react-aria/button';\nimport { FocusScope, useFocusRing } from '@react-aria/focus';\nimport { DismissButton, useOverlay } from '@react-aria/overlays';\nimport { HiddenSelect, useSelect } from '@react-aria/select';\nimport { mergeProps } from '@react-aria/utils';\nimport { useSelectState } from '@react-stately/select';\nimport { merge } from '@utilities/merge';\nimport { AnimatePresence, motion } from 'framer-motion';\nimport React, { FC, ReactElement, useEffect, useRef } from 'react';\nimport { DEFAULT_DROPDOWN_MAX_HEIGHT, useDropdownAutoHeight } from './useDropdownAutoHeight';\nimport { Validation } from '@utilities/validation';\nimport { LoadingCircle, LoadingCircleSize } from '@components/LoadingCircle';\nimport { createPortal } from 'react-dom';\nimport { usePopper } from 'react-popper';\nimport { VariationPlacement } from '@popperjs/core';\n\nexport enum DropdownSize {\n Small = 'Small',\n Large = 'Large',\n}\n\nexport enum DropdownAlignment {\n Start = 'Start',\n End = 'End',\n}\n\nexport enum DropdownPosition {\n Top = 'Top',\n Bottom = 'Bottom',\n}\n\nexport type DropdownProps = {\n id?: string;\n menuBlocks: MenuBlock[];\n onChange: (id?: string | number) => void;\n activeItemId?: string | number;\n placeholder?: string;\n size?: DropdownSize;\n disabled?: boolean;\n clearable?: boolean;\n ariaLabel?: string;\n decorator?: ReactElement;\n autoResize?: boolean;\n validation?: Validation;\n alignment?: DropdownAlignment;\n position?: DropdownPosition;\n};\n\nconst getActiveItem = (blocks: MenuBlock[], activeId: string | number): MenuItemType | null => {\n const disabledItems = getDisabledItemIds(getMenuItems(blocks));\n if (disabledItems.has(activeId)) {\n return null;\n }\n\n return (\n blocks\n .map(({ menuItems }) => menuItems)\n .flat()\n .find(({ id }) => id.toString() === activeId?.toString()) || null\n );\n};\n\nexport const Dropdown: FC<DropdownProps> = ({\n id: propId,\n menuBlocks,\n onChange,\n activeItemId,\n placeholder = 'Select item',\n size = DropdownSize.Small,\n disabled = false,\n clearable = false,\n ariaLabel = 'Dropdown',\n decorator,\n autoResize = true,\n validation = Validation.Default,\n alignment = DropdownAlignment.Start,\n position = DropdownPosition.Bottom,\n}) => {\n const activeItem = !!activeItemId ? getActiveItem(menuBlocks, activeItemId) : null;\n const props = mapToAriaProps(ariaLabel, menuBlocks);\n const state = useSelectState({\n ...props,\n defaultSelectedKey: activeItemId,\n onSelectionChange: (key) => onChange(key),\n disabledKeys: getDisabledItemIds(getMenuItems(menuBlocks)),\n });\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n\n const { triggerProps, valueProps, menuProps } = useSelect({ ...props, isDisabled: disabled }, state, triggerRef);\n\n const { buttonProps } = useButton({ ...triggerProps, isDisabled: disabled }, triggerRef);\n const { isOpen } = state;\n const { isFocusVisible, focusProps } = useFocusRing();\n const overlayRef = useRef<HTMLDivElement | null>(null);\n const { overlayProps } = useOverlay(\n { isOpen, onClose: () => state.close(), shouldCloseOnBlur: true, isDismissable: true },\n overlayRef,\n );\n\n useEffect(() => {\n if (state.disabledKeys.has(activeItemId as string)) {\n return;\n }\n\n state.setSelectedKey(activeItemId as string);\n }, [activeItemId]);\n\n const { maxHeight } = useDropdownAutoHeight(triggerRef, { isOpen, autoResize });\n\n const heightIsReady = !autoResize || maxHeight !== DEFAULT_DROPDOWN_MAX_HEIGHT;\n\n const enabledTextColorState = activeItem ? MenuItemTextColorState.Active : MenuItemTextColorState.Default;\n const textState = disabled ? MenuItemTextColorState.Disabled : enabledTextColorState;\n\n const textColorClass = activeItem\n ? menuItemTextColorRecord[activeItem.style || MenuItemStyle.Primary][textState]\n : 'tw-text-black-60';\n\n const onClear = clearable\n ? () => {\n state.setSelectedKey('');\n const first = state.collection.getFirstKey();\n if (first) {\n state.selectionManager.setFocusedKey(first);\n }\n }\n : undefined;\n\n const showClear = !!activeItem && !!onClear;\n const dropdownRef = useRef<HTMLDivElement | null>(null);\n\n const placementMap: Record<string, VariationPlacement> = {\n ['Top-Start']: 'top-start',\n ['Top-End']: 'top-end',\n ['Bottom-Start']: 'bottom-start',\n ['Bottom-End']: 'bottom-end',\n };\n const popperInstance = usePopper(triggerRef?.current, dropdownRef.current, {\n placement: placementMap[`${position}-${alignment}`],\n modifiers: [\n {\n name: 'offset',\n options: {\n offset: [0, 8],\n },\n },\n {\n name: 'flip',\n enabled: false,\n },\n ],\n });\n\n return (\n <div className=\"tw-relative tw-w-full tw-font-sans tw-text-s\">\n <Trigger\n disabled={disabled}\n buttonProps={buttonProps}\n isFocusVisible={!disabled && isFocusVisible}\n isOpen={isOpen}\n size={size === DropdownSize.Large ? TriggerSize.Large : TriggerSize.Small}\n onClear={onClear}\n showClear={showClear}\n validation={validation}\n >\n <HiddenSelect state={state} triggerRef={triggerRef} />\n <button\n {...mergeProps(buttonProps, focusProps)}\n id={useMemoizedId(propId)}\n ref={triggerRef}\n data-test-id=\"dropdown-trigger\"\n className={merge([\n 'tw-overflow-hidden tw-flex-auto tw-h-full tw-rounded tw-text-left tw-outline-none',\n size === DropdownSize.Small\n ? 'tw-py-2 tw-pl-3 tw-min-h-[34px]'\n : 'tw-pl-5 tw-py-4 tw-min-h-[60px]',\n showClear ? 'tw-pr-11' : 'tw-pr-7',\n textColorClass,\n ])}\n >\n <MenuItemContent\n ariaProps={valueProps}\n title={activeItem?.title || placeholder}\n decorator={decorator ?? activeItem?.decorator}\n size={size === DropdownSize.Small ? MenuItemContentSize.Small : MenuItemContentSize.Large}\n />\n </button>\n </Trigger>\n {createPortal(\n <AnimatePresence>\n {!disabled && isOpen && heightIsReady && (\n <motion.div\n ref={dropdownRef}\n style={{\n ...popperInstance.styles.popper,\n width: triggerRef.current?.getBoundingClientRect().width,\n minWidth: 'fit-content',\n }}\n {...popperInstance.attributes.popper}\n className=\"tw-absolute tw-p-0 tw-shadow-mid tw-list-none tw-m-0 tw-z-[120000] tw-min-w-full tw-overflow-hidden\"\n key=\"content\"\n initial={{ height: 0 }}\n animate={{ height: 'auto' }}\n transition={{ ease: [0.04, 0.62, 0.23, 0.98], duration: 0.5 }}\n >\n <FocusScope restoreFocus>\n <div\n {...overlayProps}\n ref={overlayRef}\n style={autoResize ? { maxHeight } : {}}\n className=\"tw-flex tw-flex-col\"\n data-test-id=\"dropdown-menu\"\n role=\"dialog\"\n >\n <DismissButton onDismiss={() => close()} />\n <SelectMenu\n ariaProps={menuProps}\n state={state}\n menuBlocks={menuBlocks}\n scrollable\n />\n <DismissButton onDismiss={() => close()} />\n </div>\n </FocusScope>\n </motion.div>\n )}\n </AnimatePresence>,\n document.body,\n )}\n {validation === Validation.Loading && (\n <span className=\"tw-absolute tw-top-[-0.55rem] tw-right-[-0.55rem] tw-bg-white tw-rounded-full tw-p-[2px] tw-border tw-border-black-10\">\n <LoadingCircle size={LoadingCircleSize.ExtraSmall} />\n </span>\n )}\n </div>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Dropdown.es.js","sources":["../../../src/components/Dropdown/Dropdown.tsx"],"sourcesContent":["/* (c) Copyright Frontify Ltd., all rights reserved. */\n\nimport { getDisabledItemIds, getMenuItems, mapToAriaProps } from '@components/ActionMenu/Aria/helper';\nimport { MenuBlock, MenuItemType, SelectMenu } from '@components/Dropdown/SelectMenu/SelectMenu';\nimport { MenuItemStyle, MenuItemTextColorState, menuItemTextColorRecord } from '@components/MenuItem';\nimport { MenuItemContent, MenuItemContentSize } from '@components/MenuItem/MenuItemContent';\nimport { Trigger, TriggerSize } from '@components/Trigger/Trigger';\nimport { useMemoizedId } from '@hooks/useMemoizedId';\nimport { useButton } from '@react-aria/button';\nimport { FocusScope, useFocusRing } from '@react-aria/focus';\nimport { DismissButton, useOverlay } from '@react-aria/overlays';\nimport { HiddenSelect, useSelect } from '@react-aria/select';\nimport { mergeProps } from '@react-aria/utils';\nimport { useSelectState } from '@react-stately/select';\nimport { merge } from '@utilities/merge';\nimport { AnimatePresence, motion } from 'framer-motion';\nimport React, { FC, ReactElement, useEffect, useRef } from 'react';\nimport { DEFAULT_DROPDOWN_MAX_HEIGHT, useDropdownAutoHeight } from './useDropdownAutoHeight';\nimport { Validation } from '@utilities/validation';\nimport { LoadingCircle, LoadingCircleSize } from '@components/LoadingCircle';\nimport { createPortal } from 'react-dom';\nimport { usePopper } from 'react-popper';\nimport { VariationPlacement } from '@popperjs/core';\n\nexport enum DropdownSize {\n Small = 'Small',\n Large = 'Large',\n}\n\nexport enum DropdownAlignment {\n Start = 'Start',\n End = 'End',\n}\n\nexport enum DropdownPosition {\n Top = 'Top',\n Bottom = 'Bottom',\n}\n\nexport type DropdownProps = {\n id?: string;\n menuBlocks: MenuBlock[];\n onChange: (id?: string | number) => void;\n activeItemId?: string | number;\n placeholder?: string;\n size?: DropdownSize;\n disabled?: boolean;\n clearable?: boolean;\n ariaLabel?: string;\n decorator?: ReactElement;\n autoResize?: boolean;\n validation?: Validation;\n alignment?: DropdownAlignment;\n position?: DropdownPosition;\n};\n\nconst getActiveItem = (blocks: MenuBlock[], activeId: string | number): MenuItemType | null => {\n const disabledItems = getDisabledItemIds(getMenuItems(blocks));\n if (disabledItems.has(activeId)) {\n return null;\n }\n\n return (\n blocks\n .map(({ menuItems }) => menuItems)\n .flat()\n .find(({ id }) => id.toString() === activeId?.toString()) || null\n );\n};\n\nexport const Dropdown: FC<DropdownProps> = ({\n id: propId,\n menuBlocks,\n onChange,\n activeItemId,\n placeholder = 'Select item',\n size = DropdownSize.Small,\n disabled = false,\n clearable = false,\n ariaLabel = 'Dropdown',\n decorator,\n autoResize = true,\n validation = Validation.Default,\n alignment = DropdownAlignment.Start,\n position = DropdownPosition.Bottom,\n}) => {\n const activeItem = !!activeItemId ? getActiveItem(menuBlocks, activeItemId) : null;\n const props = mapToAriaProps(ariaLabel, menuBlocks);\n const state = useSelectState({\n ...props,\n defaultSelectedKey: activeItemId,\n onSelectionChange: (key) => onChange(key),\n disabledKeys: getDisabledItemIds(getMenuItems(menuBlocks)),\n });\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n\n const { triggerProps, valueProps, menuProps } = useSelect({ ...props, isDisabled: disabled }, state, triggerRef);\n\n const { buttonProps } = useButton({ ...triggerProps, isDisabled: disabled }, triggerRef);\n const { isOpen } = state;\n const { isFocusVisible, focusProps } = useFocusRing();\n const overlayRef = useRef<HTMLDivElement | null>(null);\n const { overlayProps } = useOverlay(\n { isOpen, onClose: () => state.close(), shouldCloseOnBlur: true, isDismissable: true },\n overlayRef,\n );\n\n useEffect(() => {\n if (state.disabledKeys.has(activeItemId as string)) {\n return;\n }\n\n state.setSelectedKey(activeItemId as string);\n }, [activeItemId]);\n\n const { maxHeight } = useDropdownAutoHeight(triggerRef, { isOpen, autoResize });\n\n const heightIsReady = !autoResize || maxHeight !== DEFAULT_DROPDOWN_MAX_HEIGHT;\n\n const enabledTextColorState = activeItem ? MenuItemTextColorState.Active : MenuItemTextColorState.Default;\n const textState = disabled ? MenuItemTextColorState.Disabled : enabledTextColorState;\n\n const textColorClass = activeItem\n ? menuItemTextColorRecord[activeItem.style || MenuItemStyle.Primary][textState]\n : 'tw-text-black-60';\n\n const onClear = clearable\n ? () => {\n state.setSelectedKey('');\n const first = state.collection.getFirstKey();\n if (first) {\n state.selectionManager.setFocusedKey(first);\n }\n }\n : undefined;\n\n const showClear = !!activeItem && !!onClear;\n const dropdownRef = useRef<HTMLDivElement | null>(null);\n\n const placementMap: Record<string, VariationPlacement> = {\n ['Top-Start']: 'top-start',\n ['Top-End']: 'top-end',\n ['Bottom-Start']: 'bottom-start',\n ['Bottom-End']: 'bottom-end',\n };\n const popperInstance = usePopper(triggerRef?.current, dropdownRef.current, {\n placement: placementMap[`${position}-${alignment}`],\n strategy: 'fixed',\n modifiers: [\n {\n name: 'offset',\n options: {\n offset: [0, 8],\n },\n },\n {\n name: 'flip',\n enabled: false,\n },\n ],\n });\n\n return (\n <div className=\"tw-relative tw-w-full tw-font-sans tw-text-s\">\n <Trigger\n disabled={disabled}\n buttonProps={buttonProps}\n isFocusVisible={!disabled && isFocusVisible}\n isOpen={isOpen}\n size={size === DropdownSize.Large ? TriggerSize.Large : TriggerSize.Small}\n onClear={onClear}\n showClear={showClear}\n validation={validation}\n >\n <HiddenSelect state={state} triggerRef={triggerRef} />\n <button\n {...mergeProps(buttonProps, focusProps)}\n id={useMemoizedId(propId)}\n ref={triggerRef}\n data-test-id=\"dropdown-trigger\"\n className={merge([\n 'tw-overflow-hidden tw-flex-auto tw-h-full tw-rounded tw-text-left tw-outline-none',\n size === DropdownSize.Small\n ? 'tw-py-2 tw-pl-3 tw-min-h-[34px]'\n : 'tw-pl-5 tw-py-4 tw-min-h-[60px]',\n showClear ? 'tw-pr-11' : 'tw-pr-7',\n textColorClass,\n ])}\n >\n <MenuItemContent\n ariaProps={valueProps}\n title={activeItem?.title || placeholder}\n decorator={decorator ?? activeItem?.decorator}\n size={size === DropdownSize.Small ? MenuItemContentSize.Small : MenuItemContentSize.Large}\n />\n </button>\n </Trigger>\n {createPortal(\n <AnimatePresence>\n {!disabled && isOpen && heightIsReady && (\n <motion.div\n ref={dropdownRef}\n style={{\n ...popperInstance.styles.popper,\n width: triggerRef.current?.getBoundingClientRect().width,\n minWidth: 'fit-content',\n }}\n {...popperInstance.attributes.popper}\n className=\"tw-absolute tw-p-0 tw-shadow-mid tw-list-none tw-m-0 tw-z-[120000] tw-min-w-full tw-overflow-hidden\"\n key=\"content\"\n initial={{ height: 0 }}\n animate={{ height: 'auto' }}\n transition={{ ease: [0.04, 0.62, 0.23, 0.98], duration: 0.5 }}\n >\n <FocusScope restoreFocus>\n <div\n {...overlayProps}\n ref={overlayRef}\n style={autoResize ? { maxHeight } : {}}\n className=\"tw-flex tw-flex-col\"\n data-test-id=\"dropdown-menu\"\n role=\"dialog\"\n >\n <DismissButton onDismiss={() => close()} />\n <SelectMenu\n ariaProps={menuProps}\n state={state}\n menuBlocks={menuBlocks}\n scrollable\n />\n <DismissButton onDismiss={() => close()} />\n </div>\n </FocusScope>\n </motion.div>\n )}\n </AnimatePresence>,\n document.body,\n )}\n {validation === Validation.Loading && (\n <span className=\"tw-absolute tw-top-[-0.55rem] tw-right-[-0.55rem] tw-bg-white tw-rounded-full tw-p-[2px] tw-border tw-border-black-10\">\n <LoadingCircle size={LoadingCircleSize.ExtraSmall} />\n </span>\n )}\n </div>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { Checklist as
|
|
2
|
-
import { Tag as
|
|
1
|
+
import { Checklist as P, ChecklistDirection as T } from "../Checklist/Checklist.es.js";
|
|
2
|
+
import { Tag as w, TagType as s, TagSize as i } from "../Tag/Tag.es.js";
|
|
3
3
|
import { Trigger as C } from "../Trigger/Trigger.es.js";
|
|
4
4
|
import { useButton as F } from "@react-aria/button";
|
|
5
|
-
import { useFocusRing as
|
|
5
|
+
import { useFocusRing as k, FocusScope as z } from "@react-aria/focus";
|
|
6
6
|
import { useOverlay as R } from "@react-aria/overlays";
|
|
7
7
|
import { mergeProps as M } from "@react-aria/utils";
|
|
8
8
|
import { merge as V } from "../../utilities/merge.es.js";
|
|
9
9
|
import { AnimatePresence as A, motion as B } from "framer-motion";
|
|
10
10
|
import t, { useState as W, useRef as h } from "react";
|
|
11
|
-
import {
|
|
11
|
+
import { getPaddingClasses as j } from "./helpers.es.js";
|
|
12
12
|
var L = /* @__PURE__ */ ((l) => (l.Default = "Default", l.Summarized = "Summarized", l))(L || {}), U = /* @__PURE__ */ ((l) => (l.Small = "Small", l.Medium = "Medium", l))(U || {});
|
|
13
13
|
const I = ({
|
|
14
14
|
items: l,
|
|
@@ -17,16 +17,16 @@ const I = ({
|
|
|
17
17
|
ariaLabel: S = "Select list",
|
|
18
18
|
disabled: b = !1,
|
|
19
19
|
placeholder: u,
|
|
20
|
-
type:
|
|
20
|
+
type: f = "Default",
|
|
21
21
|
size: m = "Medium"
|
|
22
22
|
}) => {
|
|
23
|
-
const [o, c] = W(!1),
|
|
23
|
+
const [o, c] = W(!1), d = h(null), p = h(null), { isFocusVisible: E, focusProps: v } = k(), x = l.map((e) => ({ ...e, label: e.value })), { overlayProps: N } = R({
|
|
24
24
|
isOpen: o,
|
|
25
25
|
onClose: () => c(!1),
|
|
26
26
|
shouldCloseOnBlur: !0,
|
|
27
27
|
isDismissable: !0,
|
|
28
28
|
shouldCloseOnInteractOutside: (e) => e && e.tagName !== "BUTTON" && e.tagName !== "svg"
|
|
29
|
-
},
|
|
29
|
+
}, d), { buttonProps: g } = F({
|
|
30
30
|
onPress: () => {
|
|
31
31
|
c(!0);
|
|
32
32
|
},
|
|
@@ -34,32 +34,32 @@ const I = ({
|
|
|
34
34
|
e.key === "Escape" && c(!1);
|
|
35
35
|
},
|
|
36
36
|
elementType: "div"
|
|
37
|
-
},
|
|
38
|
-
const
|
|
39
|
-
|
|
37
|
+
}, p), O = (e) => {
|
|
38
|
+
const a = new Set(r);
|
|
39
|
+
a.has(e) ? a.delete(e) : a.add(e), n(Array.from(a));
|
|
40
40
|
}, D = [r.length, `option${r.length > 1 ? "s" : ""}`, "selected"].join(" ");
|
|
41
41
|
return /* @__PURE__ */ t.createElement("div", {
|
|
42
42
|
className: "tw-relative"
|
|
43
43
|
}, /* @__PURE__ */ t.createElement(C, {
|
|
44
44
|
disabled: b,
|
|
45
|
-
buttonProps:
|
|
45
|
+
buttonProps: g,
|
|
46
46
|
isFocusVisible: E,
|
|
47
47
|
isOpen: o
|
|
48
48
|
}, /* @__PURE__ */ t.createElement("div", {
|
|
49
|
-
...M(
|
|
50
|
-
ref:
|
|
49
|
+
...M(g, v),
|
|
50
|
+
ref: p,
|
|
51
51
|
className: V([
|
|
52
|
-
"tw-flex-1 tw-flex tw-flex-wrap tw-gap-1 tw-
|
|
52
|
+
"tw-flex-1 tw-flex tw-flex-wrap tw-gap-1 tw-min-h-[34px] tw-outline-none",
|
|
53
53
|
j(m, r.length > 0)
|
|
54
54
|
])
|
|
55
|
-
},
|
|
55
|
+
}, f === "Default" && r.map((e) => /* @__PURE__ */ t.createElement(w, {
|
|
56
56
|
key: e,
|
|
57
|
-
type: o ?
|
|
57
|
+
type: o ? s.SelectedWithFocus : s.Selected,
|
|
58
58
|
label: e.toString(),
|
|
59
59
|
size: m === "Small" ? i.Small : i.Medium,
|
|
60
60
|
onClick: () => O(e)
|
|
61
|
-
})),
|
|
62
|
-
type: o ?
|
|
61
|
+
})), f === "Summarized" && r.length > 0 && /* @__PURE__ */ t.createElement(w, {
|
|
62
|
+
type: o ? s.SelectedWithFocus : s.Selected,
|
|
63
63
|
label: D,
|
|
64
64
|
size: m === "Small" ? i.Small : i.Medium,
|
|
65
65
|
onClick: () => n([])
|
|
@@ -72,17 +72,17 @@ const I = ({
|
|
|
72
72
|
animate: { height: "auto" },
|
|
73
73
|
exit: { height: 0 },
|
|
74
74
|
transition: { ease: [0.04, 0.62, 0.23, 0.98] }
|
|
75
|
-
}, /* @__PURE__ */ t.createElement(
|
|
75
|
+
}, /* @__PURE__ */ t.createElement(z, {
|
|
76
76
|
restoreFocus: !0
|
|
77
77
|
}, /* @__PURE__ */ t.createElement("div", {
|
|
78
78
|
...N,
|
|
79
|
-
ref:
|
|
79
|
+
ref: d,
|
|
80
80
|
className: "tw-p-4"
|
|
81
|
-
}, /* @__PURE__ */ t.createElement(
|
|
81
|
+
}, /* @__PURE__ */ t.createElement(P, {
|
|
82
82
|
activeValues: r.map((e) => e.toString()),
|
|
83
83
|
setActiveValues: n,
|
|
84
84
|
checkboxes: x,
|
|
85
|
-
direction:
|
|
85
|
+
direction: T.Vertical,
|
|
86
86
|
ariaLabel: S
|
|
87
87
|
}))))));
|
|
88
88
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultiSelect.es.js","sources":["../../../src/components/MultiSelect/MultiSelect.tsx"],"sourcesContent":["/* (c) Copyright Frontify Ltd., all rights reserved. */\n\nimport { Checklist, ChecklistDirection } from '@components/Checklist/Checklist';\nimport { Tag, TagSize, TagType } from '@components/Tag/Tag';\nimport { Trigger } from '@components/Trigger/Trigger';\nimport { useButton } from '@react-aria/button';\nimport { FocusScope, useFocusRing } from '@react-aria/focus';\nimport { useOverlay } from '@react-aria/overlays';\nimport { mergeProps } from '@react-aria/utils';\nimport { merge } from '@utilities/merge';\nimport { AnimatePresence, motion } from 'framer-motion';\nimport React, { FC, useRef, useState } from 'react';\nimport {
|
|
1
|
+
{"version":3,"file":"MultiSelect.es.js","sources":["../../../src/components/MultiSelect/MultiSelect.tsx"],"sourcesContent":["/* (c) Copyright Frontify Ltd., all rights reserved. */\n\nimport { Checklist, ChecklistDirection } from '@components/Checklist/Checklist';\nimport { Tag, TagSize, TagType } from '@components/Tag/Tag';\nimport { Trigger } from '@components/Trigger/Trigger';\nimport { useButton } from '@react-aria/button';\nimport { FocusScope, useFocusRing } from '@react-aria/focus';\nimport { useOverlay } from '@react-aria/overlays';\nimport { mergeProps } from '@react-aria/utils';\nimport { merge } from '@utilities/merge';\nimport { AnimatePresence, motion } from 'framer-motion';\nimport React, { FC, useRef, useState } from 'react';\nimport { getPaddingClasses } from './helpers';\n\nexport enum MultiSelectType {\n Default = 'Default',\n Summarized = 'Summarized',\n}\n\nexport enum MultiSelectSize {\n Small = 'Small',\n Medium = 'Medium',\n}\n\nexport type MultiSelectItem = {\n value: string;\n ariaLabel?: string;\n};\n\nexport type MultiSelectProps = {\n items: MultiSelectItem[];\n activeItemKeys: (string | number)[];\n disabled?: boolean;\n onSelectionChange: (keys: (string | number)[]) => void;\n ariaLabel?: string;\n placeholder?: string;\n type?: MultiSelectType;\n size?: MultiSelectSize;\n};\n\nexport const MultiSelect: FC<MultiSelectProps> = ({\n items,\n activeItemKeys,\n onSelectionChange,\n ariaLabel = 'Select list',\n disabled = false,\n placeholder,\n type = MultiSelectType.Default,\n size = MultiSelectSize.Medium,\n}) => {\n const [open, setOpen] = useState(false);\n const overlayRef = useRef<HTMLDivElement | null>(null);\n const triggerRef = useRef<HTMLDivElement | null>(null);\n const { isFocusVisible, focusProps } = useFocusRing();\n const checkboxes = items.map((item) => ({ ...item, label: item.value }));\n\n const { overlayProps } = useOverlay(\n {\n isOpen: open,\n onClose: () => setOpen(false),\n shouldCloseOnBlur: true,\n isDismissable: true,\n shouldCloseOnInteractOutside: (element) =>\n element && element.tagName !== 'BUTTON' && element.tagName !== 'svg',\n },\n overlayRef,\n );\n\n const { buttonProps } = useButton(\n {\n onPress: () => {\n setOpen(true);\n },\n onKeyDown: (e) => {\n if (e.key === 'Escape') {\n setOpen(false);\n }\n },\n elementType: 'div',\n },\n triggerRef,\n );\n\n const toggleSelection = (key: string | number) => {\n const keySet = new Set(activeItemKeys);\n\n if (keySet.has(key)) {\n keySet.delete(key);\n } else {\n keySet.add(key);\n }\n\n onSelectionChange(Array.from(keySet));\n };\n\n const summarizedLabel = [activeItemKeys.length, `option${activeItemKeys.length > 1 ? 's' : ''}`, 'selected'].join(\n ' ',\n );\n\n return (\n <div className=\"tw-relative\">\n <Trigger disabled={disabled} buttonProps={buttonProps} isFocusVisible={isFocusVisible} isOpen={open}>\n <div\n {...mergeProps(buttonProps, focusProps)}\n ref={triggerRef}\n className={merge([\n 'tw-flex-1 tw-flex tw-flex-wrap tw-gap-1 tw-min-h-[34px] tw-outline-none',\n getPaddingClasses(size, activeItemKeys.length > 0),\n ])}\n >\n {type === MultiSelectType.Default &&\n activeItemKeys.map((key) => (\n <Tag\n key={key}\n type={open ? TagType.SelectedWithFocus : TagType.Selected}\n label={key.toString()}\n size={size === MultiSelectSize.Small ? TagSize.Small : TagSize.Medium}\n onClick={() => toggleSelection(key)}\n />\n ))}\n\n {type === MultiSelectType.Summarized && activeItemKeys.length > 0 && (\n <Tag\n type={open ? TagType.SelectedWithFocus : TagType.Selected}\n label={summarizedLabel}\n size={size === MultiSelectSize.Small ? TagSize.Small : TagSize.Medium}\n onClick={() => onSelectionChange([])}\n />\n )}\n\n {activeItemKeys.length === 0 && placeholder && (\n <div className=\"tw-text-black-60 tw-text-s\">{placeholder}</div>\n )}\n </div>\n </Trigger>\n <AnimatePresence>\n {open && (\n <motion.div\n className=\"tw-absolute tw-left-0 tw-w-full tw-overflow-hidden tw-p-0 tw-shadow-mid tw-list-none tw-m-0 tw-mt-2 tw-z-10 tw-bg-base\"\n key=\"content\"\n initial={{ height: 0 }}\n animate={{ height: 'auto' }}\n exit={{ height: 0 }}\n transition={{ ease: [0.04, 0.62, 0.23, 0.98] }}\n >\n <FocusScope restoreFocus>\n <div {...overlayProps} ref={overlayRef} className=\"tw-p-4\">\n <Checklist\n activeValues={activeItemKeys.map((key) => key.toString())}\n setActiveValues={onSelectionChange}\n checkboxes={checkboxes}\n direction={ChecklistDirection.Vertical}\n ariaLabel={ariaLabel}\n />\n </div>\n </FocusScope>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { MultiSelectSize } from './MultiSelect';
|
|
2
|
-
export declare const
|
|
2
|
+
export declare const getPaddingClasses: (size: MultiSelectSize, hasActiveKeys: boolean) => string | undefined;
|
|
@@ -1,6 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { merge as s } from "../../utilities/merge.es.js";
|
|
2
|
+
import { MultiSelectSize as e } from "./MultiSelect.es.js";
|
|
3
|
+
const c = (p, r) => {
|
|
4
|
+
const t = ["tw-pr-9"];
|
|
5
|
+
switch (p) {
|
|
6
|
+
case e.Small:
|
|
7
|
+
t.push(`tw-pl-3 ${r ? "tw-py-1" : "tw-py-2"}`);
|
|
8
|
+
break;
|
|
9
|
+
case e.Medium:
|
|
10
|
+
t.push("tw-pl-[19px] tw-py-[11px]");
|
|
11
|
+
break;
|
|
12
|
+
default:
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
return s(t);
|
|
16
|
+
};
|
|
3
17
|
export {
|
|
4
|
-
|
|
18
|
+
c as getPaddingClasses
|
|
5
19
|
};
|
|
6
20
|
//# sourceMappingURL=helpers.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.es.js","sources":["../../../src/components/MultiSelect/helpers.ts"],"sourcesContent":["import { MultiSelectSize } from './MultiSelect';\n\nexport const
|
|
1
|
+
{"version":3,"file":"helpers.es.js","sources":["../../../src/components/MultiSelect/helpers.ts"],"sourcesContent":["import { merge } from '@utilities/merge';\nimport { MultiSelectSize } from './MultiSelect';\n\nexport const getPaddingClasses = (size: MultiSelectSize, hasActiveKeys: boolean) => {\n const classes = ['tw-pr-9'];\n switch (size) {\n case MultiSelectSize.Small:\n classes.push(`tw-pl-3 ${hasActiveKeys ? 'tw-py-1' : 'tw-py-2'}`);\n break;\n case MultiSelectSize.Medium:\n classes.push('tw-pl-[19px] tw-py-[11px]');\n break;\n default:\n return;\n }\n\n return merge(classes);\n};\n"],"names":[],"mappings":";;AAGa,MAAA,IAAoB,CAAC,GAAuB,MAA2B;AAC1E,QAAA,IAAU,CAAC,SAAS;AAClB,UAAA;AAAA,SACC,EAAgB;AACjB,QAAQ,KAAK,WAAW,IAAgB,YAAY,WAAW;AAC/D;AAAA,SACC,EAAgB;AACjB,QAAQ,KAAK,2BAA2B;AACxC;AAAA;AAEA;AAAA;AAGR,SAAO,EAAM,CAAO;AACxB;"}
|
|
@@ -2,9 +2,9 @@ import { Button as I, ButtonStyle as _, ButtonSize as P } from "../Button/Button
|
|
|
2
2
|
import { IconSize as $ } from "../../foundation/Icon/IconSize.es.js";
|
|
3
3
|
import { useLink as re } from "@react-aria/link";
|
|
4
4
|
import { FOCUS_VISIBLE_STYLE as oe } from "../../utilities/focusStyle.es.js";
|
|
5
|
-
import { merge as
|
|
5
|
+
import { merge as d } from "../../utilities/merge.es.js";
|
|
6
6
|
import e, { useRef as f, useMemo as ae, useState as V, useCallback as E, cloneElement as x } from "react";
|
|
7
|
-
import { BrightHeader as se, brightHeaderArrowBackgroundColors as
|
|
7
|
+
import { BrightHeader as se, brightHeaderArrowBackgroundColors as k } from "./BrightHeader.es.js";
|
|
8
8
|
import { usePopper as le } from "react-popper";
|
|
9
9
|
import { createPortal as ce } from "react-dom";
|
|
10
10
|
const Y = {
|
|
@@ -15,7 +15,7 @@ const Y = {
|
|
|
15
15
|
large: "tw-pb-4"
|
|
16
16
|
};
|
|
17
17
|
var ne = /* @__PURE__ */ ((t) => (t.Top = "Top", t.Right = "Right", t.Bottom = "Bottom", t.Left = "Left", t))(ne || {}), we = /* @__PURE__ */ ((t) => (t.Start = "Start", t.Middle = "Middle", t.End = "End", t))(we || {});
|
|
18
|
-
const
|
|
18
|
+
const de = {
|
|
19
19
|
["Top-Start"]: "top-start",
|
|
20
20
|
["Top-End"]: "top-end",
|
|
21
21
|
["Bottom-Start"]: "bottom-start",
|
|
@@ -28,48 +28,49 @@ const me = {
|
|
|
28
28
|
["Right-Middle"]: "right",
|
|
29
29
|
["Bottom-Middle"]: "bottom",
|
|
30
30
|
["Left-Middle"]: "left"
|
|
31
|
-
},
|
|
31
|
+
}, me = (t, a, w) => {
|
|
32
32
|
switch (!0) {
|
|
33
33
|
case t.toString().includes("Top".toLowerCase()):
|
|
34
34
|
return "before:tw-border-t-0 before:tw-border-l-0 tw-bottom-[-6px] before:tw-bg-black-100 before:dark:tw-bg-white";
|
|
35
35
|
case t.toString().includes("Right".toLowerCase()):
|
|
36
|
-
return
|
|
36
|
+
return d([
|
|
37
37
|
"before:tw-border-t-0 before:tw-border-r-0 tw-left-[-6px]",
|
|
38
|
-
a && w === "Start" ?
|
|
38
|
+
a && w === "Start" ? k[a] : "before:tw-bg-black-100 before:dark:tw-bg-white"
|
|
39
39
|
]);
|
|
40
40
|
case t.toString().includes("Bottom".toLowerCase()):
|
|
41
|
-
return
|
|
41
|
+
return d([
|
|
42
42
|
"before:tw-border-b-0 before:tw-border-r-0 tw-top-[-6px]",
|
|
43
|
-
a ?
|
|
43
|
+
a ? k[a] : "before:tw-bg-black-100 before:dark:tw-bg-white"
|
|
44
44
|
]);
|
|
45
45
|
case t.toString().includes("Left".toLowerCase()):
|
|
46
|
-
return
|
|
46
|
+
return d([
|
|
47
47
|
"before:tw-border-b-0 before:tw-border-l-0 tw-right-[-6px]",
|
|
48
|
-
a && w === "Start" ?
|
|
48
|
+
a && w === "Start" ? k[a] : "before:tw-bg-black-100 before:dark:tw-bg-white"
|
|
49
49
|
]);
|
|
50
50
|
default:
|
|
51
51
|
return "before:tw-border-b-0 before:tw-border-r-0 tw-top-[-6px] before:tw-bg-black-100 before:dark:tw-bg-white";
|
|
52
52
|
}
|
|
53
|
-
},
|
|
53
|
+
}, ke = ({
|
|
54
54
|
content: t,
|
|
55
55
|
tooltipIcon: a,
|
|
56
56
|
heading: w,
|
|
57
57
|
headingIcon: u,
|
|
58
58
|
linkUrl: l,
|
|
59
59
|
linkLabel: S,
|
|
60
|
-
brightHeader:
|
|
60
|
+
brightHeader: m,
|
|
61
61
|
buttons: r,
|
|
62
62
|
children: q,
|
|
63
|
-
position:
|
|
63
|
+
position: B = "Bottom",
|
|
64
64
|
alignment: g = "Middle",
|
|
65
65
|
withArrow: b,
|
|
66
66
|
flip: D = !0,
|
|
67
|
-
triggerElement:
|
|
67
|
+
triggerElement: y,
|
|
68
68
|
hoverDelay: G = 200
|
|
69
69
|
}) => {
|
|
70
70
|
var z, T;
|
|
71
|
-
const o = f(null),
|
|
71
|
+
const o = f(null), M = f(null), { linkProps: J } = re({}, M), K = ae(() => l || m || r || w || u, [l, m, r, w, u]), Q = de[`${B}-${g}`], s = f(null), p = f(null), [W, X] = V(null), Z = b ? 10 : 5, i = le(o == null ? void 0 : o.current, s.current, {
|
|
72
72
|
placement: Q,
|
|
73
|
+
strategy: "fixed",
|
|
73
74
|
modifiers: [
|
|
74
75
|
{
|
|
75
76
|
name: "arrow",
|
|
@@ -88,7 +89,7 @@ const me = {
|
|
|
88
89
|
enabled: D
|
|
89
90
|
}
|
|
90
91
|
]
|
|
91
|
-
}), R = (T = (z = i.state) == null ? void 0 : z.placement) != null ? T :
|
|
92
|
+
}), R = (T = (z = i.state) == null ? void 0 : z.placement) != null ? T : B, A = me(R, m, g), [H, c] = V(!1), h = f(null), U = E(() => {
|
|
92
93
|
h.current && clearTimeout(h.current), c(!0);
|
|
93
94
|
}, [o == null ? void 0 : o.current]), L = E(() => {
|
|
94
95
|
h.current = setTimeout(() => c(!1), G);
|
|
@@ -105,7 +106,7 @@ const me = {
|
|
|
105
106
|
return /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement("div", {
|
|
106
107
|
...te,
|
|
107
108
|
ref: p
|
|
108
|
-
},
|
|
109
|
+
}, y && x(y, {
|
|
109
110
|
ref: o
|
|
110
111
|
})), ce(/* @__PURE__ */ e.createElement("div", null, H && /* @__PURE__ */ e.createElement("div", {
|
|
111
112
|
ref: s,
|
|
@@ -117,10 +118,10 @@ const me = {
|
|
|
117
118
|
onFocus: () => c(!0),
|
|
118
119
|
onMouseOver: (n) => N(n.nativeEvent),
|
|
119
120
|
onMouseLeave: L
|
|
120
|
-
},
|
|
121
|
-
headerStyle:
|
|
121
|
+
}, m && /* @__PURE__ */ e.createElement(se, {
|
|
122
|
+
headerStyle: m
|
|
122
123
|
}), /* @__PURE__ */ e.createElement("div", {
|
|
123
|
-
className:
|
|
124
|
+
className: d([
|
|
124
125
|
"tw-px-4",
|
|
125
126
|
K ? Y.small : Y.large,
|
|
126
127
|
l ? j.small : j.large
|
|
@@ -134,15 +135,15 @@ const me = {
|
|
|
134
135
|
}, a && /* @__PURE__ */ e.createElement("span", {
|
|
135
136
|
className: "tw-shrink-0 tw-mr-1"
|
|
136
137
|
}, x(a, { size: $.Size16 })), /* @__PURE__ */ e.createElement("p", {
|
|
137
|
-
className: "tw-text-s"
|
|
138
|
+
className: "tw-text-s tw-min-w-0 tw-break-words"
|
|
138
139
|
}, t)), l && /* @__PURE__ */ e.createElement("a", {
|
|
139
140
|
...J,
|
|
140
141
|
"data-test-id": "tooltip-link",
|
|
141
|
-
ref:
|
|
142
|
+
ref: M,
|
|
142
143
|
href: l,
|
|
143
144
|
target: "_blank",
|
|
144
145
|
rel: "noopener noreferrer",
|
|
145
|
-
className:
|
|
146
|
+
className: d([
|
|
146
147
|
"tw-text-xs tw-text-black-40 dark:tw-text-black-80 tw-underline tw-mt-1",
|
|
147
148
|
oe
|
|
148
149
|
]),
|
|
@@ -168,14 +169,14 @@ const me = {
|
|
|
168
169
|
"data-popper-arrow": b,
|
|
169
170
|
ref: X,
|
|
170
171
|
style: i.styles.arrow,
|
|
171
|
-
className:
|
|
172
|
+
className: d([
|
|
172
173
|
b && "tw-popper-arrow tw-absolute tw-w-3 tw-h-3 tw-pointer-events-none before:tw-absolute before:tw-w-3 before:tw-h-3 before:tw-rotate-45 before:tw-border before:tw-border-line",
|
|
173
174
|
b && A
|
|
174
175
|
])
|
|
175
176
|
})), q)), document.body));
|
|
176
177
|
};
|
|
177
178
|
export {
|
|
178
|
-
|
|
179
|
+
ke as Tooltip,
|
|
179
180
|
we as TooltipAlignment,
|
|
180
181
|
ne as TooltipPosition
|
|
181
182
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip.es.js","sources":["../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["/* (c) Copyright Frontify Ltd., all rights reserved. */\n\nimport { Button, ButtonSize, ButtonStyle } from '@components/Button/Button';\nimport { IconSize } from '@foundation/Icon/IconSize';\nimport { useLink } from '@react-aria/link';\nimport { FOCUS_VISIBLE_STYLE } from '@utilities/focusStyle';\nimport { merge } from '@utilities/merge';\nimport React, {\n HTMLAttributes,\n PropsWithChildren,\n ReactChild,\n ReactElement,\n ReactNode,\n cloneElement,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { BrightHeader, BrightHeaderStyle, brightHeaderArrowBackgroundColors } from './BrightHeader';\nimport { usePopper } from 'react-popper';\nimport { createPortal } from 'react-dom';\nimport { Placement } from '@popperjs/core';\n\nexport type TooltipButton = {\n label: string;\n action: () => void;\n};\n\nexport type TooltipProps = PropsWithChildren<{\n triggerElement?: ReactElement;\n content: ReactNode;\n tooltipIcon?: ReactElement;\n heading?: ReactNode;\n headingIcon?: ReactElement;\n linkUrl?: string;\n linkLabel?: string;\n brightHeader?: BrightHeaderStyle;\n buttons?: [TooltipButton, TooltipButton] | [TooltipButton];\n children?: ReactChild;\n position?: TooltipPosition;\n alignment?: TooltipAlignment;\n flip?: boolean;\n withArrow?: boolean;\n hoverDelay?: number;\n}>;\n\n/**\n * This is a temporary workaround because for some yet unknown reasons `tailwindcss` in clarify purges the `tw-pb-3.5` and `tw-pt-3.5` class.\n */\nconst paddingsTop = {\n small: 'tw-pt-3.5',\n large: 'tw-pt-4',\n};\n\nconst paddingsBottom = {\n small: 'tw-pb-3.5',\n large: 'tw-pb-4',\n};\n\nexport enum TooltipPosition {\n Top = 'Top',\n Right = 'Right',\n Bottom = 'Bottom',\n Left = 'Left',\n}\n\nexport enum TooltipAlignment {\n Start = 'Start',\n Middle = 'Middle',\n End = 'End',\n}\n\nconst placementMap: Record<`${TooltipPosition}-${TooltipAlignment}`, Placement> = {\n ['Top-Start']: 'top-start',\n ['Top-End']: 'top-end',\n ['Bottom-Start']: 'bottom-start',\n ['Bottom-End']: 'bottom-end',\n ['Left-Start']: 'left-start',\n ['Left-End']: 'left-end',\n ['Right-Start']: 'right-start',\n ['Right-End']: 'right-end',\n ['Top-Middle']: 'top',\n ['Right-Middle']: 'right',\n ['Bottom-Middle']: 'bottom',\n ['Left-Middle']: 'left',\n};\n\nconst getArrowClasses = (currentPlacement: string, brightHeader: BrightHeaderStyle | undefined, alignment: string) => {\n switch (true) {\n case currentPlacement.toString().includes(TooltipPosition.Top.toLowerCase()):\n return 'before:tw-border-t-0 before:tw-border-l-0 tw-bottom-[-6px] before:tw-bg-black-100 before:dark:tw-bg-white';\n case currentPlacement.toString().includes(TooltipPosition.Right.toLowerCase()):\n return merge([\n 'before:tw-border-t-0 before:tw-border-r-0 tw-left-[-6px]',\n brightHeader && alignment === TooltipAlignment.Start\n ? brightHeaderArrowBackgroundColors[brightHeader]\n : 'before:tw-bg-black-100 before:dark:tw-bg-white',\n ]);\n case currentPlacement.toString().includes(TooltipPosition.Bottom.toLowerCase()):\n return merge([\n 'before:tw-border-b-0 before:tw-border-r-0 tw-top-[-6px]',\n brightHeader\n ? brightHeaderArrowBackgroundColors[brightHeader]\n : 'before:tw-bg-black-100 before:dark:tw-bg-white',\n ]);\n case currentPlacement.toString().includes(TooltipPosition.Left.toLowerCase()):\n return merge([\n 'before:tw-border-b-0 before:tw-border-l-0 tw-right-[-6px]',\n brightHeader && alignment === TooltipAlignment.Start\n ? brightHeaderArrowBackgroundColors[brightHeader]\n : 'before:tw-bg-black-100 before:dark:tw-bg-white',\n ]);\n default:\n return 'before:tw-border-b-0 before:tw-border-r-0 tw-top-[-6px] before:tw-bg-black-100 before:dark:tw-bg-white';\n }\n};\n\nexport const Tooltip = ({\n content,\n tooltipIcon,\n heading,\n headingIcon,\n linkUrl,\n linkLabel,\n brightHeader,\n buttons,\n children,\n position = TooltipPosition.Bottom,\n alignment = TooltipAlignment.Middle,\n withArrow,\n flip = true,\n triggerElement,\n hoverDelay = 200,\n}: TooltipProps) => {\n const triggerRefElement = useRef<HTMLElement | HTMLDivElement | HTMLButtonElement | null>(null);\n const linkRef = useRef<HTMLAnchorElement | null>(null);\n const { linkProps } = useLink({}, linkRef);\n const hasLargePaddingTop = useMemo(\n () => linkUrl || brightHeader || buttons || heading || headingIcon,\n [linkUrl, brightHeader, buttons, heading, headingIcon],\n );\n\n const placement = placementMap[`${position}-${alignment}`];\n const tooltipContainerRef = useRef<HTMLDivElement | null>(null);\n const triggerElementContainerRef = useRef<HTMLDivElement | null>(null);\n const [arrowElement, setArrowElement] = useState<HTMLDivElement | null>(null);\n\n const tooltipOffset = withArrow ? 10 : 5;\n const popperInstance = usePopper(triggerRefElement?.current, tooltipContainerRef.current, {\n placement,\n modifiers: [\n {\n name: 'arrow',\n options: {\n element: arrowElement,\n },\n },\n {\n name: 'offset',\n options: {\n offset: [0, tooltipOffset],\n },\n },\n {\n name: 'flip',\n enabled: flip,\n },\n ],\n });\n\n const currentPlacement = popperInstance.state?.placement ?? position;\n const arrowStyling = getArrowClasses(currentPlacement, brightHeader, alignment);\n const [isOpen, setIsOpen] = useState(false);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const handleShowTooltipOnHover = useCallback(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n setIsOpen(true);\n }, [triggerRefElement?.current]);\n\n const handleHideTooltipOnHover = useCallback(() => {\n timeoutRef.current = setTimeout(() => setIsOpen(false), hoverDelay);\n }, [triggerRefElement?.current, tooltipContainerRef?.current]);\n\n const checkIfHovered = useCallback(\n (event) => {\n const hoveredElement = event.path ?? event.composedPath?.();\n const hoverSources = [triggerRefElement, triggerElementContainerRef, tooltipContainerRef];\n\n if (hoveredElement && hoverSources.some((el) => hoveredElement.includes(el?.current))) {\n handleShowTooltipOnHover();\n }\n },\n [triggerRefElement?.current, tooltipContainerRef?.current, triggerElementContainerRef?.current],\n );\n\n const hasInteractiveElements = !!(buttons?.length || linkUrl?.length);\n const triggerProps: HTMLAttributes<HTMLElement> = {\n onMouseOver: (event) => checkIfHovered(event.nativeEvent),\n onMouseLeave: handleHideTooltipOnHover,\n onFocus: () => setIsOpen(true),\n onBlur: () => (!hasInteractiveElements ? setIsOpen(false) : null),\n };\n\n return (\n <>\n <div {...triggerProps} ref={triggerElementContainerRef}>\n {triggerElement &&\n cloneElement(triggerElement, {\n ref: triggerRefElement,\n })}\n </div>\n {createPortal(\n <div>\n {isOpen && (\n <div\n ref={tooltipContainerRef}\n className=\"tw-popper-container tw-inline-block tw-max-w-[200px] tw-bg-black-100 dark:tw-bg-white tw-rounded-md tw-shadow-mid tw-text-white dark:tw-text-black-100 tw-z-[120000]\"\n data-test-id=\"tooltip\"\n role=\"tooltip\"\n style={popperInstance.styles.popper}\n {...popperInstance.attributes.popper}\n onFocus={() => setIsOpen(true)}\n onMouseOver={(event) => checkIfHovered(event.nativeEvent)}\n onMouseLeave={handleHideTooltipOnHover}\n >\n {brightHeader && <BrightHeader headerStyle={brightHeader} />}\n <div\n className={merge([\n 'tw-px-4',\n hasLargePaddingTop ? paddingsTop.small : paddingsTop.large,\n linkUrl ? paddingsBottom.small : paddingsBottom.large,\n ])}\n >\n {heading && (\n <h4 className=\"tw-flex tw-text-m tw-font-bold tw-mb-1\">\n {headingIcon && (\n <span className=\"tw-mr-1.5\">\n {cloneElement(headingIcon, { size: IconSize.Size20 })}\n </span>\n )}\n {heading}\n </h4>\n )}\n <div className=\"tw-flex\">\n {tooltipIcon && (\n <span className=\"tw-shrink-0 tw-mr-1\">\n {cloneElement(tooltipIcon, { size: IconSize.Size16 })}\n </span>\n )}\n <p className=\"tw-text-s\">{content}</p>\n </div>\n {linkUrl && (\n <a\n {...linkProps}\n data-test-id=\"tooltip-link\"\n ref={linkRef}\n href={linkUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={merge([\n 'tw-text-xs tw-text-black-40 dark:tw-text-black-80 tw-underline tw-mt-1',\n FOCUS_VISIBLE_STYLE,\n ])}\n onBlur={() => (buttons && buttons.length > 0 ? null : setIsOpen(false))}\n >\n {linkLabel ?? 'Click here to learn more.'}\n </a>\n )}\n {buttons && (\n <div className=\"tw-flex tw-flex-row-reverse tw-gap-x-1 tw-mt-4\">\n {buttons.length > 0 && (\n <div\n onBlur={() => (buttons && buttons.length < 2 ? setIsOpen(false) : null)}\n >\n <Button\n style={ButtonStyle.Primary}\n size={ButtonSize.Small}\n inverted\n onClick={buttons[0].action}\n >\n {buttons[0].label}\n </Button>\n </div>\n )}\n {buttons.length === 2 && (\n <div onBlur={() => setIsOpen(false)}>\n <Button\n style={ButtonStyle.Secondary}\n size={ButtonSize.Small}\n inverted\n onClick={buttons[1].action}\n >\n {buttons[1].label}\n </Button>\n </div>\n )}\n </div>\n )}\n <div\n data-test-id=\"popover-arrow\"\n data-popper-arrow={withArrow}\n ref={setArrowElement}\n style={popperInstance.styles.arrow}\n className={merge([\n withArrow &&\n 'tw-popper-arrow tw-absolute tw-w-3 tw-h-3 tw-pointer-events-none before:tw-absolute before:tw-w-3 before:tw-h-3 before:tw-rotate-45 before:tw-border before:tw-border-line',\n withArrow && arrowStyling,\n ])}\n />\n </div>\n {children}\n </div>\n )}\n </div>,\n document.body,\n )}\n </>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Tooltip.es.js","sources":["../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["/* (c) Copyright Frontify Ltd., all rights reserved. */\n\nimport { Button, ButtonSize, ButtonStyle } from '@components/Button/Button';\nimport { IconSize } from '@foundation/Icon/IconSize';\nimport { useLink } from '@react-aria/link';\nimport { FOCUS_VISIBLE_STYLE } from '@utilities/focusStyle';\nimport { merge } from '@utilities/merge';\nimport React, {\n HTMLAttributes,\n PropsWithChildren,\n ReactChild,\n ReactElement,\n ReactNode,\n cloneElement,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { BrightHeader, BrightHeaderStyle, brightHeaderArrowBackgroundColors } from './BrightHeader';\nimport { usePopper } from 'react-popper';\nimport { createPortal } from 'react-dom';\nimport { Placement } from '@popperjs/core';\n\nexport type TooltipButton = {\n label: string;\n action: () => void;\n};\n\nexport type TooltipProps = PropsWithChildren<{\n triggerElement?: ReactElement;\n content: ReactNode;\n tooltipIcon?: ReactElement;\n heading?: ReactNode;\n headingIcon?: ReactElement;\n linkUrl?: string;\n linkLabel?: string;\n brightHeader?: BrightHeaderStyle;\n buttons?: [TooltipButton, TooltipButton] | [TooltipButton];\n children?: ReactChild;\n position?: TooltipPosition;\n alignment?: TooltipAlignment;\n flip?: boolean;\n withArrow?: boolean;\n hoverDelay?: number;\n}>;\n\n/**\n * This is a temporary workaround because for some yet unknown reasons `tailwindcss` in clarify purges the `tw-pb-3.5` and `tw-pt-3.5` class.\n */\nconst paddingsTop = {\n small: 'tw-pt-3.5',\n large: 'tw-pt-4',\n};\n\nconst paddingsBottom = {\n small: 'tw-pb-3.5',\n large: 'tw-pb-4',\n};\n\nexport enum TooltipPosition {\n Top = 'Top',\n Right = 'Right',\n Bottom = 'Bottom',\n Left = 'Left',\n}\n\nexport enum TooltipAlignment {\n Start = 'Start',\n Middle = 'Middle',\n End = 'End',\n}\n\nconst placementMap: Record<`${TooltipPosition}-${TooltipAlignment}`, Placement> = {\n ['Top-Start']: 'top-start',\n ['Top-End']: 'top-end',\n ['Bottom-Start']: 'bottom-start',\n ['Bottom-End']: 'bottom-end',\n ['Left-Start']: 'left-start',\n ['Left-End']: 'left-end',\n ['Right-Start']: 'right-start',\n ['Right-End']: 'right-end',\n ['Top-Middle']: 'top',\n ['Right-Middle']: 'right',\n ['Bottom-Middle']: 'bottom',\n ['Left-Middle']: 'left',\n};\n\nconst getArrowClasses = (currentPlacement: string, brightHeader: BrightHeaderStyle | undefined, alignment: string) => {\n switch (true) {\n case currentPlacement.toString().includes(TooltipPosition.Top.toLowerCase()):\n return 'before:tw-border-t-0 before:tw-border-l-0 tw-bottom-[-6px] before:tw-bg-black-100 before:dark:tw-bg-white';\n case currentPlacement.toString().includes(TooltipPosition.Right.toLowerCase()):\n return merge([\n 'before:tw-border-t-0 before:tw-border-r-0 tw-left-[-6px]',\n brightHeader && alignment === TooltipAlignment.Start\n ? brightHeaderArrowBackgroundColors[brightHeader]\n : 'before:tw-bg-black-100 before:dark:tw-bg-white',\n ]);\n case currentPlacement.toString().includes(TooltipPosition.Bottom.toLowerCase()):\n return merge([\n 'before:tw-border-b-0 before:tw-border-r-0 tw-top-[-6px]',\n brightHeader\n ? brightHeaderArrowBackgroundColors[brightHeader]\n : 'before:tw-bg-black-100 before:dark:tw-bg-white',\n ]);\n case currentPlacement.toString().includes(TooltipPosition.Left.toLowerCase()):\n return merge([\n 'before:tw-border-b-0 before:tw-border-l-0 tw-right-[-6px]',\n brightHeader && alignment === TooltipAlignment.Start\n ? brightHeaderArrowBackgroundColors[brightHeader]\n : 'before:tw-bg-black-100 before:dark:tw-bg-white',\n ]);\n default:\n return 'before:tw-border-b-0 before:tw-border-r-0 tw-top-[-6px] before:tw-bg-black-100 before:dark:tw-bg-white';\n }\n};\n\nexport const Tooltip = ({\n content,\n tooltipIcon,\n heading,\n headingIcon,\n linkUrl,\n linkLabel,\n brightHeader,\n buttons,\n children,\n position = TooltipPosition.Bottom,\n alignment = TooltipAlignment.Middle,\n withArrow,\n flip = true,\n triggerElement,\n hoverDelay = 200,\n}: TooltipProps) => {\n const triggerRefElement = useRef<HTMLElement | HTMLDivElement | HTMLButtonElement | null>(null);\n const linkRef = useRef<HTMLAnchorElement | null>(null);\n const { linkProps } = useLink({}, linkRef);\n const hasLargePaddingTop = useMemo(\n () => linkUrl || brightHeader || buttons || heading || headingIcon,\n [linkUrl, brightHeader, buttons, heading, headingIcon],\n );\n\n const placement = placementMap[`${position}-${alignment}`];\n const tooltipContainerRef = useRef<HTMLDivElement | null>(null);\n const triggerElementContainerRef = useRef<HTMLDivElement | null>(null);\n const [arrowElement, setArrowElement] = useState<HTMLDivElement | null>(null);\n\n const tooltipOffset = withArrow ? 10 : 5;\n const popperInstance = usePopper(triggerRefElement?.current, tooltipContainerRef.current, {\n placement,\n strategy: 'fixed',\n modifiers: [\n {\n name: 'arrow',\n options: {\n element: arrowElement,\n },\n },\n {\n name: 'offset',\n options: {\n offset: [0, tooltipOffset],\n },\n },\n {\n name: 'flip',\n enabled: flip,\n },\n ],\n });\n\n const currentPlacement = popperInstance.state?.placement ?? position;\n const arrowStyling = getArrowClasses(currentPlacement, brightHeader, alignment);\n const [isOpen, setIsOpen] = useState(false);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const handleShowTooltipOnHover = useCallback(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n setIsOpen(true);\n }, [triggerRefElement?.current]);\n\n const handleHideTooltipOnHover = useCallback(() => {\n timeoutRef.current = setTimeout(() => setIsOpen(false), hoverDelay);\n }, [triggerRefElement?.current, tooltipContainerRef?.current]);\n\n const checkIfHovered = useCallback(\n (event) => {\n const hoveredElement = event.path ?? event.composedPath?.();\n const hoverSources = [triggerRefElement, triggerElementContainerRef, tooltipContainerRef];\n\n if (hoveredElement && hoverSources.some((el) => hoveredElement.includes(el?.current))) {\n handleShowTooltipOnHover();\n }\n },\n [triggerRefElement?.current, tooltipContainerRef?.current, triggerElementContainerRef?.current],\n );\n\n const hasInteractiveElements = !!(buttons?.length || linkUrl?.length);\n const triggerProps: HTMLAttributes<HTMLElement> = {\n onMouseOver: (event) => checkIfHovered(event.nativeEvent),\n onMouseLeave: handleHideTooltipOnHover,\n onFocus: () => setIsOpen(true),\n onBlur: () => (!hasInteractiveElements ? setIsOpen(false) : null),\n };\n\n return (\n <>\n <div {...triggerProps} ref={triggerElementContainerRef}>\n {triggerElement &&\n cloneElement(triggerElement, {\n ref: triggerRefElement,\n })}\n </div>\n {createPortal(\n <div>\n {isOpen && (\n <div\n ref={tooltipContainerRef}\n className=\"tw-popper-container tw-inline-block tw-max-w-[200px] tw-bg-black-100 dark:tw-bg-white tw-rounded-md tw-shadow-mid tw-text-white dark:tw-text-black-100 tw-z-[120000]\"\n data-test-id=\"tooltip\"\n role=\"tooltip\"\n style={popperInstance.styles.popper}\n {...popperInstance.attributes.popper}\n onFocus={() => setIsOpen(true)}\n onMouseOver={(event) => checkIfHovered(event.nativeEvent)}\n onMouseLeave={handleHideTooltipOnHover}\n >\n {brightHeader && <BrightHeader headerStyle={brightHeader} />}\n <div\n className={merge([\n 'tw-px-4',\n hasLargePaddingTop ? paddingsTop.small : paddingsTop.large,\n linkUrl ? paddingsBottom.small : paddingsBottom.large,\n ])}\n >\n {heading && (\n <h4 className=\"tw-flex tw-text-m tw-font-bold tw-mb-1\">\n {headingIcon && (\n <span className=\"tw-mr-1.5\">\n {cloneElement(headingIcon, { size: IconSize.Size20 })}\n </span>\n )}\n {heading}\n </h4>\n )}\n <div className=\"tw-flex\">\n {tooltipIcon && (\n <span className=\"tw-shrink-0 tw-mr-1\">\n {cloneElement(tooltipIcon, { size: IconSize.Size16 })}\n </span>\n )}\n <p className=\"tw-text-s tw-min-w-0 tw-break-words\">{content}</p>\n </div>\n {linkUrl && (\n <a\n {...linkProps}\n data-test-id=\"tooltip-link\"\n ref={linkRef}\n href={linkUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={merge([\n 'tw-text-xs tw-text-black-40 dark:tw-text-black-80 tw-underline tw-mt-1',\n FOCUS_VISIBLE_STYLE,\n ])}\n onBlur={() => (buttons && buttons.length > 0 ? null : setIsOpen(false))}\n >\n {linkLabel ?? 'Click here to learn more.'}\n </a>\n )}\n {buttons && (\n <div className=\"tw-flex tw-flex-row-reverse tw-gap-x-1 tw-mt-4\">\n {buttons.length > 0 && (\n <div\n onBlur={() => (buttons && buttons.length < 2 ? setIsOpen(false) : null)}\n >\n <Button\n style={ButtonStyle.Primary}\n size={ButtonSize.Small}\n inverted\n onClick={buttons[0].action}\n >\n {buttons[0].label}\n </Button>\n </div>\n )}\n {buttons.length === 2 && (\n <div onBlur={() => setIsOpen(false)}>\n <Button\n style={ButtonStyle.Secondary}\n size={ButtonSize.Small}\n inverted\n onClick={buttons[1].action}\n >\n {buttons[1].label}\n </Button>\n </div>\n )}\n </div>\n )}\n <div\n data-test-id=\"popover-arrow\"\n data-popper-arrow={withArrow}\n ref={setArrowElement}\n style={popperInstance.styles.arrow}\n className={merge([\n withArrow &&\n 'tw-popper-arrow tw-absolute tw-w-3 tw-h-3 tw-pointer-events-none before:tw-absolute before:tw-w-3 before:tw-h-3 before:tw-rotate-45 before:tw-border before:tw-border-line',\n withArrow && arrowStyling,\n ])}\n />\n </div>\n {children}\n </div>\n )}\n </div>,\n document.body,\n )}\n </>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;AAkDA,MAAM,IAAc;AAAA,EAChB,OAAO;AAAA,EACP,OAAO;AACX,GAEM,IAAiB;AAAA,EACnB,OAAO;AAAA,EACP,OAAO;AACX;AAEY,IAAA,uBAAA,MACF,GAAA,MAAA,OACE,EAAA,QAAA,SACC,EAAA,SAAA,UACF,EAAA,OAAA,QAJC,IAAA,MAAA,CAAA,CAAA,GAOA,uBAAA,MACA,GAAA,QAAA,SACC,EAAA,SAAA,UACH,EAAA,MAAA,OAHE,IAAA,MAAA,CAAA,CAAA;AAMZ,MAAM,KAA4E;AAAA,EAC9E,CAAC,cAAc;AAAA,EACf,CAAC,YAAY;AAAA,EACb,CAAC,iBAAiB;AAAA,EAClB,CAAC,eAAe;AAAA,EAChB,CAAC,eAAe;AAAA,EAChB,CAAC,aAAa;AAAA,EACd,CAAC,gBAAgB;AAAA,EACjB,CAAC,cAAc;AAAA,EACf,CAAC,eAAe;AAAA,EAChB,CAAC,iBAAiB;AAAA,EAClB,CAAC,kBAAkB;AAAA,EACnB,CAAC,gBAAgB;AACrB,GAEM,KAAkB,CAAC,GAA0B,GAA6C,MAAsB;AAC1G,UAAA;AAAA,SACC,EAAiB,SAAS,EAAE,SAAS,MAAoB,aAAa;AAChE,aAAA;AAAA,SACN,EAAiB,SAAS,EAAE,SAAS,QAAsB,aAAa;AACzE,aAAO,EAAM;AAAA,QACT;AAAA,QACA,KAAgB,MAAc,UACxB,EAAkC,KAClC;AAAA,MAAA,CACT;AAAA,SACA,EAAiB,SAAS,EAAE,SAAS,SAAuB,aAAa;AAC1E,aAAO,EAAM;AAAA,QACT;AAAA,QACA,IACM,EAAkC,KAClC;AAAA,MAAA,CACT;AAAA,SACA,EAAiB,SAAS,EAAE,SAAS,OAAqB,aAAa;AACxE,aAAO,EAAM;AAAA,QACT;AAAA,QACA,KAAgB,MAAc,UACxB,EAAkC,KAClC;AAAA,MAAA,CACT;AAAA;AAEM,aAAA;AAAA;AAEnB,GAEa,KAAU,CAAC;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAW;AAAA,EACX,eAAY;AAAA,EACZ;AAAA,EACA,UAAO;AAAA,EACP;AAAA,EACA,gBAAa;AAAA,MACG;;AACV,QAAA,IAAoB,EAAgE,IAAI,GACxF,IAAU,EAAiC,IAAI,GAC/C,EAAE,iBAAc,GAAQ,IAAI,CAAO,GACnC,IAAqB,GACvB,MAAM,KAAW,KAAgB,KAAW,KAAW,GACvD,CAAC,GAAS,GAAc,GAAS,GAAS,CAAW,CACzD,GAEM,IAAY,GAAa,GAAG,KAAY,MACxC,IAAsB,EAA8B,IAAI,GACxD,IAA6B,EAA8B,IAAI,GAC/D,CAAC,GAAc,KAAmB,EAAgC,IAAI,GAEtE,IAAgB,IAAY,KAAK,GACjC,IAAiB,GAAU,uBAAmB,SAAS,EAAoB,SAAS;AAAA,IACtF;AAAA,IACA,UAAU;AAAA,IACV,WAAW;AAAA,MACP;AAAA,QACI,MAAM;AAAA,QACN,SAAS;AAAA,UACL,SAAS;AAAA,QACb;AAAA,MACJ;AAAA,MACA;AAAA,QACI,MAAM;AAAA,QACN,SAAS;AAAA,UACL,QAAQ,CAAC,GAAG,CAAa;AAAA,QAC7B;AAAA,MACJ;AAAA,MACA;AAAA,QACI,MAAM;AAAA,QACN,SAAS;AAAA,MACb;AAAA,IACJ;AAAA,EAAA,CACH,GAEK,IAAmB,YAAe,UAAf,kBAAsB,cAAtB,WAAmC,GACtD,IAAe,GAAgB,GAAkB,GAAc,CAAS,GACxE,CAAC,GAAQ,KAAa,EAAS,EAAK,GACpC,IAAa,EAA6C,IAAI,GAE9D,IAA2B,EAAY,MAAM;AAC/C,IAAI,EAAW,WACX,aAAa,EAAW,OAAO,GAEnC,EAAU,EAAI;AAAA,EAAA,GACf,CAAC,uBAAmB,OAAO,CAAC,GAEzB,IAA2B,EAAY,MAAM;AAC/C,MAAW,UAAU,WAAW,MAAM,EAAU,EAAK,GAAG,CAAU;AAAA,KACnE,CAAC,uBAAmB,SAAS,uBAAqB,OAAO,CAAC,GAEvD,IAAiB,EACnB,CAAC,MAAU;;AACP,UAAM,IAAiB,OAAM,SAAN,WAAc,OAAM,iBAAN;AAGjC,IAAA,KAAkB,AAFD,CAAC,GAAmB,GAA4B,CAAmB,EAErD,KAAK,CAAC,MAAO,EAAe,SAAS,uBAAI,OAAO,CAAC,KACvD;EAC7B,GAEJ,CAAC,uBAAmB,SAAS,uBAAqB,SAAS,uBAA4B,OAAO,CAClG,GAEM,KAAyB,CAAC,CAAE,yBAAS,WAAU,wBAAS,UACxD,KAA4C;AAAA,IAC9C,aAAa,CAAC,MAAU,EAAe,EAAM,WAAW;AAAA,IACxD,cAAc;AAAA,IACd,SAAS,MAAM,EAAU,EAAI;AAAA,IAC7B,QAAQ,MAAO,AAAC,KAA4C,OAAnB,EAAU,EAAK;AAAA,EAAI;AAGhE,2DAES,kBAAA,cAAA,OAAA;AAAA,IAAK,GAAG;AAAA,IAAc,KAAK;AAAA,EAAA,GACvB,KACG,EAAa,GAAgB;AAAA,IACzB,KAAK;AAAA,EACR,CAAA,CACT,GACC,GACI,kBAAA,cAAA,OAAA,MACI,KACI,kBAAA,cAAA,OAAA;AAAA,IACG,KAAK;AAAA,IACL,WAAU;AAAA,IACV,gBAAa;AAAA,IACb,MAAK;AAAA,IACL,OAAO,EAAe,OAAO;AAAA,IAC5B,GAAG,EAAe,WAAW;AAAA,IAC9B,SAAS,MAAM,EAAU,EAAI;AAAA,IAC7B,aAAa,CAAC,MAAU,EAAe,EAAM,WAAW;AAAA,IACxD,cAAc;AAAA,EAAA,GAEb,KAAiB,kBAAA,cAAA,IAAA;AAAA,IAAa,aAAa;AAAA,EAAA,CAAc,GACzD,kBAAA,cAAA,OAAA;AAAA,IACG,WAAW,EAAM;AAAA,MACb;AAAA,MACA,IAAqB,EAAY,QAAQ,EAAY;AAAA,MACrD,IAAU,EAAe,QAAQ,EAAe;AAAA,IAAA,CACnD;AAAA,EAAA,GAEA,KACI,kBAAA,cAAA,MAAA;AAAA,IAAG,WAAU;AAAA,EAAA,GACT,KACI,kBAAA,cAAA,QAAA;AAAA,IAAK,WAAU;AAAA,EACX,GAAA,EAAa,GAAa,EAAE,MAAM,EAAS,QAAQ,CACxD,GAEH,CACL,GAEH,kBAAA,cAAA,OAAA;AAAA,IAAI,WAAU;AAAA,EAAA,GACV,KACI,kBAAA,cAAA,QAAA;AAAA,IAAK,WAAU;AAAA,EACX,GAAA,EAAa,GAAa,EAAE,MAAM,EAAS,OAAQ,CAAA,CACxD,GAEH,kBAAA,cAAA,KAAA;AAAA,IAAE,WAAU;AAAA,EAAA,GAAuC,CAAQ,CAChE,GACC,KACI,kBAAA,cAAA,KAAA;AAAA,IACI,GAAG;AAAA,IACJ,gBAAa;AAAA,IACb,KAAK;AAAA,IACL,MAAM;AAAA,IACN,QAAO;AAAA,IACP,KAAI;AAAA,IACJ,WAAW,EAAM;AAAA,MACb;AAAA,MACA;AAAA,IAAA,CACH;AAAA,IACD,QAAQ,MAAO,KAAW,EAAQ,SAAS,IAAI,OAAO,EAAU,EAAK;AAAA,EAAA,GAEpE,gBAAa,2BAClB,GAEH,KACI,kBAAA,cAAA,OAAA;AAAA,IAAI,WAAU;AAAA,EAAA,GACV,EAAQ,SAAS,KACb,kBAAA,cAAA,OAAA;AAAA,IACG,QAAQ,MAAO,KAAW,EAAQ,SAAS,IAAI,EAAU,EAAK,IAAI;AAAA,EAAA,GAEjE,kBAAA,cAAA,GAAA;AAAA,IACG,OAAO,EAAY;AAAA,IACnB,MAAM,EAAW;AAAA,IACjB,UAAQ;AAAA,IACR,SAAS,EAAQ,GAAG;AAAA,EAEnB,GAAA,EAAQ,GAAG,KAChB,CACJ,GAEH,EAAQ,WAAW,KACf,kBAAA,cAAA,OAAA;AAAA,IAAI,QAAQ,MAAM,EAAU,EAAK;AAAA,EAAA,GAC7B,kBAAA,cAAA,GAAA;AAAA,IACG,OAAO,EAAY;AAAA,IACnB,MAAM,EAAW;AAAA,IACjB,UAAQ;AAAA,IACR,SAAS,EAAQ,GAAG;AAAA,EAAA,GAEnB,EAAQ,GAAG,KAChB,CACJ,CAER,GAEH,kBAAA,cAAA,OAAA;AAAA,IACG,gBAAa;AAAA,IACb,qBAAmB;AAAA,IACnB,KAAK;AAAA,IACL,OAAO,EAAe,OAAO;AAAA,IAC7B,WAAW,EAAM;AAAA,MACb,KACI;AAAA,MACJ,KAAa;AAAA,IAAA,CAChB;AAAA,EAAA,CACL,CACJ,GACC,CACL,CAER,GACA,SAAS,IACb,CACJ;AAER;"}
|