@helsenorge/designsystem-react 9.4.3 → 9.6.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 +16 -0
- package/HighlightPanel.js +5 -2
- package/HighlightPanel.js.map +1 -1
- package/Label.js +8 -3
- package/Label.js.map +1 -1
- package/ListHeader.js +2 -4
- package/ListHeader.js.map +1 -1
- package/PopOver.js +1 -1
- package/PopOver.js.map +1 -1
- package/TabList.js +77 -22
- package/TabList.js.map +1 -1
- package/components/ExpanderList/index.js +3 -3
- package/components/ExpanderList/index.js.map +1 -1
- package/components/Label/Label.d.ts +2 -2
- package/components/Label/SubLabel.d.ts +2 -0
- package/components/Modal/styles.module.scss +26 -0
- package/components/Tabs/TabList/TabChevron.d.ts +9 -0
- package/components/Tabs/TabList/TabItem.d.ts +1 -0
- package/components/Tabs/TabList/TabList.d.ts +2 -0
- package/components/Tabs/TabList/styles.module.scss +29 -5
- package/components/Tabs/TabList/styles.module.scss.d.ts +3 -0
- package/components/Tabs/TabPanel/styles.module.scss +2 -2
- package/components/Tabs/Tabs.d.ts +4 -0
- package/components/Tabs/index.js +15 -2
- package/components/Tabs/index.js.map +1 -1
- package/components/Toggle/index.js +16 -16
- package/components/Toggle/index.js.map +1 -1
- package/constants.d.ts +0 -1
- package/constants.js +0 -1
- package/constants.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
## [9.5.0](https://github.com/helsenorge/designsystem/branchCompare?baseVersion=GTv9.4.3&targetVersion=GTv9.5.0) (2024-12-13)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **Sublabel:** støtte for children ([4880fd2](https://github.com/helsenorge/designsystem/commit/4880fd2085c41c13382c68183846dbf0010307b3)), closes [#340280](https://github.com/helsenorge/designsystem/issues/340280)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* popover og datepicker popup kan brukes i 400 prosent zoom ([782ce70](https://github.com/helsenorge/designsystem/commit/782ce70b9b2c06a65a872ee886f742d54f5689ab)), closes [#340117](https://github.com/helsenorge/designsystem/issues/340117)
|
|
12
|
+
* **highlightpanel:** tillat tittel selv om ikon ikke er gitt ([63322a8](https://github.com/helsenorge/designsystem/commit/63322a881857ae42aaf3039412548c6b9750abee)), closes [#332566](https://github.com/helsenorge/designsystem/issues/332566)
|
|
13
|
+
* **tabs:** ikke scroll til fane med mindre komponenten er i view ([0c30a43](https://github.com/helsenorge/designsystem/commit/0c30a43e4fdb6acece3db8f30e6ed43468c712fd)), closes [#339921](https://github.com/helsenorge/designsystem/issues/339921)
|
|
14
|
+
|
|
15
|
+
## [9.4.3](https://github.com/helsenorge/designsystem/branchCompare?baseVersion=GTv9.4.2&targetVersion=GTv9.4.3) (2024-12-09)
|
|
16
|
+
|
|
1
17
|
## [9.4.2](https://github.com/helsenorge/designsystem/branchCompare?baseVersion=GTv9.4.1&targetVersion=GTv9.4.2) (2024-12-04)
|
|
2
18
|
|
|
3
19
|
|
package/HighlightPanel.js
CHANGED
|
@@ -42,9 +42,9 @@ const HighlightPanel = (props) => {
|
|
|
42
42
|
className
|
|
43
43
|
);
|
|
44
44
|
const renderContent = () => {
|
|
45
|
+
const titleElement = title && /* @__PURE__ */ jsx(Title, { testId: "titleId", htmlMarkup: titleHtmlMarkup, appearance: "title4", children: title });
|
|
45
46
|
if (svgIcon) {
|
|
46
47
|
const iconSize = size === "large" && breakpoint && breakpoint >= Breakpoint.md ? IconSize.Medium : IconSize.Small;
|
|
47
|
-
const titleElement = /* @__PURE__ */ jsx(Title, { testId: "titleId", htmlMarkup: titleHtmlMarkup, appearance: "title4", children: title });
|
|
48
48
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
49
49
|
/* @__PURE__ */ jsxs("div", { className: styles.highlightpanel__icon, children: [
|
|
50
50
|
typeof svgIcon === "string" ? /* @__PURE__ */ jsx(LazyIcon, { iconName: svgIcon, size: iconSize }) : /* @__PURE__ */ jsx(Icon, { svgIcon, size: iconSize }),
|
|
@@ -56,7 +56,10 @@ const HighlightPanel = (props) => {
|
|
|
56
56
|
] })
|
|
57
57
|
] });
|
|
58
58
|
}
|
|
59
|
-
return children
|
|
59
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
60
|
+
title && /* @__PURE__ */ jsx("div", { className: styles.highlightpanel__content, children: /* @__PURE__ */ jsx("div", { children: titleElement }) }),
|
|
61
|
+
children
|
|
62
|
+
] });
|
|
60
63
|
};
|
|
61
64
|
const CustomTag = htmlMarkup;
|
|
62
65
|
const contentWrapperClasses = classNames(styles["highlightpanel__content-wrapper"], contentWrapperClassName);
|
package/HighlightPanel.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HighlightPanel.js","sources":["../src/components/HighlightPanel/HighlightPanel.tsx"],"sourcesContent":["import React from 'react';\n\nimport classNames from 'classnames';\n\nimport { useBreakpoint, Breakpoint } from '../..';\nimport { AnalyticsId } from '../../constants';\nimport { PaletteNames } from '../../theme/palette';\nimport Icon, { SvgIcon, IconSize } from '../Icon';\nimport { IconName } from '../Icons/IconNames';\nimport LazyIcon from '../LazyIcon';\nimport Title, { TitleTags } from '../Title';\n\nimport styles from './styles.module.scss';\n\nexport type HighlightPanelColors = Extract<PaletteNames, 'white' | 'neutral' | 'blueberry' | 'cherry'>;\n\nexport enum HighlightPanelSize {\n medium = 'medium',\n large = 'large',\n fluid = 'fluid',\n}\n\nexport type HighlightPanelTags = Exclude<\n keyof HTMLElementTagNameMap,\n 'dir' | 'font' | 'frame' | 'frameset' | 'marquee' | 'applet' | 'basefont' | 'search'\n>;\n\nexport interface HighlightPanelProps {\n /** What's in the box? */\n children: React.ReactNode;\n /** Changes the background color. Default: white */\n color?: HighlightPanelColors;\n /** Changes the size. Default: medium */\n size?: keyof typeof HighlightPanelSize;\n /** Adds an icon to the highlightpanel. */\n svgIcon?: SvgIcon | IconName;\n /** Changes the underlying element. Default: div */\n htmlMarkup?: HighlightPanelTags;\n /** Adds custom classes to the element. */\n className?: string;\n /** Adds custom classes to the content-wrapper. Not used for fluid size. */\n contentWrapperClassName?: string;\n /** Sets the data-testid attribute. */\n testId?: string;\n /** Element that is set after the icon-element in the DOM, often a title-element */\n title?: string;\n /** Markup props for title */\n titleHtmlMarkup?: TitleTags;\n}\n\ninterface WrapperProps {\n children?: React.ReactNode;\n className: string;\n size?: keyof typeof HighlightPanelSize;\n}\n\nconst Wrapper: React.FC<WrapperProps> = ({ className, size, children }) => (\n <div className={className} data-testid={'highlightpanel-wrapper'}>\n <div className={styles.highlightpanel__row}>\n <div className={classNames(styles.highlightpanel__col, size === HighlightPanelSize.medium && styles['highlightpanel__col--offset'])}>\n {children}\n </div>\n </div>\n </div>\n);\n\ninterface ContentWrapperProps {\n children: React.ReactNode;\n className?: string;\n}\n\nconst ContentWrapper: React.FC<ContentWrapperProps> = props => {\n const { children, className } = props;\n const contentWrapperClasses = classNames(styles['highlightpanel__content-wrapper'], className);\n\n return (\n <div className={contentWrapperClasses}>\n <div className={classNames(styles.highlightpanel__row)}>{children}</div>\n </div>\n );\n};\n\nconst HighlightPanel: React.FC<HighlightPanelProps> = props => {\n const {\n children,\n color = 'white',\n size = HighlightPanelSize.medium,\n testId,\n svgIcon,\n htmlMarkup = 'div',\n className,\n contentWrapperClassName,\n title,\n titleHtmlMarkup = 'h2',\n } = props;\n const breakpoint = useBreakpoint();\n\n const containerClassName = classNames(\n styles[`highlightpanel--${color}`],\n styles[`highlightpanel--${size}`],\n svgIcon && styles['highlightpanel--has-icon'],\n { container: size === 'medium' || size === 'large' },\n className\n );\n\n const renderContent = () => {\n if (svgIcon) {\n const iconSize = size === HighlightPanelSize.large && breakpoint && breakpoint >= Breakpoint.md ? IconSize.Medium : IconSize.Small;\n\n
|
|
1
|
+
{"version":3,"file":"HighlightPanel.js","sources":["../src/components/HighlightPanel/HighlightPanel.tsx"],"sourcesContent":["import React from 'react';\n\nimport classNames from 'classnames';\n\nimport { useBreakpoint, Breakpoint } from '../..';\nimport { AnalyticsId } from '../../constants';\nimport { PaletteNames } from '../../theme/palette';\nimport Icon, { SvgIcon, IconSize } from '../Icon';\nimport { IconName } from '../Icons/IconNames';\nimport LazyIcon from '../LazyIcon';\nimport Title, { TitleTags } from '../Title';\n\nimport styles from './styles.module.scss';\n\nexport type HighlightPanelColors = Extract<PaletteNames, 'white' | 'neutral' | 'blueberry' | 'cherry'>;\n\nexport enum HighlightPanelSize {\n medium = 'medium',\n large = 'large',\n fluid = 'fluid',\n}\n\nexport type HighlightPanelTags = Exclude<\n keyof HTMLElementTagNameMap,\n 'dir' | 'font' | 'frame' | 'frameset' | 'marquee' | 'applet' | 'basefont' | 'search'\n>;\n\nexport interface HighlightPanelProps {\n /** What's in the box? */\n children: React.ReactNode;\n /** Changes the background color. Default: white */\n color?: HighlightPanelColors;\n /** Changes the size. Default: medium */\n size?: keyof typeof HighlightPanelSize;\n /** Adds an icon to the highlightpanel. */\n svgIcon?: SvgIcon | IconName;\n /** Changes the underlying element. Default: div */\n htmlMarkup?: HighlightPanelTags;\n /** Adds custom classes to the element. */\n className?: string;\n /** Adds custom classes to the content-wrapper. Not used for fluid size. */\n contentWrapperClassName?: string;\n /** Sets the data-testid attribute. */\n testId?: string;\n /** Element that is set after the icon-element in the DOM, often a title-element */\n title?: string;\n /** Markup props for title */\n titleHtmlMarkup?: TitleTags;\n}\n\ninterface WrapperProps {\n children?: React.ReactNode;\n className: string;\n size?: keyof typeof HighlightPanelSize;\n}\n\nconst Wrapper: React.FC<WrapperProps> = ({ className, size, children }) => (\n <div className={className} data-testid={'highlightpanel-wrapper'}>\n <div className={styles.highlightpanel__row}>\n <div className={classNames(styles.highlightpanel__col, size === HighlightPanelSize.medium && styles['highlightpanel__col--offset'])}>\n {children}\n </div>\n </div>\n </div>\n);\n\ninterface ContentWrapperProps {\n children: React.ReactNode;\n className?: string;\n}\n\nconst ContentWrapper: React.FC<ContentWrapperProps> = props => {\n const { children, className } = props;\n const contentWrapperClasses = classNames(styles['highlightpanel__content-wrapper'], className);\n\n return (\n <div className={contentWrapperClasses}>\n <div className={classNames(styles.highlightpanel__row)}>{children}</div>\n </div>\n );\n};\n\nconst HighlightPanel: React.FC<HighlightPanelProps> = props => {\n const {\n children,\n color = 'white',\n size = HighlightPanelSize.medium,\n testId,\n svgIcon,\n htmlMarkup = 'div',\n className,\n contentWrapperClassName,\n title,\n titleHtmlMarkup = 'h2',\n } = props;\n const breakpoint = useBreakpoint();\n\n const containerClassName = classNames(\n styles[`highlightpanel--${color}`],\n styles[`highlightpanel--${size}`],\n svgIcon && styles['highlightpanel--has-icon'],\n { container: size === 'medium' || size === 'large' },\n className\n );\n\n const renderContent = () => {\n const titleElement = title && (\n <Title testId=\"titleId\" htmlMarkup={titleHtmlMarkup} appearance=\"title4\">\n {title}\n </Title>\n );\n\n if (svgIcon) {\n const iconSize = size === HighlightPanelSize.large && breakpoint && breakpoint >= Breakpoint.md ? IconSize.Medium : IconSize.Small;\n\n return (\n <>\n <div className={styles.highlightpanel__icon}>\n {typeof svgIcon === 'string' ? <LazyIcon iconName={svgIcon} size={iconSize} /> : <Icon svgIcon={svgIcon} size={iconSize} />}\n {title && <div className={styles['mobile']}>{titleElement}</div>}\n </div>\n <div className={styles.highlightpanel__content}>\n {title && (\n <div className={styles['desktop']} aria-hidden=\"true\">\n {titleElement}\n </div>\n )}\n {children}\n </div>\n </>\n );\n }\n\n return (\n <>\n {title && (\n <div className={styles.highlightpanel__content}>\n <div>{titleElement}</div>\n </div>\n )}\n {children}\n </>\n );\n };\n\n const CustomTag = htmlMarkup;\n\n const contentWrapperClasses = classNames(styles['highlightpanel__content-wrapper'], contentWrapperClassName);\n\n if (size === HighlightPanelSize.medium) {\n return (\n <Wrapper className={containerClassName} size={size}>\n <CustomTag className={contentWrapperClasses} data-testid={testId} data-analyticsid={AnalyticsId.HighlightPanel}>\n {renderContent()}\n </CustomTag>\n </Wrapper>\n );\n }\n\n if (size === HighlightPanelSize.large && svgIcon) {\n return (\n <Wrapper className={containerClassName} size={size}>\n <ContentWrapper className={contentWrapperClasses}>\n <CustomTag\n className={classNames(styles.highlightpanel__col, styles['highlightpanel__col--large-with-icon'])}\n data-testid={testId}\n data-analyticsid={AnalyticsId.HighlightPanel}\n >\n {renderContent()}\n </CustomTag>\n </ContentWrapper>\n </Wrapper>\n );\n }\n\n if (size === HighlightPanelSize.large) {\n return (\n <Wrapper className={containerClassName} size={size}>\n <ContentWrapper className={contentWrapperClasses}>\n <CustomTag\n className={classNames(styles.highlightpanel__col, styles['highlightpanel__col--offset'])}\n data-testid={testId}\n data-analyticsid={AnalyticsId.HighlightPanel}\n >\n {renderContent()}\n </CustomTag>\n </ContentWrapper>\n </Wrapper>\n );\n }\n\n if (size === HighlightPanelSize.fluid) {\n return (\n <CustomTag className={containerClassName} data-testid={testId}>\n {renderContent()}\n </CustomTag>\n );\n }\n\n return null;\n};\n\nexport default HighlightPanel;\n"],"names":["HighlightPanelSize"],"mappings":"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"}
|
package/Label.js
CHANGED
|
@@ -6,7 +6,7 @@ import { S as Spacer } from "./Spacer.js";
|
|
|
6
6
|
import styles from "./components/Label/styles.module.scss";
|
|
7
7
|
import { isComponent } from "./utils/component.js";
|
|
8
8
|
import { S as StatusDot } from "./StatusDot.js";
|
|
9
|
-
const Sublabel = ({ className, id, onColor, sublabelTexts, testId }) => {
|
|
9
|
+
const Sublabel = ({ children, className, id, onColor, sublabelTexts, testId }) => {
|
|
10
10
|
const mapSublabels = (hideFromScreenReader) => {
|
|
11
11
|
return sublabelTexts && sublabelTexts.map((sublabelText, index) => {
|
|
12
12
|
const labelClasses = classNames(styles.label, styles["label--sublabel"], {
|
|
@@ -20,14 +20,18 @@ const Sublabel = ({ className, id, onColor, sublabelTexts, testId }) => {
|
|
|
20
20
|
const ariaHiddenSublabels = mapSublabels(true);
|
|
21
21
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
22
22
|
/* @__PURE__ */ jsx(Spacer, { size: "3xs" }),
|
|
23
|
-
subLabels && /* @__PURE__ */
|
|
23
|
+
(subLabels || children) && /* @__PURE__ */ jsxs("div", { className, id, "data-testid": testId, "data-analyticsid": AnalyticsId.Sublabel, children: [
|
|
24
|
+
subLabels,
|
|
25
|
+
children
|
|
26
|
+
] }),
|
|
24
27
|
ariaHiddenSublabels && /* @__PURE__ */ jsx("div", { className, "data-testid": testId, children: ariaHiddenSublabels })
|
|
25
28
|
] });
|
|
26
29
|
};
|
|
27
30
|
const getLabelText = (label) => {
|
|
31
|
+
var _a;
|
|
28
32
|
let allLabelText = "";
|
|
29
33
|
if (isComponent(label, Label)) {
|
|
30
|
-
label.props.labelTexts.forEach((labelText) => {
|
|
34
|
+
(_a = label.props.labelTexts) == null ? void 0 : _a.forEach((labelText) => {
|
|
31
35
|
allLabelText += !labelText.hideFromScreenReader ? labelText.text : "";
|
|
32
36
|
});
|
|
33
37
|
}
|
|
@@ -88,6 +92,7 @@ const Label = ({
|
|
|
88
92
|
className
|
|
89
93
|
);
|
|
90
94
|
const mapLabels = () => {
|
|
95
|
+
if (typeof labelTexts === "undefined") return null;
|
|
91
96
|
return labelTexts.map((labelText, index) => {
|
|
92
97
|
const labelClasses = classNames(
|
|
93
98
|
styles.label,
|
package/Label.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Label.js","sources":["../src/components/Label/SubLabel.tsx","../src/components/Label/Label.tsx"],"sourcesContent":["import React from 'react';\n\nimport cn from 'classnames';\n\nimport { LabelText } from './Label';\nimport { AnalyticsId, FormOnColor } from '../../constants';\nimport Spacer from '../Spacer';\n\nimport styles from './styles.module.scss';\n\nexport interface SublabelProps {\n /** Adds custom classes to the element. */\n className?: string;\n /** id that is placed on the wrapper */\n id: string;\n /** Array of sublabel strings. Can be of type semibold or normal */\n onColor?: FormOnColor;\n /** Array of sublabel strings. Can be of type semibold or normal */\n sublabelTexts?: LabelText[];\n /** Sets the data-testid attribute. */\n testId?: string;\n}\n\nexport const Sublabel: React.FC<SublabelProps> = ({ className, id, onColor, sublabelTexts, testId }) => {\n const mapSublabels = (hideFromScreenReader?: boolean): React.ReactNode => {\n return (\n sublabelTexts &&\n sublabelTexts.map((sublabelText, index) => {\n const labelClasses = cn(styles.label, styles['label--sublabel'], {\n [styles['label--semibold']]: sublabelText.type === 'semibold',\n [styles['label--on-dark']]: onColor === FormOnColor.ondark,\n });\n return (\n hideFromScreenReader === sublabelText.hideFromScreenReader && (\n <span className={labelClasses} key={index}>\n {sublabelText.text}\n </span>\n )\n );\n })\n );\n };\n\n const subLabels = mapSublabels();\n const ariaHiddenSublabels = mapSublabels(true);\n\n return (\n <>\n <Spacer size={'3xs'} />\n {subLabels && (\n <div className={className} id={id} data-testid={testId} data-analyticsid={AnalyticsId.Sublabel}>\n {subLabels}\n </div>\n )}\n {ariaHiddenSublabels && (\n <div className={className} data-testid={testId}>\n {ariaHiddenSublabels}\n </div>\n )}\n </>\n );\n};\n","import React, { FunctionComponent } from 'react';\n\nimport cn from 'classnames';\n\nimport { Sublabel, SublabelProps } from './SubLabel';\nimport { AnalyticsId, FormOnColor } from '../../constants';\nimport { isComponent } from '../../utils/component';\nimport Spacer from '../Spacer';\nimport StatusDot, { StatusDotProps } from '../StatusDot';\n\nimport styles from './styles.module.scss';\n\nexport type LabelText = {\n hideFromScreenReader?: boolean;\n text: string;\n type?: 'semibold' | 'normal';\n};\n\nexport type LabelTags = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'span' | 'label' | 'p';\n\nexport interface LabelProps {\n /** Component shown after label - discourage use of this */\n afterLabelChildren?: React.ReactNode;\n /** Adds custom classes to the element. */\n children?: React.ReactNode;\n /** Adds custom classes to the label tag. */\n labelClassName?: string;\n /** Adds custom classes to the label text. */\n labelTextClassName?: string;\n /** Adds custom classes to the element. */\n className?: string;\n /** Id that is put on the \"for\" attribute of the label */\n htmlFor?: string;\n /** Changes the underlying element of the label */\n htmlMarkup?: LabelTags;\n /** Id som plasseres på <label/> */\n labelId?: string;\n /** Array of main label strings. Can be of type semibold or normal */\n labelTexts: LabelText[];\n /** Array of sublabel strings. Can be of type semibold or normal */\n onColor?: keyof typeof FormOnColor;\n /** StatusDot placed underneath the last sublabel */\n statusDot?: React.ReactNode;\n /** Sublabel component */\n sublabel?: React.ReactNode;\n /** Adds custom classes to the div wrapping the sublabels. */\n sublabelWrapperClassName?: string;\n /** Sets the data-testid attribute. */\n testId?: string;\n}\n\nexport const getLabelText = (label: React.ReactNode): string => {\n let allLabelText = '';\n\n if (isComponent<LabelProps>(label, Label)) {\n label.props.labelTexts.forEach(labelText => {\n allLabelText += !labelText.hideFromScreenReader ? labelText.text : '';\n });\n }\n\n return allLabelText;\n};\n\nexport const renderLabel = (label: React.ReactNode, inputId: string, onColor: FormOnColor, markup?: LabelTags): React.ReactNode => {\n return (\n <>\n {label && isComponent<LabelProps>(label, Label)\n ? React.cloneElement(label, {\n htmlFor: inputId,\n htmlMarkup: markup || 'label',\n onColor,\n })\n : typeof label === 'string' && <Label labelTexts={[{ text: label, type: 'semibold' }]} htmlFor={inputId} onColor={onColor} />}\n </>\n );\n};\n\nexport const renderLabelAsParent = (\n label: React.ReactNode,\n children: React.ReactNode,\n inputId: string,\n onColor: FormOnColor,\n labelClassName?: string,\n labelTextClassName?: string,\n sublabelWrapperClassName?: string,\n large?: boolean,\n markup?: LabelTags\n): React.ReactNode => {\n return (\n <>\n {label && isComponent<LabelProps>(label, Label)\n ? React.cloneElement(label, {\n htmlFor: inputId,\n onColor,\n children: children,\n labelClassName: cn(labelClassName, label.props.labelClassName),\n labelTextClassName: labelTextClassName,\n htmlMarkup: markup || 'label',\n sublabelWrapperClassName: sublabelWrapperClassName,\n sublabel: large ? undefined : label.props.sublabel,\n statusDot: large ? undefined : label.props.statusDot,\n })\n : typeof label === 'string' && (\n <Label\n labelTexts={[{ text: label }]}\n htmlFor={inputId}\n onColor={onColor}\n htmlMarkup={markup || 'label'}\n labelClassName={labelClassName}\n labelTextClassName={labelTextClassName}\n sublabelWrapperClassName={sublabelWrapperClassName}\n >\n {children}\n </Label>\n )}\n </>\n );\n};\n\nconst Label: FunctionComponent<LabelProps> = ({\n afterLabelChildren,\n children,\n className,\n htmlFor,\n htmlMarkup = 'label',\n labelClassName,\n labelTextClassName,\n labelId,\n labelTexts,\n onColor = FormOnColor.onwhite,\n statusDot,\n sublabel,\n sublabelWrapperClassName,\n testId,\n}) => {\n const hasChildren = children && typeof children !== 'undefined';\n const labelWrapperClasses = cn(\n styles['label-wrapper'],\n { [styles['label-wrapper--no-bottom-margin']]: hasChildren, [styles['label-wrapper--after-label-children']]: afterLabelChildren },\n className\n );\n\n const mapLabels = (): React.ReactNode => {\n return labelTexts.map((labelText, index) => {\n const labelClasses = cn(\n styles.label,\n {\n [styles['label--semibold']]: labelText.type === 'semibold',\n [styles['label--on-dark']]: onColor === FormOnColor.ondark,\n },\n labelTextClassName\n );\n return (\n <span aria-hidden={labelText.hideFromScreenReader} className={labelClasses} key={index}>\n {labelText.text}\n </span>\n );\n });\n };\n const CustomTag = htmlMarkup;\n\n return (\n <div className={labelWrapperClasses}>\n <div>\n <CustomTag className={labelClassName} id={labelId} htmlFor={htmlFor} data-testid={testId} data-analyticsid={AnalyticsId.Label}>\n <span className={styles['label-content-wrapper']}>\n {children}\n <span className={styles.label__texts}>{mapLabels()}</span>\n </span>\n </CustomTag>\n <div className={sublabelWrapperClassName}>\n {sublabel &&\n isComponent<SublabelProps>(sublabel, Sublabel) &&\n React.cloneElement(sublabel, {\n onColor: onColor as FormOnColor,\n })}\n {statusDot && isComponent<StatusDotProps>(statusDot, StatusDot) && (\n <>\n <Spacer size={'3xs'} />\n {React.cloneElement(statusDot, {\n onColor: onColor === FormOnColor.ondark ? 'ondark' : 'onwhite',\n })}\n </>\n )}\n </div>\n </div>\n {afterLabelChildren && <div className={styles['after-label-children']}>{afterLabelChildren}</div>}\n </div>\n );\n};\n\nexport default Label;\n"],"names":["cn"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Label.js","sources":["../src/components/Label/SubLabel.tsx","../src/components/Label/Label.tsx"],"sourcesContent":["import React from 'react';\n\nimport cn from 'classnames';\n\nimport { LabelText } from './Label';\nimport { AnalyticsId, FormOnColor } from '../../constants';\nimport Spacer from '../Spacer';\n\nimport styles from './styles.module.scss';\n\nexport interface SublabelProps {\n /** Sets the content of the Sublabel */\n children?: React.ReactNode;\n /** Adds custom classes to the element. */\n className?: string;\n /** id that is placed on the wrapper */\n id: string;\n /** Array of sublabel strings. Can be of type semibold or normal */\n onColor?: FormOnColor;\n /** Array of sublabel strings. Can be of type semibold or normal */\n sublabelTexts?: LabelText[];\n /** Sets the data-testid attribute. */\n testId?: string;\n}\n\nexport const Sublabel: React.FC<SublabelProps> = ({ children, className, id, onColor, sublabelTexts, testId }) => {\n const mapSublabels = (hideFromScreenReader?: boolean): React.ReactNode => {\n return (\n sublabelTexts &&\n sublabelTexts.map((sublabelText, index) => {\n const labelClasses = cn(styles.label, styles['label--sublabel'], {\n [styles['label--semibold']]: sublabelText.type === 'semibold',\n [styles['label--on-dark']]: onColor === FormOnColor.ondark,\n });\n return (\n hideFromScreenReader === sublabelText.hideFromScreenReader && (\n <span className={labelClasses} key={index}>\n {sublabelText.text}\n </span>\n )\n );\n })\n );\n };\n\n const subLabels = mapSublabels();\n const ariaHiddenSublabels = mapSublabels(true);\n\n return (\n <>\n <Spacer size={'3xs'} />\n {(subLabels || children) && (\n <div className={className} id={id} data-testid={testId} data-analyticsid={AnalyticsId.Sublabel}>\n {subLabels}\n {children}\n </div>\n )}\n {ariaHiddenSublabels && (\n <div className={className} data-testid={testId}>\n {ariaHiddenSublabels}\n </div>\n )}\n </>\n );\n};\n","import React, { FunctionComponent } from 'react';\n\nimport cn from 'classnames';\n\nimport { Sublabel, SublabelProps } from './SubLabel';\nimport { AnalyticsId, FormOnColor } from '../../constants';\nimport { isComponent } from '../../utils/component';\nimport Spacer from '../Spacer';\nimport StatusDot, { StatusDotProps } from '../StatusDot';\n\nimport styles from './styles.module.scss';\n\nexport type LabelText = {\n hideFromScreenReader?: boolean;\n text: string;\n type?: 'semibold' | 'normal';\n};\n\nexport type LabelTags = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'span' | 'label' | 'p';\n\nexport interface LabelProps {\n /** Component shown after label - discourage use of this */\n afterLabelChildren?: React.ReactNode;\n /** Sets the content of the Label */\n children?: React.ReactNode;\n /** Adds custom classes to the label tag. */\n labelClassName?: string;\n /** Adds custom classes to the label text. */\n labelTextClassName?: string;\n /** Adds custom classes to the element. */\n className?: string;\n /** Id that is put on the \"for\" attribute of the label */\n htmlFor?: string;\n /** Changes the underlying element of the label */\n htmlMarkup?: LabelTags;\n /** Id som plasseres på <label/> */\n labelId?: string;\n /** Array of main label strings. Can be of type semibold or normal */\n labelTexts?: LabelText[];\n /** Array of sublabel strings. Can be of type semibold or normal */\n onColor?: keyof typeof FormOnColor;\n /** StatusDot placed underneath the last sublabel */\n statusDot?: React.ReactNode;\n /** Sublabel component */\n sublabel?: React.ReactNode;\n /** Adds custom classes to the div wrapping the sublabels. */\n sublabelWrapperClassName?: string;\n /** Sets the data-testid attribute. */\n testId?: string;\n}\n\nexport const getLabelText = (label: React.ReactNode): string => {\n let allLabelText = '';\n\n if (isComponent<LabelProps>(label, Label)) {\n label.props.labelTexts?.forEach(labelText => {\n allLabelText += !labelText.hideFromScreenReader ? labelText.text : '';\n });\n }\n\n return allLabelText;\n};\n\nexport const renderLabel = (label: React.ReactNode, inputId: string, onColor: FormOnColor, markup?: LabelTags): React.ReactNode => {\n return (\n <>\n {label && isComponent<LabelProps>(label, Label)\n ? React.cloneElement(label, {\n htmlFor: inputId,\n htmlMarkup: markup || 'label',\n onColor,\n })\n : typeof label === 'string' && <Label labelTexts={[{ text: label, type: 'semibold' }]} htmlFor={inputId} onColor={onColor} />}\n </>\n );\n};\n\nexport const renderLabelAsParent = (\n label: React.ReactNode,\n children: React.ReactNode,\n inputId: string,\n onColor: FormOnColor,\n labelClassName?: string,\n labelTextClassName?: string,\n sublabelWrapperClassName?: string,\n large?: boolean,\n markup?: LabelTags\n): React.ReactNode => {\n return (\n <>\n {label && isComponent<LabelProps>(label, Label)\n ? React.cloneElement(label, {\n htmlFor: inputId,\n onColor,\n children: children,\n labelClassName: cn(labelClassName, label.props.labelClassName),\n labelTextClassName: labelTextClassName,\n htmlMarkup: markup || 'label',\n sublabelWrapperClassName: sublabelWrapperClassName,\n sublabel: large ? undefined : label.props.sublabel,\n statusDot: large ? undefined : label.props.statusDot,\n })\n : typeof label === 'string' && (\n <Label\n labelTexts={[{ text: label }]}\n htmlFor={inputId}\n onColor={onColor}\n htmlMarkup={markup || 'label'}\n labelClassName={labelClassName}\n labelTextClassName={labelTextClassName}\n sublabelWrapperClassName={sublabelWrapperClassName}\n >\n {children}\n </Label>\n )}\n </>\n );\n};\n\nconst Label: FunctionComponent<LabelProps> = ({\n afterLabelChildren,\n children,\n className,\n htmlFor,\n htmlMarkup = 'label',\n labelClassName,\n labelTextClassName,\n labelId,\n labelTexts,\n onColor = FormOnColor.onwhite,\n statusDot,\n sublabel,\n sublabelWrapperClassName,\n testId,\n}) => {\n const hasChildren = children && typeof children !== 'undefined';\n const labelWrapperClasses = cn(\n styles['label-wrapper'],\n { [styles['label-wrapper--no-bottom-margin']]: hasChildren, [styles['label-wrapper--after-label-children']]: afterLabelChildren },\n className\n );\n\n const mapLabels = (): React.ReactNode => {\n if (typeof labelTexts === 'undefined') return null;\n\n return labelTexts.map((labelText, index) => {\n const labelClasses = cn(\n styles.label,\n {\n [styles['label--semibold']]: labelText.type === 'semibold',\n [styles['label--on-dark']]: onColor === FormOnColor.ondark,\n },\n labelTextClassName\n );\n return (\n <span aria-hidden={labelText.hideFromScreenReader} className={labelClasses} key={index}>\n {labelText.text}\n </span>\n );\n });\n };\n const CustomTag = htmlMarkup;\n\n return (\n <div className={labelWrapperClasses}>\n <div>\n <CustomTag className={labelClassName} id={labelId} htmlFor={htmlFor} data-testid={testId} data-analyticsid={AnalyticsId.Label}>\n <span className={styles['label-content-wrapper']}>\n {children}\n <span className={styles.label__texts}>{mapLabels()}</span>\n </span>\n </CustomTag>\n <div className={sublabelWrapperClassName}>\n {sublabel &&\n isComponent<SublabelProps>(sublabel, Sublabel) &&\n React.cloneElement(sublabel, {\n onColor: onColor as FormOnColor,\n })}\n {statusDot && isComponent<StatusDotProps>(statusDot, StatusDot) && (\n <>\n <Spacer size={'3xs'} />\n {React.cloneElement(statusDot, {\n onColor: onColor === FormOnColor.ondark ? 'ondark' : 'onwhite',\n })}\n </>\n )}\n </div>\n </div>\n {afterLabelChildren && <div className={styles['after-label-children']}>{afterLabelChildren}</div>}\n </div>\n );\n};\n\nexport default Label;\n"],"names":["cn"],"mappings":"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"}
|
package/ListHeader.js
CHANGED
|
@@ -4,7 +4,6 @@ import classNames from "classnames";
|
|
|
4
4
|
import { L as ListHeaderText } from "./ListHeaderText.js";
|
|
5
5
|
import { useBreakpoint, Breakpoint } from "./hooks/useBreakpoint.js";
|
|
6
6
|
import { isComponent, isComponentWithChildren } from "./utils/component.js";
|
|
7
|
-
import { u as uuid } from "./uuid.js";
|
|
8
7
|
import { A as Avatar, a as AvatarSize } from "./Avatar.js";
|
|
9
8
|
import { B as Badge } from "./Badge.js";
|
|
10
9
|
import { I as Icon } from "./Icon.js";
|
|
@@ -111,9 +110,8 @@ const ListHeader = (props) => {
|
|
|
111
110
|
!!(mappedChildren == null ? void 0 : mappedChildren.stringChildren.length) && /* @__PURE__ */ jsx(CustomTag, { className: styles["list-header__title"], children: mappedChildren.stringChildren }),
|
|
112
111
|
mappedChildren == null ? void 0 : mappedChildren.remainingChildren
|
|
113
112
|
] }),
|
|
114
|
-
(mappedChildren == null ? void 0 : mappedChildren.badgeChildren) && mappedChildren.badgeChildren.map((badgeChild) => {
|
|
115
|
-
|
|
116
|
-
return /* @__PURE__ */ jsx("span", { className: badgeClasses, children: badgeChild }, id);
|
|
113
|
+
(mappedChildren == null ? void 0 : mappedChildren.badgeChildren) && mappedChildren.badgeChildren.map((badgeChild, index) => {
|
|
114
|
+
return /* @__PURE__ */ jsx("span", { className: badgeClasses, children: badgeChild }, index);
|
|
117
115
|
}),
|
|
118
116
|
showChevronAndIcon && chevronIcon && /* @__PURE__ */ jsx("span", { className: chevronClasses, children: /* @__PURE__ */ jsx(Icon, { svgIcon: chevronIcon, isHovered, size: IconSize.XSmall }) })
|
|
119
117
|
] });
|
package/ListHeader.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ListHeader.js","sources":["../src/components/ListHeader/ListHeader.tsx"],"sourcesContent":["import React from 'react';\n\nimport cn from 'classnames';\n\nimport ListHeaderText, { ListHeaderTextProps, ListHeaderTextType } from './ListHeaderText/ListHeaderText';\nimport { Breakpoint, useBreakpoint } from '../../hooks/useBreakpoint';\nimport { isComponent, isComponentWithChildren } from '../../utils/component';\nimport uuid from '../../utils/uuid';\nimport Avatar, { AvatarProps, AvatarSize, AvatarType } from '../Avatar';\nimport Badge, { BadgeProps, BadgeType } from '../Badge';\nimport Icon, { IconSize, SvgIcon } from '../Icon';\nimport { TitleTags } from '../Title';\n\nimport styles from './styles.module.scss';\n\nexport type ListHeaderSize = 'small' | 'medium' | 'large';\n\nexport interface ListHeaderType extends React.FC<ListHeaderProps> {\n Avatar?: AvatarType;\n Badge?: BadgeType;\n ListHeaderText?: ListHeaderTextType;\n}\n\nexport const renderListHeader = (\n element: React.ReactNode,\n titleHtmlMarkup: TitleTags,\n isHovered: boolean,\n size: ListHeaderSize,\n chevronIcon?: SvgIcon,\n icon?: React.ReactElement\n): JSX.Element | undefined => {\n if (isComponent<ListHeaderProps>(element, ListHeader)) {\n return React.cloneElement(element, {\n chevronIcon,\n icon,\n isHovered,\n size,\n });\n }\n if (element) {\n return (\n <ListHeader titleHtmlMarkup={titleHtmlMarkup} chevronIcon={chevronIcon} icon={icon} isHovered={isHovered} size={size}>\n {element}\n </ListHeader>\n );\n }\n};\n\nexport interface ListHeaderProps {\n /** Adds custom classes to the ListHeader element. */\n className?: string;\n /** Chevron to render inside of the ListHeader */\n chevronIcon?: SvgIcon;\n /** Children to be rendered inside of ListHeader */\n children: React.ReactNode;\n /** Changes the underlying element of the title. Default: h2*/\n titleHtmlMarkup?: TitleTags;\n /** icon to be rendered inside of ListHeader */\n icon?: React.ReactElement;\n /** whether or not the parent is hovered */\n isHovered?: boolean;\n /** Changes size of the ListHeader. */\n size?: ListHeaderSize;\n /** Sets the data-testid attribute. */\n testId?: string;\n}\n\ninterface ListHeaderChildren {\n avatarChild?: React.ReactElement<AvatarProps>;\n listHeaderTextChildren: React.ReactElement<ListHeaderTextProps>[];\n badgeChildren?: React.ReactElement<BadgeProps>[];\n elementChild?: React.ReactElement;\n stringChildren: string[];\n remainingChildren: React.ReactNode[];\n}\n\ntype ChildrenMapper = (children: React.ReactNode, isJsxChild?: boolean) => ListHeaderChildren | undefined;\n\nexport const mapChildren: ChildrenMapper = (children, isJsxChild = false) => {\n let avatarChild: React.ReactElement<AvatarProps> | undefined;\n const badgeChildren: React.ReactElement<BadgeProps>[] = [];\n const listHeaderTextChildren: React.ReactElement<ListHeaderTextProps>[] = [];\n const stringChildren: string[] = [];\n const remainingChildren: React.ReactNode[] = [];\n\n React.Children.forEach(children, child => {\n if (child === null || typeof child === 'undefined') return;\n if (isComponent<AvatarProps>(child, Avatar)) {\n avatarChild = child;\n } else if (isComponent<ListHeaderTextProps>(child, ListHeaderText)) {\n listHeaderTextChildren.push(child);\n } else if (isComponent<BadgeProps>(child, Badge)) {\n badgeChildren.push(child);\n } else if (typeof child === 'string') {\n stringChildren.push(child);\n } else {\n remainingChildren.push(child);\n }\n });\n\n // Dette og recursive mapChildren under(gjøres en gang) er for å passe på at jsx children også sjekkes for Avatar og liknende innhold.\n // Slik opprettholder vi stylingen i tilfeller hvor vertikaler har wrappet elementer i en parent span eller div.\n const hasSpecialChildren =\n avatarChild !== undefined || listHeaderTextChildren.length > 0 || (badgeChildren !== undefined && stringChildren.length > 0);\n const noRemainingRecursiveChildren =\n remainingChildren.length === 0 ||\n (isComponentWithChildren(remainingChildren[0]) && typeof remainingChildren[0]?.props?.children === 'undefined');\n\n if (isJsxChild || hasSpecialChildren || noRemainingRecursiveChildren) {\n return { avatarChild, listHeaderTextChildren, badgeChildren, stringChildren, remainingChildren };\n }\n\n if (isComponentWithChildren(remainingChildren[0])) {\n return mapChildren(remainingChildren[0]?.props?.children, true);\n }\n};\n\nexport const ListHeader: ListHeaderType = props => {\n const { className = '', titleHtmlMarkup = 'h2', chevronIcon, children, icon, isHovered, size, testId } = props;\n const breakpoint = useBreakpoint();\n const showChevronAndIcon = size !== 'small' && !!(chevronIcon || icon);\n const contentIsString = typeof children === 'string';\n const mappedChildren = mapChildren(children);\n const topAlignContent =\n mappedChildren?.avatarChild ||\n (mappedChildren?.listHeaderTextChildren && mappedChildren.listHeaderTextChildren.length > 0) ||\n (mappedChildren?.remainingChildren && mappedChildren?.remainingChildren.length > 0);\n\n const listLabelClasses = cn(\n styles['list-header'],\n {\n [styles['list-header--for-element-content']]: !contentIsString,\n [styles['list-header--top-align-content']]: topAlignContent,\n },\n className\n );\n const badgeClasses = cn(\n styles['list-header__badge'],\n {\n [styles['list-header__badge--for-string-content']]: contentIsString,\n },\n !contentIsString && size && styles[`list-header__badge--${size}`]\n );\n const chevronClasses = cn(styles['list-header__chevron'], !contentIsString && size && styles[`list-header__chevron--${size}`], {\n [styles['list-header__chevron--for-string-content']]: contentIsString,\n });\n const contentClasses = cn(styles['list-header__content'], {\n [styles['list-header__content--string']]: contentIsString,\n [styles['list-header__content--element']]: !contentIsString,\n [styles['list-header__content--spacing']]: !mappedChildren?.avatarChild && !icon,\n });\n const iconClasses = cn(\n styles['list-header__icon'],\n !contentIsString && size && (size === 'medium' || size === 'large') && styles[`list-header__icon--for-element-content--${size}`],\n {\n [styles['list-header__icon--for-string-content']]: contentIsString,\n [styles['list-header__icon--for-element-content']]: !contentIsString,\n }\n );\n const avatarClasses = cn(\n styles['list-header__avatar'],\n !contentIsString && size && (size === 'medium' || size === 'large') && styles[`list-header__avatar--for-element-content--${size}`],\n {\n [styles['list-header__avatar--for-string-content']]: contentIsString,\n [styles['list-header__avatar--for-element-content']]: !contentIsString,\n }\n );\n const CustomTag = titleHtmlMarkup;\n return (\n <span data-testid={testId} className={listLabelClasses}>\n {showChevronAndIcon && icon && (\n <span className={iconClasses}>\n {React.cloneElement(icon, {\n size: breakpoint === Breakpoint.xs ? IconSize.XSmall : IconSize.Small,\n isHovered,\n })}\n </span>\n )}\n {size !== 'small' && mappedChildren?.avatarChild && (\n <span className={avatarClasses}>{React.cloneElement(mappedChildren.avatarChild, { size: AvatarSize.xsmall })}</span>\n )}\n <span className={contentClasses}>\n {mappedChildren?.listHeaderTextChildren}\n {!!mappedChildren?.stringChildren.length && (\n <CustomTag className={styles['list-header__title']}>{mappedChildren.stringChildren}</CustomTag>\n )}\n {mappedChildren?.remainingChildren}\n </span>\n\n {mappedChildren?.badgeChildren &&\n mappedChildren.badgeChildren.map(badgeChild => {\n const id = uuid();\n return (\n <span key={id} className={badgeClasses}>\n {badgeChild}\n </span>\n );\n })}\n {showChevronAndIcon && chevronIcon && (\n <span className={chevronClasses}>\n <Icon svgIcon={chevronIcon} isHovered={isHovered} size={IconSize.XSmall} />\n </span>\n )}\n </span>\n );\n};\n\nListHeader.displayName = 'ListHeader';\n\nexport default ListHeader;\n"],"names":["cn"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ListHeader.js","sources":["../src/components/ListHeader/ListHeader.tsx"],"sourcesContent":["import React from 'react';\n\nimport cn from 'classnames';\n\nimport ListHeaderText, { ListHeaderTextProps, ListHeaderTextType } from './ListHeaderText/ListHeaderText';\nimport { Breakpoint, useBreakpoint } from '../../hooks/useBreakpoint';\nimport { isComponent, isComponentWithChildren } from '../../utils/component';\nimport Avatar, { AvatarProps, AvatarSize, AvatarType } from '../Avatar';\nimport Badge, { BadgeProps, BadgeType } from '../Badge';\nimport Icon, { IconSize, SvgIcon } from '../Icon';\nimport { TitleTags } from '../Title';\n\nimport styles from './styles.module.scss';\n\nexport type ListHeaderSize = 'small' | 'medium' | 'large';\n\nexport interface ListHeaderType extends React.FC<ListHeaderProps> {\n Avatar?: AvatarType;\n Badge?: BadgeType;\n ListHeaderText?: ListHeaderTextType;\n}\n\nexport const renderListHeader = (\n element: React.ReactNode,\n titleHtmlMarkup: TitleTags,\n isHovered: boolean,\n size: ListHeaderSize,\n chevronIcon?: SvgIcon,\n icon?: React.ReactElement\n): JSX.Element | undefined => {\n if (isComponent<ListHeaderProps>(element, ListHeader)) {\n return React.cloneElement(element, {\n chevronIcon,\n icon,\n isHovered,\n size,\n });\n }\n if (element) {\n return (\n <ListHeader titleHtmlMarkup={titleHtmlMarkup} chevronIcon={chevronIcon} icon={icon} isHovered={isHovered} size={size}>\n {element}\n </ListHeader>\n );\n }\n};\n\nexport interface ListHeaderProps {\n /** Adds custom classes to the ListHeader element. */\n className?: string;\n /** Chevron to render inside of the ListHeader */\n chevronIcon?: SvgIcon;\n /** Children to be rendered inside of ListHeader */\n children: React.ReactNode;\n /** Changes the underlying element of the title. Default: h2*/\n titleHtmlMarkup?: TitleTags;\n /** icon to be rendered inside of ListHeader */\n icon?: React.ReactElement;\n /** whether or not the parent is hovered */\n isHovered?: boolean;\n /** Changes size of the ListHeader. */\n size?: ListHeaderSize;\n /** Sets the data-testid attribute. */\n testId?: string;\n}\n\ninterface ListHeaderChildren {\n avatarChild?: React.ReactElement<AvatarProps>;\n listHeaderTextChildren: React.ReactElement<ListHeaderTextProps>[];\n badgeChildren?: React.ReactElement<BadgeProps>[];\n elementChild?: React.ReactElement;\n stringChildren: string[];\n remainingChildren: React.ReactNode[];\n}\n\ntype ChildrenMapper = (children: React.ReactNode, isJsxChild?: boolean) => ListHeaderChildren | undefined;\n\nexport const mapChildren: ChildrenMapper = (children, isJsxChild = false) => {\n let avatarChild: React.ReactElement<AvatarProps> | undefined;\n const badgeChildren: React.ReactElement<BadgeProps>[] = [];\n const listHeaderTextChildren: React.ReactElement<ListHeaderTextProps>[] = [];\n const stringChildren: string[] = [];\n const remainingChildren: React.ReactNode[] = [];\n\n React.Children.forEach(children, child => {\n if (child === null || typeof child === 'undefined') return;\n if (isComponent<AvatarProps>(child, Avatar)) {\n avatarChild = child;\n } else if (isComponent<ListHeaderTextProps>(child, ListHeaderText)) {\n listHeaderTextChildren.push(child);\n } else if (isComponent<BadgeProps>(child, Badge)) {\n badgeChildren.push(child);\n } else if (typeof child === 'string') {\n stringChildren.push(child);\n } else {\n remainingChildren.push(child);\n }\n });\n\n // Dette og recursive mapChildren under(gjøres en gang) er for å passe på at jsx children også sjekkes for Avatar og liknende innhold.\n // Slik opprettholder vi stylingen i tilfeller hvor vertikaler har wrappet elementer i en parent span eller div.\n const hasSpecialChildren =\n avatarChild !== undefined || listHeaderTextChildren.length > 0 || (badgeChildren !== undefined && stringChildren.length > 0);\n const noRemainingRecursiveChildren =\n remainingChildren.length === 0 ||\n (isComponentWithChildren(remainingChildren[0]) && typeof remainingChildren[0]?.props?.children === 'undefined');\n\n if (isJsxChild || hasSpecialChildren || noRemainingRecursiveChildren) {\n return { avatarChild, listHeaderTextChildren, badgeChildren, stringChildren, remainingChildren };\n }\n\n if (isComponentWithChildren(remainingChildren[0])) {\n return mapChildren(remainingChildren[0]?.props?.children, true);\n }\n};\n\nexport const ListHeader: ListHeaderType = props => {\n const { className = '', titleHtmlMarkup = 'h2', chevronIcon, children, icon, isHovered, size, testId } = props;\n const breakpoint = useBreakpoint();\n const showChevronAndIcon = size !== 'small' && !!(chevronIcon || icon);\n const contentIsString = typeof children === 'string';\n const mappedChildren = mapChildren(children);\n const topAlignContent =\n mappedChildren?.avatarChild ||\n (mappedChildren?.listHeaderTextChildren && mappedChildren.listHeaderTextChildren.length > 0) ||\n (mappedChildren?.remainingChildren && mappedChildren?.remainingChildren.length > 0);\n\n const listLabelClasses = cn(\n styles['list-header'],\n {\n [styles['list-header--for-element-content']]: !contentIsString,\n [styles['list-header--top-align-content']]: topAlignContent,\n },\n className\n );\n const badgeClasses = cn(\n styles['list-header__badge'],\n {\n [styles['list-header__badge--for-string-content']]: contentIsString,\n },\n !contentIsString && size && styles[`list-header__badge--${size}`]\n );\n const chevronClasses = cn(styles['list-header__chevron'], !contentIsString && size && styles[`list-header__chevron--${size}`], {\n [styles['list-header__chevron--for-string-content']]: contentIsString,\n });\n const contentClasses = cn(styles['list-header__content'], {\n [styles['list-header__content--string']]: contentIsString,\n [styles['list-header__content--element']]: !contentIsString,\n [styles['list-header__content--spacing']]: !mappedChildren?.avatarChild && !icon,\n });\n const iconClasses = cn(\n styles['list-header__icon'],\n !contentIsString && size && (size === 'medium' || size === 'large') && styles[`list-header__icon--for-element-content--${size}`],\n {\n [styles['list-header__icon--for-string-content']]: contentIsString,\n [styles['list-header__icon--for-element-content']]: !contentIsString,\n }\n );\n const avatarClasses = cn(\n styles['list-header__avatar'],\n !contentIsString && size && (size === 'medium' || size === 'large') && styles[`list-header__avatar--for-element-content--${size}`],\n {\n [styles['list-header__avatar--for-string-content']]: contentIsString,\n [styles['list-header__avatar--for-element-content']]: !contentIsString,\n }\n );\n const CustomTag = titleHtmlMarkup;\n return (\n <span data-testid={testId} className={listLabelClasses}>\n {showChevronAndIcon && icon && (\n <span className={iconClasses}>\n {React.cloneElement(icon, {\n size: breakpoint === Breakpoint.xs ? IconSize.XSmall : IconSize.Small,\n isHovered,\n })}\n </span>\n )}\n {size !== 'small' && mappedChildren?.avatarChild && (\n <span className={avatarClasses}>{React.cloneElement(mappedChildren.avatarChild, { size: AvatarSize.xsmall })}</span>\n )}\n <span className={contentClasses}>\n {mappedChildren?.listHeaderTextChildren}\n {!!mappedChildren?.stringChildren.length && (\n <CustomTag className={styles['list-header__title']}>{mappedChildren.stringChildren}</CustomTag>\n )}\n {mappedChildren?.remainingChildren}\n </span>\n\n {mappedChildren?.badgeChildren &&\n mappedChildren.badgeChildren.map((badgeChild, index) => {\n return (\n <span key={index} className={badgeClasses}>\n {badgeChild}\n </span>\n );\n })}\n {showChevronAndIcon && chevronIcon && (\n <span className={chevronClasses}>\n <Icon svgIcon={chevronIcon} isHovered={isHovered} size={IconSize.XSmall} />\n </span>\n )}\n </span>\n );\n};\n\nListHeader.displayName = 'ListHeader';\n\nexport default ListHeader;\n"],"names":["cn"],"mappings":"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"}
|
package/PopOver.js
CHANGED
|
@@ -156,7 +156,7 @@ const PopOver = React.forwardRef((props, ref) => {
|
|
|
156
156
|
const arrowRef = useRef(null);
|
|
157
157
|
const bubbleSize = useSize(bubbleRef);
|
|
158
158
|
const [controllerSize, setControllerSize] = useState();
|
|
159
|
-
const controllerisVisible = useIsVisible(
|
|
159
|
+
const controllerisVisible = useIsVisible(bubbleRef, 0);
|
|
160
160
|
const updateControllerSize = () => {
|
|
161
161
|
var _a;
|
|
162
162
|
setControllerSize((_a = controllerRef.current) == null ? void 0 : _a.getBoundingClientRect());
|
package/PopOver.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PopOver.js","sources":["../src/components/PopOver/utils.ts","../src/components/PopOver/PopOver.tsx"],"sourcesContent":["import { CSSProperties } from 'react';\n\nimport { PopOverVariant } from './PopOver';\n\ntype HorizontalPosition = 'left' | 'right' | 'floating';\ntype BubblePosition = 'leftabove' | 'leftbelow' | 'rightabove' | 'rightbelow' | 'floatingabove' | 'floatingbelow';\n\n/** Bredde på hjelpeboble */\nconst BUBBLE_WIDTH_PX = 373;\n/** Hjelpeboblen skal holde avstand til venstre/høyre kant på vinduet */\nconst WINDOW_MARGIN_PX = 12;\n/** Vertikal avstand fra hjelpeboble til kontroller */\nconst BUBBLE_VERTICAL_OFFSET_PX = 16;\n/** Høyde/bredde på pil */\nconst ARROW_WIDTH_PX = 20;\n/** Avstand fra pil til hjelpeboble */\nconst ARROW_VERTICAL_OFFSET_PX = 4;\n/** Pilen skal holde avstand til venstre/høyre kant av hjelpeboblen */\nconst ARROW_HORIZONTAL_MARGIN_PX = 12;\n\n/**\n * Beregn om hjelpeboblen skal vises over eller under kontrolleren\n * @param controllerSize DOMRect for controlleren\n * @param bubbleSize DOMRect for hjelpeboblen\n * @param variant Ønsket plassering av hjelpeboblen (over/under/automatisk)\n * @returns Om hjelpeboblen skal vises over eller under\n */\nexport const getVerticalPosition = (\n controllerSize: DOMRect,\n bubbleSize: DOMRect,\n variant: keyof typeof PopOverVariant\n): keyof typeof PopOverVariant => {\n if (variant !== PopOverVariant.positionautomatic) {\n return variant;\n }\n if (controllerSize.top > bubbleSize.height + BUBBLE_VERTICAL_OFFSET_PX) {\n return PopOverVariant.positionabove;\n } else {\n return PopOverVariant.positionbelow;\n }\n};\n\n/**\n * Finn horisontalt midtpunkt på kontrolleren i forhold til venstre kant av vinduet\n * @param controllerSize DOMRect for controlleren\n * @returns Horisontalt senter av controlleren i px\n */\nconst getControllerLeftCenterPx = (controllerSize: DOMRect): number => controllerSize.left + controllerSize.width / 2;\n\n/**\n * Finn horisontalt midtpunkt på kontrolleren i forhold til høyre kant av vinduet\n * @param controllerSize DOMRect for controlleren\n * @returns Horisontalt senter av controlleren i px\n */\nconst getControllerRightCenterPx = (controllerSize: DOMRect): number =>\n document.documentElement.clientWidth - controllerSize.right + controllerSize.width / 2;\n\n/**\n * Finn venstre kant av hjelpeboblen i forhold til kontrolleren\n * @param controllerSize DOMRect for controlleren\n * @param bubbleSize DOMRect for hjelpeboblen\n * @returns Venstre kant av hjelpeboblen i px\n */\nconst getBubbleLeftPx = (controllerSize: DOMRect, bubbleSize: DOMRect): number => {\n const controllerHorizontalCenterPx = getControllerLeftCenterPx(controllerSize);\n\n return controllerHorizontalCenterPx - bubbleSize.width / 2;\n};\n\n/**\n * Finn høyre kant av hjelpeboblen i forhold til kontrolleren\n * @param controllerSize DOMRect for controlleren\n * @param bubbleSize DOMRect for hjelpeboblen\n * @returns Høyre kant av hjelpeboblen i px\n */\nconst getBubbleRightPx = (controllerSize: DOMRect, bubbleSize: DOMRect): number => {\n const bubbleLeftPx = getBubbleLeftPx(controllerSize, bubbleSize);\n\n return bubbleLeftPx + bubbleSize.width;\n};\n\n/**\n * Sjekk om venstre kant av hjelpeboblen er innenfor vinduet\n * @param controllerSize DOMRect for controlleren\n * @param bubbleSize DOMRect for hjelpeboblen\n * @returns true dersom venstre kant er innenfor vinduet\n */\nconst getBubbleLeftVisible = (controllerSize: DOMRect, bubbleSize: DOMRect): boolean => {\n const bubbleLeftPx = getBubbleLeftPx(controllerSize, bubbleSize);\n\n return bubbleLeftPx > WINDOW_MARGIN_PX;\n};\n\n/**\n * Sjekk om høyre kant av hjelpeboblen er innenfor vinduet\n * @param controllerSize DOMRect for controlleren\n * @param bubbleSize DOMRect for hjelpeboblen\n * @returns true dersom høyre kant er innenfor vinduet\n */\nconst getBubbleRightIsVisible = (controllerSize: DOMRect, bubbleSize: DOMRect): boolean => {\n const bubbleRightPx = getBubbleRightPx(controllerSize, bubbleSize);\n\n return bubbleRightPx < document.documentElement.clientWidth - WINDOW_MARGIN_PX;\n};\n\n/**\n * Finn riktig horisontal plassering til hjelpeboblen\n * @param controllerSize DOMRect for controlleren\n * @param bubbleSize DOMRect for hjelpeboblen\n * @returns left, right eller floating\n */\nconst getHorizontalPosition = (controllerSize: DOMRect, bubbleSize: DOMRect): HorizontalPosition => {\n if (!getBubbleRightIsVisible(controllerSize, bubbleSize)) {\n return 'right';\n }\n if (!getBubbleLeftVisible(controllerSize, bubbleSize)) {\n return 'left';\n }\n\n return 'floating';\n};\n\n/**\n * Finn vertikal plassering av hjelpeboblen når den skal vises over\n * @param controllerSize DOMRect for controlleren\n * @param bubbleSize DOMRect for hjelpeboblen\n * @returns \"Top\" for hjelpeboblen i px\n */\nconst getBubbleAbovePx = (controllerSize: DOMRect, bubbleSize: DOMRect): number =>\n controllerSize.top - BUBBLE_VERTICAL_OFFSET_PX - bubbleSize.height;\n\n/**\n * Finn vertikal plassering av hjelpeboblen når den skal vises under\n * @param controllerSize DOMRect for controlleren\n * @param bubbleSize DOMRect for hjelpeboblen\n * @returns \"Top\" for hjelpeboblen i px\n */\nconst getBubbleBelowPx = (controllerSize: DOMRect): number => controllerSize.bottom + BUBBLE_VERTICAL_OFFSET_PX;\n\n/**\n * Finn maks bredde på hjelpeboblen i forhold til vinduet\n * @returns Bredde på hjelpeboblen i px\n */\nconst getBubbleWidth = (): number => document.documentElement.clientWidth - WINDOW_MARGIN_PX * 2;\n\n/**\n * Sjekk om hjelpeboblen har plass i vinduet\n * @returns true dersom det er plass til hjelpeboblen i vinduet\n */\nconst getBubbleFitsInWindow = (): boolean => {\n return document.documentElement.clientWidth > BUBBLE_WIDTH_PX + WINDOW_MARGIN_PX * 2;\n};\n\n/**\n * Finn vertikal plassering av pilen når den skal vises over\n * @param controllerSize DOMRect for controlleren\n * @returns \"Top\" for pilen i px\n */\nconst getArrowTopxPx = (controllerSize: DOMRect): number => controllerSize.top - BUBBLE_VERTICAL_OFFSET_PX - ARROW_VERTICAL_OFFSET_PX;\n\n/**\n * Finn horisontal plassering av pilen i forhold til venstre kant av vinduet\n * @param controllerSize DOMRect for controlleren\n * @returns Venstre kant av pilen i px\n */\nconst getArrowLeftPx = (controllerSize: DOMRect): number => getControllerLeftCenterPx(controllerSize) - ARROW_WIDTH_PX / 2;\n\n/**\n * Finn horisontal plassering av pilen\n * @param controllerSize DOMRect for controlleren\n * @returns Venstre kant av pilen i px\n */\nconst getArrowRightPx = (controllerSize: DOMRect): number => getControllerRightCenterPx(controllerSize) - ARROW_WIDTH_PX / 2;\n\n/**\n * Finn riktig plassering av hjelpeboblen\n * @param controllerSize DOMRect for controlleren\n * @param bubbleSize DOMRect for hjelpeboblen\n * @param variant Ønsket plassering av hjelpeboblen (over/under)\n * @returns Beste mulige plassering av hjelpeboblen\n */\nconst getBubblePosition = (controllerSize: DOMRect, bubbleSize: DOMRect, variant: keyof typeof PopOverVariant): BubblePosition => {\n const horizontalPosition = getHorizontalPosition(controllerSize, bubbleSize);\n const verticalPosition = getVerticalPosition(controllerSize, bubbleSize, variant);\n\n if (horizontalPosition === 'left') {\n if (verticalPosition === PopOverVariant.positionabove) {\n return 'leftabove';\n }\n return 'leftbelow';\n }\n\n if (horizontalPosition === 'right') {\n if (verticalPosition === PopOverVariant.positionabove) {\n return 'rightabove';\n }\n return 'rightbelow';\n }\n\n if (verticalPosition === PopOverVariant.positionabove) {\n return 'floatingabove';\n }\n\n return 'floatingbelow';\n};\n\n/**\n * Finn riktig plassering av hjelpeboblen\n * @param controllerSize DOMRect for controlleren\n * @param bubbleSize DOMRect for hjelpeboblen\n * @param variant Ønsket plassering av hjelpeboblen (over/under)\n * @returns CSSProperties som plasserer hjelpeboblen riktig\n */\nexport const getBubbleStyle = (controllerSize: DOMRect, bubbleSize: DOMRect, variant: keyof typeof PopOverVariant): CSSProperties => {\n const bubblePosition = getBubblePosition(controllerSize, bubbleSize, variant);\n const bubbleWidth = !getBubbleFitsInWindow() ? getBubbleWidth() : undefined;\n\n if (bubblePosition === 'leftabove') {\n return {\n left: WINDOW_MARGIN_PX,\n top: getBubbleAbovePx(controllerSize, bubbleSize),\n width: bubbleWidth,\n };\n }\n if (bubblePosition === 'leftbelow') {\n return { left: WINDOW_MARGIN_PX, top: getBubbleBelowPx(controllerSize), width: bubbleWidth };\n }\n if (bubblePosition === 'rightabove') {\n return { right: WINDOW_MARGIN_PX, top: getBubbleAbovePx(controllerSize, bubbleSize), width: bubbleWidth };\n }\n if (bubblePosition === 'rightbelow') {\n return { right: WINDOW_MARGIN_PX, top: getBubbleBelowPx(controllerSize), width: bubbleWidth };\n }\n\n if (bubblePosition === 'floatingbelow') {\n return { left: getBubbleLeftPx(controllerSize, bubbleSize), top: getBubbleBelowPx(controllerSize), width: bubbleWidth };\n }\n\n return { left: getBubbleLeftPx(controllerSize, bubbleSize), top: getBubbleAbovePx(controllerSize, bubbleSize), width: bubbleWidth };\n};\n\n/**\n * Finn riktig plassering av pilen\n * @param bubbleStyle CSSProperties for hjelpeboblen\n * @param controllerSize DOMRect for kontrolleren\n * @param verticalPosition Ønsket plassering av hjelpeboblen (over/under)\n * @returns CSSProperties som plasserer pilen riktig\n */\nexport const getArrowStyle = (\n bubbleStyle: CSSProperties,\n controllerSize: DOMRect,\n verticalPosition: keyof typeof PopOverVariant\n): CSSProperties => {\n const leftPx = getArrowLeftPx(controllerSize);\n const rightPx = getArrowRightPx(controllerSize);\n const minLeftPx = (bubbleStyle.left as number) + ARROW_HORIZONTAL_MARGIN_PX;\n const minRightPx = (bubbleStyle.right as number) + ARROW_HORIZONTAL_MARGIN_PX;\n\n if (bubbleStyle.right) {\n if (verticalPosition === PopOverVariant.positionabove) {\n return {\n right: rightPx > minRightPx ? rightPx : minRightPx,\n top: getArrowTopxPx(controllerSize),\n };\n }\n\n return {\n right: rightPx > minRightPx ? rightPx : minRightPx,\n top: controllerSize.bottom,\n };\n }\n\n if (verticalPosition === PopOverVariant.positionabove) {\n return {\n left: leftPx > minLeftPx ? leftPx : minLeftPx,\n top: getArrowTopxPx(controllerSize),\n };\n }\n\n return {\n left: leftPx > minLeftPx ? leftPx : minLeftPx,\n top: controllerSize.bottom,\n };\n};\n","import React, { useEffect, useRef, useState } from 'react';\n\nimport classNames from 'classnames';\n\nimport { getArrowStyle, getBubbleStyle, getVerticalPosition } from './utils';\nimport { AnalyticsId, ZIndex } from '../../constants';\nimport { useInterval } from '../../hooks/useInterval';\nimport { useIsVisible } from '../../hooks/useIsVisible';\nimport { useLayoutEvent } from '../../hooks/useLayoutEvent';\nimport { useSize } from '../../hooks/useSize';\nimport { mergeRefs } from '../../utils/refs';\n\nimport styles from './styles.module.scss';\n\nexport enum PopOverVariant {\n positionautomatic = 'positionautomatic',\n positionbelow = 'positionbelow',\n positionabove = 'positionabove',\n}\n\nexport type PopOverRole = 'tooltip';\n\nexport interface PopOverProps {\n /** Id of the PopOver */\n id?: string;\n /** Content shown inside PopOver. Note that if role=\"tooltip\", you must not include interactive/focusable elements. */\n children: React.ReactNode;\n /** Ref for the element the PopOver is placed upon */\n controllerRef: React.RefObject<HTMLElement | SVGSVGElement>;\n /** Ref for the element the PopOver is placed upon */\n popOverRef?: React.RefObject<HTMLDivElement>;\n /** Show the popover. Only applies when role=tooltip. Default: false. */\n show?: boolean;\n /** Adds custom classes to the element. */\n className?: string;\n /** Adds custom classes to the arrow element. */\n arrowClassName?: string;\n /** Determines the placement of the popover. Default: automatic positioning. */\n variant?: keyof typeof PopOverVariant;\n /** Sets role of the PopOver element */\n role?: PopOverRole;\n /** Sets the data-testid attribute. */\n testId?: string;\n /** Overrides the default z-index of PopOver */\n zIndex?: number;\n}\n\nconst PopOver = React.forwardRef<HTMLDivElement | SVGSVGElement, PopOverProps>((props, ref) => {\n const {\n id,\n children,\n controllerRef,\n popOverRef,\n show = false,\n className = '',\n variant = PopOverVariant.positionautomatic,\n role,\n testId,\n arrowClassName,\n zIndex = ZIndex.PopOver,\n } = props;\n\n const bubbleRef = popOverRef || useRef<HTMLDivElement>(null);\n const arrowRef = useRef<HTMLDivElement>(null);\n const bubbleSize = useSize(bubbleRef);\n const [controllerSize, setControllerSize] = useState<DOMRect>();\n const controllerisVisible = useIsVisible(controllerRef, 0);\n\n const updateControllerSize = (): void => {\n setControllerSize(controllerRef.current?.getBoundingClientRect());\n };\n\n useInterval(updateControllerSize, 500);\n useLayoutEvent(updateControllerSize, ['scroll', 'resize'], 10);\n\n useEffect(() => {\n updateControllerSize();\n }, []);\n\n const isTooltip = role === 'tooltip';\n\n const popOverClasses = classNames(styles.popover, { [styles['popover--visible']]: isTooltip ? show : controllerisVisible }, className);\n const verticalPosition = controllerSize && bubbleSize && getVerticalPosition(controllerSize, bubbleSize, variant);\n const arrowClasses = classNames(styles.popover__arrow, arrowClassName, {\n [styles['popover__arrow--over']]: verticalPosition === PopOverVariant.positionbelow,\n [styles['popover__arrow--under']]: verticalPosition === PopOverVariant.positionabove,\n [styles['popover__arrow--visible']]: isTooltip ? show : controllerisVisible,\n });\n\n const bubbleStyle = controllerSize && bubbleSize && getBubbleStyle(controllerSize, bubbleSize, variant);\n const arrowStyle = bubbleStyle && controllerSize && verticalPosition && getArrowStyle(bubbleStyle, controllerSize, verticalPosition);\n\n return (\n <>\n <div\n id={id}\n ref={mergeRefs([ref, bubbleRef])}\n className={popOverClasses}\n style={{ ...bubbleStyle, zIndex }}\n data-testid={testId}\n data-analyticsid={AnalyticsId.PopOver}\n role={role}\n >\n {children}\n </div>\n <div ref={arrowRef} className={arrowClasses} style={{ ...arrowStyle, zIndex }} />\n </>\n );\n});\n\nPopOver.displayName = 'PopOver';\n\nexport default PopOver;\n"],"names":["PopOverVariant"],"mappings":";;;;;;;;;;AAQA,MAAM,kBAAkB;AAExB,MAAM,mBAAmB;AAEzB,MAAM,4BAA4B;AAElC,MAAM,iBAAiB;AAEvB,MAAM,2BAA2B;AAEjC,MAAM,6BAA6B;AAS5B,MAAM,sBAAsB,CACjC,gBACA,YACA,YACgC;AAC5B,MAAA,YAAY,eAAe,mBAAmB;AACzC,WAAA;AAAA,EAAA;AAET,MAAI,eAAe,MAAM,WAAW,SAAS,2BAA2B;AACtE,WAAO,eAAe;AAAA,EAAA,OACjB;AACL,WAAO,eAAe;AAAA,EAAA;AAE1B;AAOA,MAAM,4BAA4B,CAAC,mBAAoC,eAAe,OAAO,eAAe,QAAQ;AAOpH,MAAM,6BAA6B,CAAC,mBAClC,SAAS,gBAAgB,cAAc,eAAe,QAAQ,eAAe,QAAQ;AAQvF,MAAM,kBAAkB,CAAC,gBAAyB,eAAgC;AAC1E,QAAA,+BAA+B,0BAA0B,cAAc;AAEtE,SAAA,+BAA+B,WAAW,QAAQ;AAC3D;AAQA,MAAM,mBAAmB,CAAC,gBAAyB,eAAgC;AAC3E,QAAA,eAAe,gBAAgB,gBAAgB,UAAU;AAE/D,SAAO,eAAe,WAAW;AACnC;AAQA,MAAM,uBAAuB,CAAC,gBAAyB,eAAiC;AAChF,QAAA,eAAe,gBAAgB,gBAAgB,UAAU;AAE/D,SAAO,eAAe;AACxB;AAQA,MAAM,0BAA0B,CAAC,gBAAyB,eAAiC;AACnF,QAAA,gBAAgB,iBAAiB,gBAAgB,UAAU;AAE1D,SAAA,gBAAgB,SAAS,gBAAgB,cAAc;AAChE;AAQA,MAAM,wBAAwB,CAAC,gBAAyB,eAA4C;AAClG,MAAI,CAAC,wBAAwB,gBAAgB,UAAU,GAAG;AACjD,WAAA;AAAA,EAAA;AAET,MAAI,CAAC,qBAAqB,gBAAgB,UAAU,GAAG;AAC9C,WAAA;AAAA,EAAA;AAGF,SAAA;AACT;AAQA,MAAM,mBAAmB,CAAC,gBAAyB,eACjD,eAAe,MAAM,4BAA4B,WAAW;AAQ9D,MAAM,mBAAmB,CAAC,mBAAoC,eAAe,SAAS;AAMtF,MAAM,iBAAiB,MAAc,SAAS,gBAAgB,cAAc,mBAAmB;AAM/F,MAAM,wBAAwB,MAAe;AAC3C,SAAO,SAAS,gBAAgB,cAAc,kBAAkB,mBAAmB;AACrF;AAOA,MAAM,iBAAiB,CAAC,mBAAoC,eAAe,MAAM,4BAA4B;AAO7G,MAAM,iBAAiB,CAAC,mBAAoC,0BAA0B,cAAc,IAAI,iBAAiB;AAOzH,MAAM,kBAAkB,CAAC,mBAAoC,2BAA2B,cAAc,IAAI,iBAAiB;AAS3H,MAAM,oBAAoB,CAAC,gBAAyB,YAAqB,YAAyD;AAC1H,QAAA,qBAAqB,sBAAsB,gBAAgB,UAAU;AAC3E,QAAM,mBAAmB,oBAAoB,gBAAgB,YAAY,OAAO;AAEhF,MAAI,uBAAuB,QAAQ;AAC7B,QAAA,qBAAqB,eAAe,eAAe;AAC9C,aAAA;AAAA,IAAA;AAEF,WAAA;AAAA,EAAA;AAGT,MAAI,uBAAuB,SAAS;AAC9B,QAAA,qBAAqB,eAAe,eAAe;AAC9C,aAAA;AAAA,IAAA;AAEF,WAAA;AAAA,EAAA;AAGL,MAAA,qBAAqB,eAAe,eAAe;AAC9C,WAAA;AAAA,EAAA;AAGF,SAAA;AACT;AASO,MAAM,iBAAiB,CAAC,gBAAyB,YAAqB,YAAwD;AACnI,QAAM,iBAAiB,kBAAkB,gBAAgB,YAAY,OAAO;AAC5E,QAAM,cAAc,CAAC,sBAAsB,IAAI,mBAAmB;AAElE,MAAI,mBAAmB,aAAa;AAC3B,WAAA;AAAA,MACL,MAAM;AAAA,MACN,KAAK,iBAAiB,gBAAgB,UAAU;AAAA,MAChD,OAAO;AAAA,IACT;AAAA,EAAA;AAEF,MAAI,mBAAmB,aAAa;AAC3B,WAAA,EAAE,MAAM,kBAAkB,KAAK,iBAAiB,cAAc,GAAG,OAAO,YAAY;AAAA,EAAA;AAE7F,MAAI,mBAAmB,cAAc;AAC5B,WAAA,EAAE,OAAO,kBAAkB,KAAK,iBAAiB,gBAAgB,UAAU,GAAG,OAAO,YAAY;AAAA,EAAA;AAE1G,MAAI,mBAAmB,cAAc;AAC5B,WAAA,EAAE,OAAO,kBAAkB,KAAK,iBAAiB,cAAc,GAAG,OAAO,YAAY;AAAA,EAAA;AAG9F,MAAI,mBAAmB,iBAAiB;AAC/B,WAAA,EAAE,MAAM,gBAAgB,gBAAgB,UAAU,GAAG,KAAK,iBAAiB,cAAc,GAAG,OAAO,YAAY;AAAA,EAAA;AAGxH,SAAO,EAAE,MAAM,gBAAgB,gBAAgB,UAAU,GAAG,KAAK,iBAAiB,gBAAgB,UAAU,GAAG,OAAO,YAAY;AACpI;AASO,MAAM,gBAAgB,CAC3B,aACA,gBACA,qBACkB;AACZ,QAAA,SAAS,eAAe,cAAc;AACtC,QAAA,UAAU,gBAAgB,cAAc;AACxC,QAAA,YAAa,YAAY,OAAkB;AAC3C,QAAA,aAAc,YAAY,QAAmB;AAEnD,MAAI,YAAY,OAAO;AACjB,QAAA,qBAAqB,eAAe,eAAe;AAC9C,aAAA;AAAA,QACL,OAAO,UAAU,aAAa,UAAU;AAAA,QACxC,KAAK,eAAe,cAAc;AAAA,MACpC;AAAA,IAAA;AAGK,WAAA;AAAA,MACL,OAAO,UAAU,aAAa,UAAU;AAAA,MACxC,KAAK,eAAe;AAAA,IACtB;AAAA,EAAA;AAGE,MAAA,qBAAqB,eAAe,eAAe;AAC9C,WAAA;AAAA,MACL,MAAM,SAAS,YAAY,SAAS;AAAA,MACpC,KAAK,eAAe,cAAc;AAAA,IACpC;AAAA,EAAA;AAGK,SAAA;AAAA,IACL,MAAM,SAAS,YAAY,SAAS;AAAA,IACpC,KAAK,eAAe;AAAA,EACtB;AACF;AC7QY,IAAA,mCAAAA,oBAAL;AACLA,kBAAA,mBAAoB,IAAA;AACpBA,kBAAA,eAAgB,IAAA;AAChBA,kBAAA,eAAgB,IAAA;AAHNA,SAAAA;AAAA,GAAA,kBAAA,CAAA,CAAA;AAiCZ,MAAM,UAAU,MAAM,WAAyD,CAAC,OAAO,QAAQ;AACvF,QAAA;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,OAAO;AAAA,EAAA,IACd;AAEE,QAAA,YAAY,cAAc,OAAuB,IAAI;AACrD,QAAA,WAAW,OAAuB,IAAI;AACtC,QAAA,aAAa,QAAQ,SAAS;AACpC,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAkB;AACxD,QAAA,sBAAsB,aAAa,eAAe,CAAC;AAEzD,QAAM,uBAAuB,MAAY;;AACrB,uBAAA,mBAAc,YAAd,mBAAuB,uBAAuB;AAAA,EAClE;AAEA,cAAY,sBAAsB,GAAG;AACrC,iBAAe,sBAAsB,CAAC,UAAU,QAAQ,GAAG,EAAE;AAE7D,YAAU,MAAM;AACO,yBAAA;AAAA,EACvB,GAAG,EAAE;AAEL,QAAM,YAAY,SAAS;AAE3B,QAAM,iBAAiB,WAAW,OAAO,SAAS,EAAE,CAAC,OAAO,kBAAkB,CAAC,GAAG,YAAY,OAAO,oBAAA,GAAuB,SAAS;AACrI,QAAM,mBAAmB,kBAAkB,cAAc,oBAAoB,gBAAgB,YAAY,OAAO;AAChH,QAAM,eAAe,WAAW,OAAO,gBAAgB,gBAAgB;AAAA,IACrE,CAAC,OAAO,sBAAsB,CAAC,GAAG,qBAAqB;AAAA,IACvD,CAAC,OAAO,uBAAuB,CAAC,GAAG,qBAAqB;AAAA,IACxD,CAAC,OAAO,yBAAyB,CAAC,GAAG,YAAY,OAAO;AAAA,EAAA,CACzD;AAED,QAAM,cAAc,kBAAkB,cAAc,eAAe,gBAAgB,YAAY,OAAO;AACtG,QAAM,aAAa,eAAe,kBAAkB,oBAAoB,cAAc,aAAa,gBAAgB,gBAAgB;AAEnI,SAEI,qBAAA,UAAA,EAAA,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,KAAK,UAAU,CAAC,KAAK,SAAS,CAAC;AAAA,QAC/B,WAAW;AAAA,QACX,OAAO,EAAE,GAAG,aAAa,OAAO;AAAA,QAChC,eAAa;AAAA,QACb,oBAAkB,YAAY;AAAA,QAC9B;AAAA,QAEC;AAAA,MAAA;AAAA,IACH;AAAA,IACA,oBAAC,OAAI,EAAA,KAAK,UAAU,WAAW,cAAc,OAAO,EAAE,GAAG,YAAY,OAAA,EAAU,CAAA;AAAA,EAAA,GACjF;AAEJ,CAAC;AAED,QAAQ,cAAc;"}
|
|
1
|
+
{"version":3,"file":"PopOver.js","sources":["../src/components/PopOver/utils.ts","../src/components/PopOver/PopOver.tsx"],"sourcesContent":["import { CSSProperties } from 'react';\n\nimport { PopOverVariant } from './PopOver';\n\ntype HorizontalPosition = 'left' | 'right' | 'floating';\ntype BubblePosition = 'leftabove' | 'leftbelow' | 'rightabove' | 'rightbelow' | 'floatingabove' | 'floatingbelow';\n\n/** Bredde på hjelpeboble */\nconst BUBBLE_WIDTH_PX = 373;\n/** Hjelpeboblen skal holde avstand til venstre/høyre kant på vinduet */\nconst WINDOW_MARGIN_PX = 12;\n/** Vertikal avstand fra hjelpeboble til kontroller */\nconst BUBBLE_VERTICAL_OFFSET_PX = 16;\n/** Høyde/bredde på pil */\nconst ARROW_WIDTH_PX = 20;\n/** Avstand fra pil til hjelpeboble */\nconst ARROW_VERTICAL_OFFSET_PX = 4;\n/** Pilen skal holde avstand til venstre/høyre kant av hjelpeboblen */\nconst ARROW_HORIZONTAL_MARGIN_PX = 12;\n\n/**\n * Beregn om hjelpeboblen skal vises over eller under kontrolleren\n * @param controllerSize DOMRect for controlleren\n * @param bubbleSize DOMRect for hjelpeboblen\n * @param variant Ønsket plassering av hjelpeboblen (over/under/automatisk)\n * @returns Om hjelpeboblen skal vises over eller under\n */\nexport const getVerticalPosition = (\n controllerSize: DOMRect,\n bubbleSize: DOMRect,\n variant: keyof typeof PopOverVariant\n): keyof typeof PopOverVariant => {\n if (variant !== PopOverVariant.positionautomatic) {\n return variant;\n }\n if (controllerSize.top > bubbleSize.height + BUBBLE_VERTICAL_OFFSET_PX) {\n return PopOverVariant.positionabove;\n } else {\n return PopOverVariant.positionbelow;\n }\n};\n\n/**\n * Finn horisontalt midtpunkt på kontrolleren i forhold til venstre kant av vinduet\n * @param controllerSize DOMRect for controlleren\n * @returns Horisontalt senter av controlleren i px\n */\nconst getControllerLeftCenterPx = (controllerSize: DOMRect): number => controllerSize.left + controllerSize.width / 2;\n\n/**\n * Finn horisontalt midtpunkt på kontrolleren i forhold til høyre kant av vinduet\n * @param controllerSize DOMRect for controlleren\n * @returns Horisontalt senter av controlleren i px\n */\nconst getControllerRightCenterPx = (controllerSize: DOMRect): number =>\n document.documentElement.clientWidth - controllerSize.right + controllerSize.width / 2;\n\n/**\n * Finn venstre kant av hjelpeboblen i forhold til kontrolleren\n * @param controllerSize DOMRect for controlleren\n * @param bubbleSize DOMRect for hjelpeboblen\n * @returns Venstre kant av hjelpeboblen i px\n */\nconst getBubbleLeftPx = (controllerSize: DOMRect, bubbleSize: DOMRect): number => {\n const controllerHorizontalCenterPx = getControllerLeftCenterPx(controllerSize);\n\n return controllerHorizontalCenterPx - bubbleSize.width / 2;\n};\n\n/**\n * Finn høyre kant av hjelpeboblen i forhold til kontrolleren\n * @param controllerSize DOMRect for controlleren\n * @param bubbleSize DOMRect for hjelpeboblen\n * @returns Høyre kant av hjelpeboblen i px\n */\nconst getBubbleRightPx = (controllerSize: DOMRect, bubbleSize: DOMRect): number => {\n const bubbleLeftPx = getBubbleLeftPx(controllerSize, bubbleSize);\n\n return bubbleLeftPx + bubbleSize.width;\n};\n\n/**\n * Sjekk om venstre kant av hjelpeboblen er innenfor vinduet\n * @param controllerSize DOMRect for controlleren\n * @param bubbleSize DOMRect for hjelpeboblen\n * @returns true dersom venstre kant er innenfor vinduet\n */\nconst getBubbleLeftVisible = (controllerSize: DOMRect, bubbleSize: DOMRect): boolean => {\n const bubbleLeftPx = getBubbleLeftPx(controllerSize, bubbleSize);\n\n return bubbleLeftPx > WINDOW_MARGIN_PX;\n};\n\n/**\n * Sjekk om høyre kant av hjelpeboblen er innenfor vinduet\n * @param controllerSize DOMRect for controlleren\n * @param bubbleSize DOMRect for hjelpeboblen\n * @returns true dersom høyre kant er innenfor vinduet\n */\nconst getBubbleRightIsVisible = (controllerSize: DOMRect, bubbleSize: DOMRect): boolean => {\n const bubbleRightPx = getBubbleRightPx(controllerSize, bubbleSize);\n\n return bubbleRightPx < document.documentElement.clientWidth - WINDOW_MARGIN_PX;\n};\n\n/**\n * Finn riktig horisontal plassering til hjelpeboblen\n * @param controllerSize DOMRect for controlleren\n * @param bubbleSize DOMRect for hjelpeboblen\n * @returns left, right eller floating\n */\nconst getHorizontalPosition = (controllerSize: DOMRect, bubbleSize: DOMRect): HorizontalPosition => {\n if (!getBubbleRightIsVisible(controllerSize, bubbleSize)) {\n return 'right';\n }\n if (!getBubbleLeftVisible(controllerSize, bubbleSize)) {\n return 'left';\n }\n\n return 'floating';\n};\n\n/**\n * Finn vertikal plassering av hjelpeboblen når den skal vises over\n * @param controllerSize DOMRect for controlleren\n * @param bubbleSize DOMRect for hjelpeboblen\n * @returns \"Top\" for hjelpeboblen i px\n */\nconst getBubbleAbovePx = (controllerSize: DOMRect, bubbleSize: DOMRect): number =>\n controllerSize.top - BUBBLE_VERTICAL_OFFSET_PX - bubbleSize.height;\n\n/**\n * Finn vertikal plassering av hjelpeboblen når den skal vises under\n * @param controllerSize DOMRect for controlleren\n * @param bubbleSize DOMRect for hjelpeboblen\n * @returns \"Top\" for hjelpeboblen i px\n */\nconst getBubbleBelowPx = (controllerSize: DOMRect): number => controllerSize.bottom + BUBBLE_VERTICAL_OFFSET_PX;\n\n/**\n * Finn maks bredde på hjelpeboblen i forhold til vinduet\n * @returns Bredde på hjelpeboblen i px\n */\nconst getBubbleWidth = (): number => document.documentElement.clientWidth - WINDOW_MARGIN_PX * 2;\n\n/**\n * Sjekk om hjelpeboblen har plass i vinduet\n * @returns true dersom det er plass til hjelpeboblen i vinduet\n */\nconst getBubbleFitsInWindow = (): boolean => {\n return document.documentElement.clientWidth > BUBBLE_WIDTH_PX + WINDOW_MARGIN_PX * 2;\n};\n\n/**\n * Finn vertikal plassering av pilen når den skal vises over\n * @param controllerSize DOMRect for controlleren\n * @returns \"Top\" for pilen i px\n */\nconst getArrowTopxPx = (controllerSize: DOMRect): number => controllerSize.top - BUBBLE_VERTICAL_OFFSET_PX - ARROW_VERTICAL_OFFSET_PX;\n\n/**\n * Finn horisontal plassering av pilen i forhold til venstre kant av vinduet\n * @param controllerSize DOMRect for controlleren\n * @returns Venstre kant av pilen i px\n */\nconst getArrowLeftPx = (controllerSize: DOMRect): number => getControllerLeftCenterPx(controllerSize) - ARROW_WIDTH_PX / 2;\n\n/**\n * Finn horisontal plassering av pilen\n * @param controllerSize DOMRect for controlleren\n * @returns Venstre kant av pilen i px\n */\nconst getArrowRightPx = (controllerSize: DOMRect): number => getControllerRightCenterPx(controllerSize) - ARROW_WIDTH_PX / 2;\n\n/**\n * Finn riktig plassering av hjelpeboblen\n * @param controllerSize DOMRect for controlleren\n * @param bubbleSize DOMRect for hjelpeboblen\n * @param variant Ønsket plassering av hjelpeboblen (over/under)\n * @returns Beste mulige plassering av hjelpeboblen\n */\nconst getBubblePosition = (controllerSize: DOMRect, bubbleSize: DOMRect, variant: keyof typeof PopOverVariant): BubblePosition => {\n const horizontalPosition = getHorizontalPosition(controllerSize, bubbleSize);\n const verticalPosition = getVerticalPosition(controllerSize, bubbleSize, variant);\n\n if (horizontalPosition === 'left') {\n if (verticalPosition === PopOverVariant.positionabove) {\n return 'leftabove';\n }\n return 'leftbelow';\n }\n\n if (horizontalPosition === 'right') {\n if (verticalPosition === PopOverVariant.positionabove) {\n return 'rightabove';\n }\n return 'rightbelow';\n }\n\n if (verticalPosition === PopOverVariant.positionabove) {\n return 'floatingabove';\n }\n\n return 'floatingbelow';\n};\n\n/**\n * Finn riktig plassering av hjelpeboblen\n * @param controllerSize DOMRect for controlleren\n * @param bubbleSize DOMRect for hjelpeboblen\n * @param variant Ønsket plassering av hjelpeboblen (over/under)\n * @returns CSSProperties som plasserer hjelpeboblen riktig\n */\nexport const getBubbleStyle = (controllerSize: DOMRect, bubbleSize: DOMRect, variant: keyof typeof PopOverVariant): CSSProperties => {\n const bubblePosition = getBubblePosition(controllerSize, bubbleSize, variant);\n const bubbleWidth = !getBubbleFitsInWindow() ? getBubbleWidth() : undefined;\n\n if (bubblePosition === 'leftabove') {\n return {\n left: WINDOW_MARGIN_PX,\n top: getBubbleAbovePx(controllerSize, bubbleSize),\n width: bubbleWidth,\n };\n }\n if (bubblePosition === 'leftbelow') {\n return { left: WINDOW_MARGIN_PX, top: getBubbleBelowPx(controllerSize), width: bubbleWidth };\n }\n if (bubblePosition === 'rightabove') {\n return { right: WINDOW_MARGIN_PX, top: getBubbleAbovePx(controllerSize, bubbleSize), width: bubbleWidth };\n }\n if (bubblePosition === 'rightbelow') {\n return { right: WINDOW_MARGIN_PX, top: getBubbleBelowPx(controllerSize), width: bubbleWidth };\n }\n\n if (bubblePosition === 'floatingbelow') {\n return { left: getBubbleLeftPx(controllerSize, bubbleSize), top: getBubbleBelowPx(controllerSize), width: bubbleWidth };\n }\n\n return { left: getBubbleLeftPx(controllerSize, bubbleSize), top: getBubbleAbovePx(controllerSize, bubbleSize), width: bubbleWidth };\n};\n\n/**\n * Finn riktig plassering av pilen\n * @param bubbleStyle CSSProperties for hjelpeboblen\n * @param controllerSize DOMRect for kontrolleren\n * @param verticalPosition Ønsket plassering av hjelpeboblen (over/under)\n * @returns CSSProperties som plasserer pilen riktig\n */\nexport const getArrowStyle = (\n bubbleStyle: CSSProperties,\n controllerSize: DOMRect,\n verticalPosition: keyof typeof PopOverVariant\n): CSSProperties => {\n const leftPx = getArrowLeftPx(controllerSize);\n const rightPx = getArrowRightPx(controllerSize);\n const minLeftPx = (bubbleStyle.left as number) + ARROW_HORIZONTAL_MARGIN_PX;\n const minRightPx = (bubbleStyle.right as number) + ARROW_HORIZONTAL_MARGIN_PX;\n\n if (bubbleStyle.right) {\n if (verticalPosition === PopOverVariant.positionabove) {\n return {\n right: rightPx > minRightPx ? rightPx : minRightPx,\n top: getArrowTopxPx(controllerSize),\n };\n }\n\n return {\n right: rightPx > minRightPx ? rightPx : minRightPx,\n top: controllerSize.bottom,\n };\n }\n\n if (verticalPosition === PopOverVariant.positionabove) {\n return {\n left: leftPx > minLeftPx ? leftPx : minLeftPx,\n top: getArrowTopxPx(controllerSize),\n };\n }\n\n return {\n left: leftPx > minLeftPx ? leftPx : minLeftPx,\n top: controllerSize.bottom,\n };\n};\n","import React, { useEffect, useRef, useState } from 'react';\n\nimport classNames from 'classnames';\n\nimport { getArrowStyle, getBubbleStyle, getVerticalPosition } from './utils';\nimport { AnalyticsId, ZIndex } from '../../constants';\nimport { useInterval } from '../../hooks/useInterval';\nimport { useIsVisible } from '../../hooks/useIsVisible';\nimport { useLayoutEvent } from '../../hooks/useLayoutEvent';\nimport { useSize } from '../../hooks/useSize';\nimport { mergeRefs } from '../../utils/refs';\n\nimport styles from './styles.module.scss';\n\nexport enum PopOverVariant {\n positionautomatic = 'positionautomatic',\n positionbelow = 'positionbelow',\n positionabove = 'positionabove',\n}\n\nexport type PopOverRole = 'tooltip';\n\nexport interface PopOverProps {\n /** Id of the PopOver */\n id?: string;\n /** Content shown inside PopOver. Note that if role=\"tooltip\", you must not include interactive/focusable elements. */\n children: React.ReactNode;\n /** Ref for the element the PopOver is placed upon */\n controllerRef: React.RefObject<HTMLElement | SVGSVGElement>;\n /** Ref for the element the PopOver is placed upon */\n popOverRef?: React.RefObject<HTMLDivElement>;\n /** Show the popover. Only applies when role=tooltip. Default: false. */\n show?: boolean;\n /** Adds custom classes to the element. */\n className?: string;\n /** Adds custom classes to the arrow element. */\n arrowClassName?: string;\n /** Determines the placement of the popover. Default: automatic positioning. */\n variant?: keyof typeof PopOverVariant;\n /** Sets role of the PopOver element */\n role?: PopOverRole;\n /** Sets the data-testid attribute. */\n testId?: string;\n /** Overrides the default z-index of PopOver */\n zIndex?: number;\n}\n\nconst PopOver = React.forwardRef<HTMLDivElement | SVGSVGElement, PopOverProps>((props, ref) => {\n const {\n id,\n children,\n controllerRef,\n popOverRef,\n show = false,\n className = '',\n variant = PopOverVariant.positionautomatic,\n role,\n testId,\n arrowClassName,\n zIndex = ZIndex.PopOver,\n } = props;\n\n const bubbleRef = popOverRef || useRef<HTMLDivElement>(null);\n const arrowRef = useRef<HTMLDivElement>(null);\n const bubbleSize = useSize(bubbleRef);\n const [controllerSize, setControllerSize] = useState<DOMRect>();\n const controllerisVisible = useIsVisible(bubbleRef, 0);\n\n const updateControllerSize = (): void => {\n setControllerSize(controllerRef.current?.getBoundingClientRect());\n };\n\n useInterval(updateControllerSize, 500);\n useLayoutEvent(updateControllerSize, ['scroll', 'resize'], 10);\n\n useEffect(() => {\n updateControllerSize();\n }, []);\n\n const isTooltip = role === 'tooltip';\n\n const popOverClasses = classNames(styles.popover, { [styles['popover--visible']]: isTooltip ? show : controllerisVisible }, className);\n const verticalPosition = controllerSize && bubbleSize && getVerticalPosition(controllerSize, bubbleSize, variant);\n const arrowClasses = classNames(styles.popover__arrow, arrowClassName, {\n [styles['popover__arrow--over']]: verticalPosition === PopOverVariant.positionbelow,\n [styles['popover__arrow--under']]: verticalPosition === PopOverVariant.positionabove,\n [styles['popover__arrow--visible']]: isTooltip ? show : controllerisVisible,\n });\n\n const bubbleStyle = controllerSize && bubbleSize && getBubbleStyle(controllerSize, bubbleSize, variant);\n const arrowStyle = bubbleStyle && controllerSize && verticalPosition && getArrowStyle(bubbleStyle, controllerSize, verticalPosition);\n\n return (\n <>\n <div\n id={id}\n ref={mergeRefs([ref, bubbleRef])}\n className={popOverClasses}\n style={{ ...bubbleStyle, zIndex }}\n data-testid={testId}\n data-analyticsid={AnalyticsId.PopOver}\n role={role}\n >\n {children}\n </div>\n <div ref={arrowRef} className={arrowClasses} style={{ ...arrowStyle, zIndex }} />\n </>\n );\n});\n\nPopOver.displayName = 'PopOver';\n\nexport default PopOver;\n"],"names":["PopOverVariant"],"mappings":"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"}
|
package/TabList.js
CHANGED
|
@@ -9,6 +9,9 @@ import styles from "./components/Tabs/TabList/styles.module.scss";
|
|
|
9
9
|
import { useIsVisible } from "./hooks/useIsVisible.js";
|
|
10
10
|
import { useRovingFocus } from "./hooks/useRovingFocus.js";
|
|
11
11
|
import { isComponent } from "./utils/component.js";
|
|
12
|
+
import { useHover } from "./hooks/useHover.js";
|
|
13
|
+
import ChevronLeft from "./components/Icons/ChevronLeft.js";
|
|
14
|
+
import ChevronRight from "./components/Icons/ChevronRight.js";
|
|
12
15
|
const Tab = (props) => {
|
|
13
16
|
return /* @__PURE__ */ jsx(Fragment, { children: props.children ?? null });
|
|
14
17
|
};
|
|
@@ -32,7 +35,7 @@ const TabItem = (props) => {
|
|
|
32
35
|
};
|
|
33
36
|
const itemRef = useRef(null);
|
|
34
37
|
useEffect(() => {
|
|
35
|
-
if (isSelected) {
|
|
38
|
+
if (isSelected && props.tabListVisible) {
|
|
36
39
|
scrollToTab(props.index);
|
|
37
40
|
}
|
|
38
41
|
}, [isSelected]);
|
|
@@ -62,8 +65,24 @@ const TabItem = (props) => {
|
|
|
62
65
|
}
|
|
63
66
|
) });
|
|
64
67
|
};
|
|
68
|
+
const TabChevron = ({ direction, onClick, backgroundColor, ariaLabel }) => {
|
|
69
|
+
const buttonRef = React.useRef(null);
|
|
70
|
+
const { isHovered } = useHover(buttonRef);
|
|
71
|
+
return /* @__PURE__ */ jsx(
|
|
72
|
+
"button",
|
|
73
|
+
{
|
|
74
|
+
type: "button",
|
|
75
|
+
ref: buttonRef,
|
|
76
|
+
className: styles["tab-list__button"],
|
|
77
|
+
onClick,
|
|
78
|
+
"aria-label": ariaLabel,
|
|
79
|
+
style: { backgroundColor },
|
|
80
|
+
children: direction === "left" ? /* @__PURE__ */ jsx(Icon, { color: "var(--color-action-graphics-onlight)", isHovered, svgIcon: ChevronLeft, size: IconSize.XSmall }) : /* @__PURE__ */ jsx(Icon, { color: "var(--color-action-graphics-onlight)", isHovered, svgIcon: ChevronRight, size: IconSize.XSmall })
|
|
81
|
+
}
|
|
82
|
+
);
|
|
83
|
+
};
|
|
65
84
|
const TabList = (props) => {
|
|
66
|
-
const { selectedTab, onTabListClick, children, color, onColor } = props;
|
|
85
|
+
const { selectedTab, onTabListClick, children, color, onColor, ariaLabelLeftButton, ariaLabelRightButton } = props;
|
|
67
86
|
const listRef = useRef(null);
|
|
68
87
|
const tabRefs = useRef(React.Children.map(children, () => React.createRef()) || []);
|
|
69
88
|
useRovingFocus(onTabListClick, tabRefs, listRef, true);
|
|
@@ -82,29 +101,55 @@ const TabList = (props) => {
|
|
|
82
101
|
const lastTab = tabRefs.current && tabRefs.current[tabRefs.current.length - 1];
|
|
83
102
|
const firstTabVisible = useIsVisible(firstTab);
|
|
84
103
|
const lastTabVisible = useIsVisible(lastTab);
|
|
104
|
+
const tabListVisible = useIsVisible(listRef);
|
|
85
105
|
const shouldShowFadeStart = () => {
|
|
86
|
-
return !firstTabVisible
|
|
106
|
+
return !firstTabVisible;
|
|
87
107
|
};
|
|
88
108
|
const shouldShowFadeEnd = () => {
|
|
89
|
-
return !lastTabVisible
|
|
109
|
+
return !lastTabVisible;
|
|
110
|
+
};
|
|
111
|
+
const scrollInList = (direction) => {
|
|
112
|
+
if (listRef.current) {
|
|
113
|
+
const listWidth = listRef.current.clientWidth;
|
|
114
|
+
const listScrollLeft = listRef.current.scrollLeft;
|
|
115
|
+
const maxScrollLeft = listRef.current.scrollWidth - listWidth;
|
|
116
|
+
if (direction === "right" && !lastTabVisible) {
|
|
117
|
+
const scrollAmount = Math.min(listWidth / 2, maxScrollLeft - listScrollLeft);
|
|
118
|
+
listRef.current.scrollBy({ left: scrollAmount, behavior: "smooth" });
|
|
119
|
+
} else if (direction === "left" && !firstTabVisible) {
|
|
120
|
+
const scrollAmount = -Math.min(listWidth / 2, listScrollLeft);
|
|
121
|
+
listRef.current.scrollBy({ left: scrollAmount, behavior: "smooth" });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
90
124
|
};
|
|
91
125
|
return /* @__PURE__ */ jsxs("div", { children: [
|
|
92
|
-
/* @__PURE__ */
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
backgroundColor: `${getBackgroundColor(onColor)}
|
|
126
|
+
shouldShowFadeStart() && /* @__PURE__ */ jsxs("div", { className: classNames(styles["tab-list__start-wrapper"]), children: [
|
|
127
|
+
/* @__PURE__ */ jsx(
|
|
128
|
+
TabChevron,
|
|
129
|
+
{
|
|
130
|
+
onClick: () => scrollInList("left"),
|
|
131
|
+
direction: "left",
|
|
132
|
+
backgroundColor: `${getBackgroundColor(onColor)}`,
|
|
133
|
+
ariaLabel: ariaLabelLeftButton
|
|
99
134
|
}
|
|
100
|
-
|
|
101
|
-
|
|
135
|
+
),
|
|
136
|
+
/* @__PURE__ */ jsx(
|
|
137
|
+
"div",
|
|
138
|
+
{
|
|
139
|
+
className: classNames(styles["tab-list__fade-start"]),
|
|
140
|
+
style: {
|
|
141
|
+
backgroundColor: `${getBackgroundColor(onColor)}`
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
)
|
|
145
|
+
] }),
|
|
102
146
|
/* @__PURE__ */ jsx("ul", { className: tablistClasses, ref: listRef, role: "tablist", "aria-orientation": "horizontal", children: React.Children.map(children, (child, index) => {
|
|
103
147
|
if (isComponent(child, Tab)) {
|
|
104
148
|
return /* @__PURE__ */ jsx(
|
|
105
149
|
TabItem,
|
|
106
150
|
{
|
|
107
151
|
tabRefs,
|
|
152
|
+
tabListVisible,
|
|
108
153
|
index,
|
|
109
154
|
selectedTab,
|
|
110
155
|
onTabListClick,
|
|
@@ -116,16 +161,26 @@ const TabList = (props) => {
|
|
|
116
161
|
}
|
|
117
162
|
return null;
|
|
118
163
|
}) }),
|
|
119
|
-
/* @__PURE__ */
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
164
|
+
shouldShowFadeEnd() && /* @__PURE__ */ jsxs("div", { className: classNames(styles["tab-list__end-wrapper"]), children: [
|
|
165
|
+
/* @__PURE__ */ jsx(
|
|
166
|
+
"div",
|
|
167
|
+
{
|
|
168
|
+
className: classNames(styles["tab-list__fade-end"]),
|
|
169
|
+
style: {
|
|
170
|
+
backgroundColor: `${getBackgroundColor(onColor)}`
|
|
171
|
+
}
|
|
126
172
|
}
|
|
127
|
-
|
|
128
|
-
|
|
173
|
+
),
|
|
174
|
+
/* @__PURE__ */ jsx(
|
|
175
|
+
TabChevron,
|
|
176
|
+
{
|
|
177
|
+
onClick: () => scrollInList("right"),
|
|
178
|
+
direction: "right",
|
|
179
|
+
backgroundColor: `${getBackgroundColor(onColor)}`,
|
|
180
|
+
ariaLabel: ariaLabelRightButton
|
|
181
|
+
}
|
|
182
|
+
)
|
|
183
|
+
] }),
|
|
129
184
|
/* @__PURE__ */ jsx("div", { className: classNames(styles["tab-list__border"]) })
|
|
130
185
|
] });
|
|
131
186
|
};
|
package/TabList.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TabList.js","sources":["../src/components/Tabs/Tab.tsx","../src/components/Tabs/TabList/TabItem.tsx","../src/components/Tabs/TabList/TabList.tsx"],"sourcesContent":["import React from 'react';\n\nimport { SvgIcon } from '../Icon';\nimport { IconName } from '../Icons/IconNames';\n\nexport interface TabProps {\n /** Sets the tab panel content */\n children?: React.ReactNode;\n /** Optional icon on the tab */\n icon?: SvgIcon | IconName;\n /** Called when tab is selected */\n onTabClick?: (index: number) => void;\n /** Sets the data-testid attribute. */\n testId?: string;\n /** Title on the tab */\n title?: string;\n}\n\nconst Tab: React.FC<TabProps> = props => {\n return <>{props.children ?? null}</>;\n};\n\nexport default Tab;\n","import React, { useEffect, useRef } from 'react';\n\nimport classNames from 'classnames';\n\nimport { palette } from '../../../theme/palette';\nimport Icon, { IconSize } from '../../Icon';\nimport { IconName } from '../../Icons/IconNames';\nimport LazyIcon from '../../LazyIcon';\nimport { TabProps } from '../Tab';\nimport { TabsColors } from '../Tabs';\n\nimport styles from './styles.module.scss';\n\ninterface TabItemProps {\n tabProps: TabProps;\n index: number;\n color: TabsColors;\n selectedTab: number;\n tabRefs: React.MutableRefObject<React.RefObject<HTMLButtonElement>[] | null | undefined>;\n onTabListClick: (index: number) => void;\n}\n\nconst TabItem: React.FC<TabItemProps> = props => {\n const isSelected = props.index === props.selectedTab;\n const { title, onTabClick, icon, testId } = props.tabProps;\n const handleClick = (): void => {\n onTabClick && onTabClick(props.index);\n props.onTabListClick(props.index);\n scrollToTab(props.index);\n };\n const tabButtonClasses = classNames(styles['tab-list__tab'], styles[`tab-list__tab--${props.color}`], {\n [styles['tab-list__tab--selected']]: isSelected,\n [styles['tab-list__tab--not-selected']]: !isSelected,\n });\n\n const currentRef = props.tabRefs.current && props.tabRefs.current[props.index];\n\n const scrollToTab = (index: number): void => {\n const currentRef = props.tabRefs.current && props.tabRefs.current[index];\n currentRef?.current?.scrollIntoView && currentRef?.current?.scrollIntoView({ behavior: 'smooth', inline: 'nearest', block: 'nearest' });\n };\n\n const itemRef = useRef<HTMLLIElement>(null);\n\n useEffect(() => {\n if (isSelected) {\n scrollToTab(props.index);\n }\n }, [isSelected]);\n\n return (\n <li role=\"presentation\" ref={itemRef}>\n <button\n role=\"tab\"\n aria-selected={isSelected}\n onClick={handleClick}\n className={tabButtonClasses}\n data-testid={testId}\n ref={currentRef as React.RefObject<HTMLButtonElement>}\n style={{\n borderBottom: isSelected\n ? `2px solid var(--color-base-background-${props.color})`\n : '1px solid var(--color-action-border-onlight-focus)',\n }}\n >\n <span className={styles['tab-list__tab__title-and-icon']}>\n {icon &&\n (typeof icon === 'string' ? (\n <LazyIcon\n iconName={icon as IconName}\n size={IconSize.XSmall}\n color={isSelected ? palette[`black`] : palette['blueberry500']}\n />\n ) : (\n <Icon svgIcon={icon} size={IconSize.XSmall} color={isSelected ? palette[`black`] : palette['blueberry500']} />\n ))}\n {title}\n </span>\n </button>\n </li>\n );\n};\n\nexport default TabItem;\n","import React, { useRef } from 'react';\n\nimport classNames from 'classnames';\n\nimport TabItem from './TabItem';\nimport { useIsVisible } from '../../../hooks/useIsVisible';\nimport { useRovingFocus } from '../../../hooks/useRovingFocus';\nimport { isComponent } from '../../../utils/component';\nimport Tab, { TabProps } from '../Tab';\nimport { TabsColors, TabsOnColor } from '../Tabs';\n\nimport styles from './styles.module.scss';\ninterface TabListProps {\n children: React.ReactNode;\n onTabListClick: (index: number) => void;\n selectedTab: number;\n color: TabsColors;\n onColor: TabsOnColor;\n}\n\nconst TabList: React.FC<TabListProps> = props => {\n const { selectedTab, onTabListClick, children, color, onColor } = props;\n\n const listRef = useRef<HTMLUListElement>(null);\n\n const tabRefs = useRef(React.Children.map(children, () => React.createRef<HTMLButtonElement>()) || []);\n useRovingFocus(onTabListClick, tabRefs, listRef, true);\n\n const tablistClasses = classNames(styles['tab-list'], styles[`tab-list--${onColor}`]);\n\n const getBackgroundColor = (onColor: TabsOnColor): string => {\n switch (onColor) {\n case 'onwhite':\n return 'var(--color-base-background-white)';\n case 'onblueberry':\n return 'var(--color-base-background-blueberry)';\n case 'onneutral':\n return 'var(--color-base-background-neutral)';\n }\n };\n const firstTab = tabRefs.current && tabRefs.current[0];\n const lastTab = tabRefs.current && tabRefs.current[tabRefs.current.length - 1];\n\n const firstTabVisible = useIsVisible(firstTab);\n const lastTabVisible = useIsVisible(lastTab);\n\n const shouldShowFadeStart = (): boolean => {\n return !firstTabVisible && selectedTab !== 0;\n };\n\n const shouldShowFadeEnd = (): boolean => {\n return !lastTabVisible && selectedTab !== tabRefs.current.length - 1;\n };\n\n return (\n <div>\n <div\n className={classNames(styles['tab-list__fade-start'])}\n style={{\n display: shouldShowFadeStart() ? 'block' : 'none',\n backgroundColor: `${getBackgroundColor(onColor)}`,\n }}\n ></div>\n <ul className={tablistClasses} ref={listRef} role=\"tablist\" aria-orientation=\"horizontal\">\n {React.Children.map(children, (child, index) => {\n if (isComponent<TabProps>(child, Tab)) {\n return (\n <TabItem\n tabRefs={tabRefs}\n key={child.props.title}\n index={index}\n selectedTab={selectedTab}\n onTabListClick={onTabListClick}\n tabProps={child.props}\n color={color}\n />\n );\n }\n return null;\n })}\n </ul>\n <div\n className={classNames(styles['tab-list__fade-end'])}\n style={{\n display: shouldShowFadeEnd() ? 'block' : 'none',\n backgroundColor: `${getBackgroundColor(onColor)}`,\n }}\n ></div>\n <div className={classNames(styles['tab-list__border'])}></div>\n </div>\n );\n};\n\nexport default TabList;\n"],"names":["currentRef","onColor"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TabList.js","sources":["../src/components/Tabs/Tab.tsx","../src/components/Tabs/TabList/TabItem.tsx","../src/components/Tabs/TabList/TabChevron.tsx","../src/components/Tabs/TabList/TabList.tsx"],"sourcesContent":["import React from 'react';\n\nimport { SvgIcon } from '../Icon';\nimport { IconName } from '../Icons/IconNames';\n\nexport interface TabProps {\n /** Sets the tab panel content */\n children?: React.ReactNode;\n /** Optional icon on the tab */\n icon?: SvgIcon | IconName;\n /** Called when tab is selected */\n onTabClick?: (index: number) => void;\n /** Sets the data-testid attribute. */\n testId?: string;\n /** Title on the tab */\n title?: string;\n}\n\nconst Tab: React.FC<TabProps> = props => {\n return <>{props.children ?? null}</>;\n};\n\nexport default Tab;\n","import React, { useEffect, useRef } from 'react';\n\nimport classNames from 'classnames';\n\nimport { palette } from '../../../theme/palette';\nimport Icon, { IconSize } from '../../Icon';\nimport { IconName } from '../../Icons/IconNames';\nimport LazyIcon from '../../LazyIcon';\nimport { TabProps } from '../Tab';\nimport { TabsColors } from '../Tabs';\n\nimport styles from './styles.module.scss';\n\ninterface TabItemProps {\n tabProps: TabProps;\n index: number;\n color: TabsColors;\n selectedTab: number;\n tabRefs: React.MutableRefObject<React.RefObject<HTMLButtonElement>[] | null | undefined>;\n tabListVisible: boolean;\n onTabListClick: (index: number) => void;\n}\n\nconst TabItem: React.FC<TabItemProps> = props => {\n const isSelected = props.index === props.selectedTab;\n const { title, onTabClick, icon, testId } = props.tabProps;\n const handleClick = (): void => {\n onTabClick && onTabClick(props.index);\n props.onTabListClick(props.index);\n scrollToTab(props.index);\n };\n const tabButtonClasses = classNames(styles['tab-list__tab'], styles[`tab-list__tab--${props.color}`], {\n [styles['tab-list__tab--selected']]: isSelected,\n [styles['tab-list__tab--not-selected']]: !isSelected,\n });\n\n const currentRef = props.tabRefs.current && props.tabRefs.current[props.index];\n\n const scrollToTab = (index: number): void => {\n const currentRef = props.tabRefs.current && props.tabRefs.current[index];\n currentRef?.current?.scrollIntoView && currentRef?.current?.scrollIntoView({ behavior: 'smooth', inline: 'nearest', block: 'nearest' });\n };\n\n const itemRef = useRef<HTMLLIElement>(null);\n\n useEffect(() => {\n if (isSelected && props.tabListVisible) {\n scrollToTab(props.index);\n }\n }, [isSelected]);\n\n return (\n <li role=\"presentation\" ref={itemRef}>\n <button\n role=\"tab\"\n aria-selected={isSelected}\n onClick={handleClick}\n className={tabButtonClasses}\n data-testid={testId}\n ref={currentRef as React.RefObject<HTMLButtonElement>}\n style={{\n borderBottom: isSelected\n ? `2px solid var(--color-base-background-${props.color})`\n : '1px solid var(--color-action-border-onlight-focus)',\n }}\n >\n <span className={styles['tab-list__tab__title-and-icon']}>\n {icon &&\n (typeof icon === 'string' ? (\n <LazyIcon\n iconName={icon as IconName}\n size={IconSize.XSmall}\n color={isSelected ? palette[`black`] : palette['blueberry500']}\n />\n ) : (\n <Icon svgIcon={icon} size={IconSize.XSmall} color={isSelected ? palette[`black`] : palette['blueberry500']} />\n ))}\n {title}\n </span>\n </button>\n </li>\n );\n};\n\nexport default TabItem;\n","import React from 'react';\n\nimport { useHover } from '../../../hooks/useHover';\nimport Icon, { IconSize } from '../../Icon';\nimport ChevronLeft from '../../Icons/ChevronLeft';\nimport ChevronRight from '../../Icons/ChevronRight';\n\nimport styles from './styles.module.scss';\n\ninterface TabChevronProps {\n direction: 'left' | 'right';\n onClick: () => void;\n backgroundColor?: string;\n ariaLabel?: string;\n}\n\nconst TabChevron: React.FC<TabChevronProps> = ({ direction, onClick, backgroundColor, ariaLabel }) => {\n const buttonRef = React.useRef<HTMLButtonElement>(null);\n const { isHovered } = useHover<HTMLButtonElement>(buttonRef);\n\n return (\n <button\n type=\"button\"\n ref={buttonRef}\n className={styles['tab-list__button']}\n onClick={onClick}\n aria-label={ariaLabel}\n style={{ backgroundColor: backgroundColor }}\n >\n {direction === 'left' ? (\n <Icon color={'var(--color-action-graphics-onlight)'} isHovered={isHovered} svgIcon={ChevronLeft} size={IconSize.XSmall} />\n ) : (\n <Icon color={'var(--color-action-graphics-onlight)'} isHovered={isHovered} svgIcon={ChevronRight} size={IconSize.XSmall} />\n )}\n </button>\n );\n};\n\nexport default TabChevron;\n","import React, { useRef } from 'react';\n\nimport classNames from 'classnames';\n\nimport TabItem from './TabItem';\nimport { useIsVisible } from '../../../hooks/useIsVisible';\nimport { useRovingFocus } from '../../../hooks/useRovingFocus';\nimport { isComponent } from '../../../utils/component';\nimport Tab, { TabProps } from '../Tab';\nimport { TabsColors, TabsOnColor } from '../Tabs';\nimport TabChevron from './TabChevron';\n\nimport styles from './styles.module.scss';\ninterface TabListProps {\n children: React.ReactNode;\n onTabListClick: (index: number) => void;\n selectedTab: number;\n color: TabsColors;\n onColor: TabsOnColor;\n ariaLabelRightButton?: string;\n ariaLabelLeftButton?: string;\n}\n\nconst TabList: React.FC<TabListProps> = props => {\n const { selectedTab, onTabListClick, children, color, onColor, ariaLabelLeftButton, ariaLabelRightButton } = props;\n\n const listRef = useRef<HTMLUListElement>(null);\n\n const tabRefs = useRef(React.Children.map(children, () => React.createRef<HTMLButtonElement>()) || []);\n useRovingFocus(onTabListClick, tabRefs, listRef, true);\n\n const tablistClasses = classNames(styles['tab-list'], styles[`tab-list--${onColor}`]);\n\n const getBackgroundColor = (onColor: TabsOnColor): string => {\n switch (onColor) {\n case 'onwhite':\n return 'var(--color-base-background-white)';\n case 'onblueberry':\n return 'var(--color-base-background-blueberry)';\n case 'onneutral':\n return 'var(--color-base-background-neutral)';\n }\n };\n const firstTab = tabRefs.current && tabRefs.current[0];\n const lastTab = tabRefs.current && tabRefs.current[tabRefs.current.length - 1];\n\n const firstTabVisible = useIsVisible(firstTab);\n const lastTabVisible = useIsVisible(lastTab);\n const tabListVisible = useIsVisible(listRef);\n\n const shouldShowFadeStart = (): boolean => {\n return !firstTabVisible;\n };\n\n const shouldShowFadeEnd = (): boolean => {\n return !lastTabVisible;\n };\n\n const scrollInList = (direction: string): void => {\n if (listRef.current) {\n const listWidth = listRef.current.clientWidth;\n const listScrollLeft = listRef.current.scrollLeft;\n const maxScrollLeft = listRef.current.scrollWidth - listWidth;\n\n if (direction === 'right' && !lastTabVisible) {\n const scrollAmount = Math.min(listWidth / 2, maxScrollLeft - listScrollLeft);\n listRef.current.scrollBy({ left: scrollAmount, behavior: 'smooth' });\n } else if (direction === 'left' && !firstTabVisible) {\n const scrollAmount = -Math.min(listWidth / 2, listScrollLeft);\n listRef.current.scrollBy({ left: scrollAmount, behavior: 'smooth' });\n }\n }\n };\n\n return (\n <div>\n {shouldShowFadeStart() && (\n <div className={classNames(styles['tab-list__start-wrapper'])}>\n <TabChevron\n onClick={() => scrollInList('left')}\n direction=\"left\"\n backgroundColor={`${getBackgroundColor(onColor)}`}\n ariaLabel={ariaLabelLeftButton}\n />\n <div\n className={classNames(styles['tab-list__fade-start'])}\n style={{\n backgroundColor: `${getBackgroundColor(onColor)}`,\n }}\n ></div>\n </div>\n )}\n <ul className={tablistClasses} ref={listRef} role=\"tablist\" aria-orientation=\"horizontal\">\n {React.Children.map(children, (child, index) => {\n if (isComponent<TabProps>(child, Tab)) {\n return (\n <TabItem\n tabRefs={tabRefs}\n tabListVisible={tabListVisible}\n key={child.props.title}\n index={index}\n selectedTab={selectedTab}\n onTabListClick={onTabListClick}\n tabProps={child.props}\n color={color}\n />\n );\n }\n return null;\n })}\n </ul>\n {shouldShowFadeEnd() && (\n <div className={classNames(styles['tab-list__end-wrapper'])}>\n <div\n className={classNames(styles['tab-list__fade-end'])}\n style={{\n backgroundColor: `${getBackgroundColor(onColor)}`,\n }}\n ></div>\n <TabChevron\n onClick={() => scrollInList('right')}\n direction=\"right\"\n backgroundColor={`${getBackgroundColor(onColor)}`}\n ariaLabel={ariaLabelRightButton}\n />\n </div>\n )}\n <div className={classNames(styles['tab-list__border'])}></div>\n </div>\n );\n};\n\nexport default TabList;\n"],"names":["currentRef","onColor"],"mappings":"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"}
|