@helsenorge/designsystem-react 10.0.1 → 10.1.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/Button.js +1 -1
- package/Button.js.map +1 -1
- package/CHANGELOG.md +22 -0
- package/Expander.js +2 -2
- package/Expander.js.map +1 -1
- package/components/ListHeader/styles.module.scss +2 -0
- package/components/StickyNote/index.js +12 -6
- package/components/StickyNote/index.js.map +1 -1
- package/components/Tabs/Tabs.d.ts +2 -0
- package/components/Tabs/index.js +5 -1
- package/components/Tabs/index.js.map +1 -1
- package/hooks/useOutsideEvent.d.ts +4 -4
- package/hooks/useOutsideEvent.js +5 -4
- package/hooks/useOutsideEvent.js.map +1 -1
- package/package.json +1 -1
package/Button.js
CHANGED
|
@@ -116,7 +116,7 @@ const Button = React.forwardRef(function ButtonForwardedRef(props, ref) {
|
|
|
116
116
|
return iconElement ? React.cloneElement(iconElement, {
|
|
117
117
|
size: iconSize,
|
|
118
118
|
color: (iconElement == null ? void 0 : iconElement.props.color) && !disabled ? iconElement.props.color : iconColor,
|
|
119
|
-
isHovered: !disabled && isHovered,
|
|
119
|
+
isHovered: iconElement.props.isHovered === void 0 ? !disabled && isHovered : iconElement.props.isHovered,
|
|
120
120
|
className: iconClassName
|
|
121
121
|
}) : null;
|
|
122
122
|
};
|
package/Button.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.js","sources":["../src/components/Button/Button.tsx"],"sourcesContent":["import React, { AriaAttributes, useEffect, useRef } from 'react';\n\nimport classNames from 'classnames';\n\nimport Icon, { IconSize } from './../Icon';\nimport { HTMLButtonProps, HTMLAnchorProps, AnalyticsId } from '../../constants';\nimport { useBreakpoint } from '../../hooks/useBreakpoint';\nimport { useHover } from '../../hooks/useHover';\nimport { BaseIconElement, useIcons } from '../../hooks/useIcons';\nimport { getColor } from '../../theme/currys/color';\nimport { breakpoints } from '../../theme/grid';\nimport { isTest, isProd } from '../../utils/environment';\nimport ArrowRight from '../Icons/ArrowRight';\n\nimport buttonStyles from './styles.module.scss';\n\nexport type ButtonConcept = 'normal' | 'destructive';\nexport type ButtonVariant = 'fill' | 'outline' | 'borderless';\nexport type ButtonSize = 'medium' | 'large';\nexport type ButtonOnColor = 'onlight' | 'ondark';\nexport type ButtonTags = 'button' | 'a';\nexport type ButtonArrows = 'icon' | 'accessibility-character';\nexport type ButtonTextPosition = 'left' | 'centered';\n\nexport interface ButtonProps extends HTMLButtonProps, HTMLAnchorProps, AriaAttributes {\n /** Sets the aria-label of the button, use when the button only includes an icon */\n ariaLabel?: string;\n /** Gives a unique id to the button */\n id?: string;\n /** Sets the content of the button. */\n children: React.ReactNode;\n /** Adds custom classes to the wrapper element. */\n wrapperClassName?: string;\n /** Adds custom classes to the element. */\n className?: string;\n /** Enables an arrow icon to the right inside the button (Not available in borderless variant) */\n arrow?: ButtonArrows;\n /** Changes the intent of the button. Mostly changes the color profile. */\n concept?: ButtonConcept;\n /** Disables text wrapping and enables ellipsis. */\n ellipsis?: boolean;\n /** Makes the button scale to full width of its parent element. */\n fluid?: boolean;\n /** Changes the underlying element of the button. */\n htmlMarkup?: ButtonTags;\n /** Changes the button colors for different backgrounds. */\n onColor?: ButtonOnColor;\n /** Function that is called when the Button loses focus */\n onBlur?: () => void;\n /** Function that is called when clicked */\n onClick?: (e?: React.MouseEvent<HTMLElement, MouseEvent> | React.FormEvent<{}> | React.KeyboardEvent<HTMLUListElement> | null) => void;\n /** Changes the button colors for different backgrounds. (Large not available in borderless variant) */\n size?: ButtonSize;\n /** Changes the visual representation of the button. */\n variant?: ButtonVariant;\n /** Specifies the focus order relative to the other buttons or controls on the page */\n tabIndex?: number;\n /** Sets the data-testid attribute. */\n testId?: string;\n /** Adds custom classes to the text */\n textClassName?: string;\n /** Sets the position of the text in the button - only applies when button is fluid */\n textPosition?: ButtonTextPosition;\n /** Button type. Default: button */\n type?: React.ButtonHTMLAttributes<HTMLButtonElement>['type'];\n}\n\nconst getIconColor = (\n fill: boolean,\n borderless: boolean,\n disabled: boolean,\n concept: ButtonConcept,\n ondark: boolean,\n mobile: boolean\n): string => {\n if (mobile && disabled) {\n return !ondark || fill ? getColor('neutral', !borderless ? 700 : 500) : getColor('white');\n }\n if (disabled) {\n return !ondark || fill ? getColor('neutral', 500) : `${getColor('white')}b3`;\n }\n if ((fill && !ondark) || (!fill && ondark)) {\n return 'white';\n }\n\n return concept === 'normal' ? getColor('blueberry', 600) : getColor('cherry', 500);\n};\nconst getLargeIconSize = (large: boolean, mobile: boolean): IconSize => {\n if (mobile && large) return IconSize.Small;\n if (large) return IconSize.Medium;\n return IconSize.XSmall;\n};\n\nconst checkOnlyIconAria = (onlyIcon: boolean, ariaLabel: string | undefined, devEnv: boolean): void => {\n if (devEnv && onlyIcon && (ariaLabel === undefined || ariaLabel === '')) {\n throw new Error('Fyll inn ariaLabel prop på Button uten tekst for å opprettholde UU krav');\n }\n};\n\nconst Button = React.forwardRef(function ButtonForwardedRef(\n props: ButtonProps,\n ref: React.ForwardedRef<HTMLButtonElement | HTMLAnchorElement>\n) {\n const {\n ariaLabel,\n id,\n children,\n wrapperClassName,\n className,\n arrow,\n concept = 'normal',\n disabled = false,\n ellipsis = false,\n fluid = false,\n htmlMarkup = 'button',\n onColor = 'onlight',\n onBlur,\n onClick,\n size = 'medium',\n variant = 'fill',\n href,\n tabIndex,\n testId,\n target,\n type = 'button',\n textClassName,\n textPosition = 'left',\n ...restProps\n } = props;\n\n const [leftIcon, rightIcon, restChildren] = useIcons(React.Children.toArray(children));\n const { hoverRef, isHovered } =\n htmlMarkup === 'button'\n ? useHover<HTMLButtonElement>(ref as React.RefObject<HTMLButtonElement>)\n : useHover<HTMLAnchorElement>(ref as React.RefObject<HTMLAnchorElement>);\n const buttonContentRef = useRef<HTMLDivElement>(null);\n const onlyIcon = !!(leftIcon || rightIcon) && !restChildren;\n const bothIcons = leftIcon && (rightIcon || arrow) && !onlyIcon;\n const onDark = onColor === 'ondark';\n const breakpoint = useBreakpoint();\n const mobile = breakpoint < breakpoints.md;\n const destructive = concept === 'destructive' && !disabled;\n const outlineVariant = variant === 'outline';\n const borderlessVariant = variant === 'borderless';\n const iconColor = getIconColor(variant === 'fill', borderlessVariant, disabled, concept, onDark, mobile);\n const hasArrow = arrow === 'icon' && !borderlessVariant;\n const large = size === 'large' && !destructive && !borderlessVariant;\n const hasUURightArrow = arrow === 'accessibility-character' && !fluid && !leftIcon && !rightIcon && !hasArrow && borderlessVariant;\n const rest = { ...restProps };\n\n const buttonWrapperClasses = classNames(\n buttonStyles['button-wrapper'],\n { [buttonStyles['button-wrapper--fluid']]: fluid || ellipsis },\n wrapperClassName\n );\n const buttonClasses = classNames(\n buttonStyles.button,\n {\n [buttonStyles['button--destructive']]: destructive,\n [buttonStyles['button--normal']]: !large,\n [buttonStyles['button--large']]: large,\n [buttonStyles['button--outline']]: outlineVariant,\n [buttonStyles['button--borderless']]: borderlessVariant,\n [buttonStyles['button--left-icon']]: leftIcon && !onlyIcon,\n [buttonStyles['button--right-icon']]: rightIcon && !onlyIcon,\n [buttonStyles['button--both-icons']]: bothIcons,\n [buttonStyles['button--only-icon']]: onlyIcon,\n [buttonStyles['button--arrow']]: hasArrow,\n [buttonStyles['button--on-dark']]: onDark,\n },\n className\n );\n const buttonTextClasses = classNames(\n buttonStyles['button__text'],\n {\n [buttonStyles['button__text--ellipsis']]: ellipsis,\n [buttonStyles['button__text--centered']]: fluid && textPosition === 'centered',\n },\n textClassName\n );\n const diagonalClasses = classNames(buttonStyles['diagonal'], {\n [buttonStyles['diagonal--on-dark']]: onDark,\n });\n\n useEffect(() => {\n checkOnlyIconAria(onlyIcon, ariaLabel, !isTest() && !isProd());\n }, []);\n\n const renderIcon = (iconElement: BaseIconElement | null, iconSize: number, iconClassName?: string): BaseIconElement | null => {\n return iconElement\n ? React.cloneElement(iconElement, {\n size: iconSize,\n color: iconElement?.props.color && !disabled ? iconElement.props.color : iconColor,\n isHovered: !disabled && isHovered,\n className: iconClassName,\n })\n : null;\n };\n\n const renderButtonContent = (): JSX.Element => {\n return (\n <span className={buttonTextClasses} ref={buttonContentRef}>\n {disabled && borderlessVariant && (\n <span className={diagonalClasses}>\n <span className={buttonStyles['diagonal__line']} />\n </span>\n )}\n <span>{onlyIcon ? ariaLabel : restChildren}</span>\n </span>\n );\n };\n\n const renderbuttonContentWrapper = (): JSX.Element => (\n <span className={buttonClasses}>\n {renderIcon(leftIcon, getLargeIconSize(large, mobile), !onlyIcon ? buttonStyles['button__left-icon'] : undefined)}\n {renderButtonContent()}\n {hasArrow\n ? renderIcon(\n <Icon svgIcon={ArrowRight} />,\n getLargeIconSize(large, mobile),\n classNames(buttonStyles['button__arrow'], { [buttonStyles['button__arrow--both-icons']]: bothIcons })\n )\n : renderIcon(rightIcon, getLargeIconSize(large, mobile), buttonStyles['button__right-icon'])}\n {hasUURightArrow && (\n <span style={{ color: iconColor }} className={buttonStyles['button__right-unicode-arrow']} aria-hidden>\n {' →'}\n </span>\n )}\n </span>\n );\n\n return (\n <>\n {htmlMarkup === 'button' && (\n <button\n id={id}\n onBlur={onBlur}\n onClick={onClick}\n disabled={disabled}\n data-testid={testId}\n data-analyticsid={AnalyticsId.Button}\n className={buttonWrapperClasses}\n ref={hoverRef as React.ForwardedRef<HTMLButtonElement>}\n tabIndex={tabIndex}\n type={type}\n {...rest}\n >\n {renderbuttonContentWrapper()}\n </button>\n )}\n {htmlMarkup === 'a' && (\n <a\n id={id}\n onBlur={onBlur}\n onClick={onClick}\n data-testid={testId}\n data-analyticsid={AnalyticsId.Button}\n className={buttonWrapperClasses}\n href={href}\n target={target}\n rel={target === '_blank' ? 'noopener noreferrer' : props.rel}\n ref={hoverRef as React.ForwardedRef<HTMLAnchorElement>}\n tabIndex={tabIndex}\n {...restProps}\n >\n {renderbuttonContentWrapper()}\n </a>\n )}\n </>\n );\n});\n\nexport default Button;\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Button.js","sources":["../src/components/Button/Button.tsx"],"sourcesContent":["import React, { AriaAttributes, useEffect, useRef } from 'react';\n\nimport classNames from 'classnames';\n\nimport Icon, { IconSize } from './../Icon';\nimport { HTMLButtonProps, HTMLAnchorProps, AnalyticsId } from '../../constants';\nimport { useBreakpoint } from '../../hooks/useBreakpoint';\nimport { useHover } from '../../hooks/useHover';\nimport { BaseIconElement, useIcons } from '../../hooks/useIcons';\nimport { getColor } from '../../theme/currys/color';\nimport { breakpoints } from '../../theme/grid';\nimport { isTest, isProd } from '../../utils/environment';\nimport ArrowRight from '../Icons/ArrowRight';\n\nimport buttonStyles from './styles.module.scss';\n\nexport type ButtonConcept = 'normal' | 'destructive';\nexport type ButtonVariant = 'fill' | 'outline' | 'borderless';\nexport type ButtonSize = 'medium' | 'large';\nexport type ButtonOnColor = 'onlight' | 'ondark';\nexport type ButtonTags = 'button' | 'a';\nexport type ButtonArrows = 'icon' | 'accessibility-character';\nexport type ButtonTextPosition = 'left' | 'centered';\n\nexport interface ButtonProps extends HTMLButtonProps, HTMLAnchorProps, AriaAttributes {\n /** Sets the aria-label of the button, use when the button only includes an icon */\n ariaLabel?: string;\n /** Gives a unique id to the button */\n id?: string;\n /** Sets the content of the button. */\n children: React.ReactNode;\n /** Adds custom classes to the wrapper element. */\n wrapperClassName?: string;\n /** Adds custom classes to the element. */\n className?: string;\n /** Enables an arrow icon to the right inside the button (Not available in borderless variant) */\n arrow?: ButtonArrows;\n /** Changes the intent of the button. Mostly changes the color profile. */\n concept?: ButtonConcept;\n /** Disables text wrapping and enables ellipsis. */\n ellipsis?: boolean;\n /** Makes the button scale to full width of its parent element. */\n fluid?: boolean;\n /** Changes the underlying element of the button. */\n htmlMarkup?: ButtonTags;\n /** Changes the button colors for different backgrounds. */\n onColor?: ButtonOnColor;\n /** Function that is called when the Button loses focus */\n onBlur?: () => void;\n /** Function that is called when clicked */\n onClick?: (e?: React.MouseEvent<HTMLElement, MouseEvent> | React.FormEvent<{}> | React.KeyboardEvent<HTMLUListElement> | null) => void;\n /** Changes the button colors for different backgrounds. (Large not available in borderless variant) */\n size?: ButtonSize;\n /** Changes the visual representation of the button. */\n variant?: ButtonVariant;\n /** Specifies the focus order relative to the other buttons or controls on the page */\n tabIndex?: number;\n /** Sets the data-testid attribute. */\n testId?: string;\n /** Adds custom classes to the text */\n textClassName?: string;\n /** Sets the position of the text in the button - only applies when button is fluid */\n textPosition?: ButtonTextPosition;\n /** Button type. Default: button */\n type?: React.ButtonHTMLAttributes<HTMLButtonElement>['type'];\n}\n\nconst getIconColor = (\n fill: boolean,\n borderless: boolean,\n disabled: boolean,\n concept: ButtonConcept,\n ondark: boolean,\n mobile: boolean\n): string => {\n if (mobile && disabled) {\n return !ondark || fill ? getColor('neutral', !borderless ? 700 : 500) : getColor('white');\n }\n if (disabled) {\n return !ondark || fill ? getColor('neutral', 500) : `${getColor('white')}b3`;\n }\n if ((fill && !ondark) || (!fill && ondark)) {\n return 'white';\n }\n\n return concept === 'normal' ? getColor('blueberry', 600) : getColor('cherry', 500);\n};\nconst getLargeIconSize = (large: boolean, mobile: boolean): IconSize => {\n if (mobile && large) return IconSize.Small;\n if (large) return IconSize.Medium;\n return IconSize.XSmall;\n};\n\nconst checkOnlyIconAria = (onlyIcon: boolean, ariaLabel: string | undefined, devEnv: boolean): void => {\n if (devEnv && onlyIcon && (ariaLabel === undefined || ariaLabel === '')) {\n throw new Error('Fyll inn ariaLabel prop på Button uten tekst for å opprettholde UU krav');\n }\n};\n\nconst Button = React.forwardRef(function ButtonForwardedRef(\n props: ButtonProps,\n ref: React.ForwardedRef<HTMLButtonElement | HTMLAnchorElement>\n) {\n const {\n ariaLabel,\n id,\n children,\n wrapperClassName,\n className,\n arrow,\n concept = 'normal',\n disabled = false,\n ellipsis = false,\n fluid = false,\n htmlMarkup = 'button',\n onColor = 'onlight',\n onBlur,\n onClick,\n size = 'medium',\n variant = 'fill',\n href,\n tabIndex,\n testId,\n target,\n type = 'button',\n textClassName,\n textPosition = 'left',\n ...restProps\n } = props;\n\n const [leftIcon, rightIcon, restChildren] = useIcons(React.Children.toArray(children));\n const { hoverRef, isHovered } =\n htmlMarkup === 'button'\n ? useHover<HTMLButtonElement>(ref as React.RefObject<HTMLButtonElement>)\n : useHover<HTMLAnchorElement>(ref as React.RefObject<HTMLAnchorElement>);\n const buttonContentRef = useRef<HTMLDivElement>(null);\n const onlyIcon = !!(leftIcon || rightIcon) && !restChildren;\n const bothIcons = leftIcon && (rightIcon || arrow) && !onlyIcon;\n const onDark = onColor === 'ondark';\n const breakpoint = useBreakpoint();\n const mobile = breakpoint < breakpoints.md;\n const destructive = concept === 'destructive' && !disabled;\n const outlineVariant = variant === 'outline';\n const borderlessVariant = variant === 'borderless';\n const iconColor = getIconColor(variant === 'fill', borderlessVariant, disabled, concept, onDark, mobile);\n const hasArrow = arrow === 'icon' && !borderlessVariant;\n const large = size === 'large' && !destructive && !borderlessVariant;\n const hasUURightArrow = arrow === 'accessibility-character' && !fluid && !leftIcon && !rightIcon && !hasArrow && borderlessVariant;\n const rest = { ...restProps };\n\n const buttonWrapperClasses = classNames(\n buttonStyles['button-wrapper'],\n { [buttonStyles['button-wrapper--fluid']]: fluid || ellipsis },\n wrapperClassName\n );\n const buttonClasses = classNames(\n buttonStyles.button,\n {\n [buttonStyles['button--destructive']]: destructive,\n [buttonStyles['button--normal']]: !large,\n [buttonStyles['button--large']]: large,\n [buttonStyles['button--outline']]: outlineVariant,\n [buttonStyles['button--borderless']]: borderlessVariant,\n [buttonStyles['button--left-icon']]: leftIcon && !onlyIcon,\n [buttonStyles['button--right-icon']]: rightIcon && !onlyIcon,\n [buttonStyles['button--both-icons']]: bothIcons,\n [buttonStyles['button--only-icon']]: onlyIcon,\n [buttonStyles['button--arrow']]: hasArrow,\n [buttonStyles['button--on-dark']]: onDark,\n },\n className\n );\n const buttonTextClasses = classNames(\n buttonStyles['button__text'],\n {\n [buttonStyles['button__text--ellipsis']]: ellipsis,\n [buttonStyles['button__text--centered']]: fluid && textPosition === 'centered',\n },\n textClassName\n );\n const diagonalClasses = classNames(buttonStyles['diagonal'], {\n [buttonStyles['diagonal--on-dark']]: onDark,\n });\n\n useEffect(() => {\n checkOnlyIconAria(onlyIcon, ariaLabel, !isTest() && !isProd());\n }, []);\n\n const renderIcon = (iconElement: BaseIconElement | null, iconSize: number, iconClassName?: string): BaseIconElement | null => {\n return iconElement\n ? React.cloneElement(iconElement, {\n size: iconSize,\n color: iconElement?.props.color && !disabled ? iconElement.props.color : iconColor,\n isHovered: iconElement.props.isHovered === undefined ? !disabled && isHovered : iconElement.props.isHovered,\n className: iconClassName,\n })\n : null;\n };\n\n const renderButtonContent = (): JSX.Element => {\n return (\n <span className={buttonTextClasses} ref={buttonContentRef}>\n {disabled && borderlessVariant && (\n <span className={diagonalClasses}>\n <span className={buttonStyles['diagonal__line']} />\n </span>\n )}\n <span>{onlyIcon ? ariaLabel : restChildren}</span>\n </span>\n );\n };\n\n const renderbuttonContentWrapper = (): JSX.Element => (\n <span className={buttonClasses}>\n {renderIcon(leftIcon, getLargeIconSize(large, mobile), !onlyIcon ? buttonStyles['button__left-icon'] : undefined)}\n {renderButtonContent()}\n {hasArrow\n ? renderIcon(\n <Icon svgIcon={ArrowRight} />,\n getLargeIconSize(large, mobile),\n classNames(buttonStyles['button__arrow'], { [buttonStyles['button__arrow--both-icons']]: bothIcons })\n )\n : renderIcon(rightIcon, getLargeIconSize(large, mobile), buttonStyles['button__right-icon'])}\n {hasUURightArrow && (\n <span style={{ color: iconColor }} className={buttonStyles['button__right-unicode-arrow']} aria-hidden>\n {' →'}\n </span>\n )}\n </span>\n );\n\n return (\n <>\n {htmlMarkup === 'button' && (\n <button\n id={id}\n onBlur={onBlur}\n onClick={onClick}\n disabled={disabled}\n data-testid={testId}\n data-analyticsid={AnalyticsId.Button}\n className={buttonWrapperClasses}\n ref={hoverRef as React.ForwardedRef<HTMLButtonElement>}\n tabIndex={tabIndex}\n type={type}\n {...rest}\n >\n {renderbuttonContentWrapper()}\n </button>\n )}\n {htmlMarkup === 'a' && (\n <a\n id={id}\n onBlur={onBlur}\n onClick={onClick}\n data-testid={testId}\n data-analyticsid={AnalyticsId.Button}\n className={buttonWrapperClasses}\n href={href}\n target={target}\n rel={target === '_blank' ? 'noopener noreferrer' : props.rel}\n ref={hoverRef as React.ForwardedRef<HTMLAnchorElement>}\n tabIndex={tabIndex}\n {...restProps}\n >\n {renderbuttonContentWrapper()}\n </a>\n )}\n </>\n );\n});\n\nexport default Button;\n"],"names":[],"mappings":"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"}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
## [10.0.3](https://github.com/helsenorge/designsystem/branchCompare?baseVersion=GTv10.0.2&targetVersion=GTv10.0.3) (2025-01-30)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **datepicker:** locale setter tekst språk igjen ([921efcb](https://github.com/helsenorge/designsystem/commit/921efcb9040a2d790e965a009b28b3b4b3593a9b)), closes [#343367](https://github.com/helsenorge/designsystem/issues/343367)
|
|
7
|
+
|
|
8
|
+
## [10.0.2](https://github.com/helsenorge/designsystem/branchCompare?baseVersion=GTv10.0.1&targetVersion=GTv10.0.2) (2025-01-29)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* hvis icon har hover prop skal denne ikke overstyres ([f4956aa](https://github.com/helsenorge/designsystem/commit/f4956aacf26d462b2ffccc24fbce5b0946bd6de4)), closes [#336117](https://github.com/helsenorge/designsystem/issues/336117)
|
|
14
|
+
* **listheader:** title margin resettes riktig ([1b50bc0](https://github.com/helsenorge/designsystem/commit/1b50bc0e3229b2d351b2df17b79798dfd95a9fb8)), closes [#343414](https://github.com/helsenorge/designsystem/issues/343414)
|
|
15
|
+
|
|
16
|
+
## [10.0.1](https://github.com/helsenorge/designsystem/branchCompare?baseVersion=GTv10.0.0&targetVersion=GTv10.0.1) (2025-01-28)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Bug Fixes
|
|
20
|
+
|
|
21
|
+
* feil letterspacing for title5 ([f1391bd](https://github.com/helsenorge/designsystem/commit/f1391bd18a30b8b2da737c6687e55b61b752a1fa)), closes [#342902](https://github.com/helsenorge/designsystem/issues/342902)
|
|
22
|
+
|
|
1
23
|
## [10.0.0](https://github.com/helsenorge/designsystem/branchCompare?baseVersion=GTv9.7.0&targetVersion=GTv10.0.0) (2025-01-27)
|
|
2
24
|
|
|
3
25
|
|
package/Expander.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useRef } from "react";
|
|
3
3
|
import classNames from "classnames";
|
|
4
|
-
import {
|
|
4
|
+
import { AnalyticsId, IconSize } from "./constants.js";
|
|
5
5
|
import { useExpand } from "./hooks/useExpand.js";
|
|
6
6
|
import { useHover } from "./hooks/useHover.js";
|
|
7
7
|
import { useSize } from "./hooks/useSize.js";
|
|
@@ -30,7 +30,7 @@ const Expander = (props) => {
|
|
|
30
30
|
testId,
|
|
31
31
|
onExpand,
|
|
32
32
|
renderChildrenWhenClosed = false,
|
|
33
|
-
zIndex
|
|
33
|
+
zIndex
|
|
34
34
|
} = props;
|
|
35
35
|
const [isExpanded, setIsExpanded] = useExpand(expanded, onExpand);
|
|
36
36
|
const expanderRef = useRef(null);
|
package/Expander.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Expander.js","sources":["../src/components/Expander/Expander.tsx"],"sourcesContent":["import React, { useRef } from 'react';\n\nimport classNames from 'classnames';\n\nimport { AnalyticsId
|
|
1
|
+
{"version":3,"file":"Expander.js","sources":["../src/components/Expander/Expander.tsx"],"sourcesContent":["import React, { useRef } from 'react';\n\nimport classNames from 'classnames';\n\nimport { AnalyticsId } from '../../constants';\nimport { useExpand } from '../../hooks/useExpand';\nimport { useHover } from '../../hooks/useHover';\nimport { useSize } from '../../hooks/useSize';\nimport { PaletteNames } from '../../theme/palette';\nimport Button from '../Button';\nimport Icon, { IconSize, SvgIcon } from '../Icon';\nimport ChevronDown from '../Icons/ChevronDown';\nimport ChevronUp from '../Icons/ChevronUp';\nimport { IconName } from '../Icons/IconNames';\nimport LazyIcon from '../LazyIcon';\n\nimport styles from './styles.module.scss';\n\nexport enum ExpanderSize {\n small = 'small',\n large = 'large',\n}\n\nexport type ExpanderColors = Extract<PaletteNames, 'banana' | 'blueberry' | 'cherry' | 'kiwi' | 'neutral' | 'plum' | 'white'>;\n\nexport interface ExpanderProps {\n /** Sets the trigger title */\n title: string;\n /** Sets the expanded content */\n children?: React.ReactNode;\n /** Sets classnames on the content area */\n contentClassNames?: string;\n /** Sets the size of the expander. Default: ExpanderSize.small */\n size?: ExpanderSize;\n /** Sets the background of the expander. Requires size=ExpanderSize.large. */\n color?: ExpanderColors;\n /** Adds an icon to the expander trigger. Requires size=ExpanderSize.large. */\n svgIcon?: SvgIcon | IconName;\n /** Opens or closes the expander */\n expanded?: boolean;\n /** Removes border to the left of the content. Requires size=ExpanderSize.small. */\n noNestedLine?: boolean;\n /** Stick expander trigger to top of screen while scrolling down */\n sticky?: boolean;\n /** Called when expander is open/closed. */\n onExpand?: (isExpanded: boolean) => void;\n /** Whether to render children when closed (in which case they are hidden with CSS). Default: false */\n renderChildrenWhenClosed?: boolean;\n /** Sets the data-testid attribute on the expander button. */\n testId?: string;\n /** Overrides the default z-index of the expander header */\n zIndex?: number;\n}\n\nconst Expander: React.FC<ExpanderProps> = props => {\n const {\n title,\n children,\n size = ExpanderSize.small,\n color,\n contentClassNames,\n svgIcon: icon,\n expanded = false,\n noNestedLine = false,\n sticky = false,\n testId,\n onExpand,\n renderChildrenWhenClosed = false,\n zIndex,\n } = props;\n const [isExpanded, setIsExpanded] = useExpand(expanded, onExpand);\n const expanderRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const { isHovered } = useHover(triggerRef);\n const contentSize = useSize(expanderRef);\n const triggerSize = useSize(triggerRef);\n\n const isSticky = sticky && isExpanded;\n\n const renderChevron = (align: 'left' | 'right'): React.ReactNode => (\n <span className={classNames(styles['expander__icon'], styles[`expander__icon--${align}`])}>\n <Icon svgIcon={isExpanded ? ChevronUp : ChevronDown} size={IconSize.XSmall} isHovered={isHovered} />\n </span>\n );\n\n const triggerClassName = classNames(\n styles['expander__trigger'],\n size === ExpanderSize.large && styles[`expander__trigger--${size}`],\n size === ExpanderSize.large && styles[`expander__trigger--${color || 'neutral'}`],\n size === ExpanderSize.large && icon && styles['expander__trigger--icon'],\n isExpanded && styles['expander__trigger--expanded'],\n isSticky && styles['expander__trigger--sticky']\n );\n\n const renderTrigger = (): React.ReactNode => (\n <button\n type=\"button\"\n className={triggerClassName}\n style={{\n zIndex: isHovered || isSticky ? zIndex : undefined,\n width: isSticky && contentSize?.width ? `${contentSize.width}px` : undefined,\n }}\n aria-expanded={isExpanded}\n ref={triggerRef}\n onClick={(): void => setIsExpanded(!isExpanded)}\n data-testid={testId}\n data-analyticsid={AnalyticsId.Expander}\n >\n {size === ExpanderSize.small && renderChevron('left')}\n {icon && (\n <span className={classNames(styles['expander__icon'], styles['expander__icon--left'])}>\n {typeof icon === 'string' ? (\n <LazyIcon iconName={icon} size={IconSize.XSmall} isHovered={isHovered} />\n ) : (\n <Icon svgIcon={icon} size={IconSize.XSmall} isHovered={isHovered} />\n )}\n </span>\n )}\n {title}\n {size === ExpanderSize.large && renderChevron('right')}\n </button>\n );\n\n const buttonClassName = classNames(styles['expander__button'], isExpanded && styles['expander__button--expanded']);\n\n const renderButton = (): React.ReactNode => (\n <div\n style={{\n width: isSticky && triggerSize?.width ? `${triggerSize?.width}px` : undefined,\n height: isSticky && triggerSize?.height ? `${triggerSize?.height}px` : undefined,\n }}\n className={classNames({\n [styles['expander__button-container--sticky']]: isSticky,\n })}\n >\n <Button\n variant=\"borderless\"\n textClassName={styles['expander__button__text']}\n className={buttonClassName}\n aria-expanded={isExpanded}\n ref={triggerRef}\n onClick={(): void => setIsExpanded(!isExpanded)}\n testId={testId}\n data-analyticsid={AnalyticsId.Expander}\n >\n <Icon svgIcon={isExpanded ? ChevronUp : ChevronDown} size={IconSize.XSmall} />\n {title}\n </Button>\n </div>\n );\n\n const renderContent = (): React.ReactNode => {\n if (!renderChildrenWhenClosed && !isExpanded) {\n return null;\n }\n\n const contentClassName = classNames(\n styles['expander__content'],\n styles[`expander__content--${size}`],\n size === ExpanderSize.large && styles[`expander__content--${color || 'neutral'}`],\n size === ExpanderSize.large && icon && styles['expander__content--icon'],\n isExpanded && styles['expander__content--expanded'],\n size === ExpanderSize.small && !noNestedLine && styles['expander__content--nested-line'],\n { [styles['expander__content--sticky']]: isSticky },\n contentClassNames\n );\n\n return <div className={contentClassName}>{children}</div>;\n };\n\n return (\n <div className={styles['expander']} ref={expanderRef}>\n {size === ExpanderSize.large ? renderTrigger() : renderButton()}\n {renderContent()}\n </div>\n );\n};\n\nexport default Expander;\n"],"names":["ExpanderSize"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useRef,
|
|
2
|
+
import { useRef, useLayoutEffect } from "react";
|
|
3
3
|
import classNames from "classnames";
|
|
4
4
|
import { useHover } from "../../hooks/useHover.js";
|
|
5
5
|
import { usePseudoClasses } from "../../hooks/usePseudoClasses.js";
|
|
@@ -73,16 +73,22 @@ const StickyNote = (props) => {
|
|
|
73
73
|
}
|
|
74
74
|
(_a = textareaRef.current) == null ? void 0 : _a.focus();
|
|
75
75
|
};
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
const resizeTextarea = () => {
|
|
77
|
+
const textarea = textareaRef.current;
|
|
78
|
+
if (!textarea) return;
|
|
79
|
+
resizeTarget(textarea);
|
|
80
|
+
};
|
|
81
|
+
const resizeTarget = (target) => {
|
|
80
82
|
target.style.height = "inherit";
|
|
81
83
|
target.style.height = `${target.scrollHeight}px`;
|
|
82
84
|
};
|
|
85
|
+
useLayoutEffect(() => {
|
|
86
|
+
resizeTextarea();
|
|
87
|
+
setTimeout(() => resizeTextarea(), 1e3);
|
|
88
|
+
}, []);
|
|
83
89
|
const handleChange = (e) => {
|
|
84
90
|
const textarea = e.target;
|
|
85
|
-
|
|
91
|
+
resizeTarget(textarea);
|
|
86
92
|
textareaProps.onChange && textareaProps.onChange(e);
|
|
87
93
|
};
|
|
88
94
|
return /* @__PURE__ */ jsxs("div", { children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/components/StickyNote/Triangle.tsx","../../../src/components/StickyNote/StickyNote.tsx"],"sourcesContent":["interface TriangleProps {\n type: 'default' | 'active' | 'error';\n}\n\nexport interface Palette {\n border: string;\n background: string;\n}\n\nconst Triangle: React.FC<TriangleProps> = ({ type }) => {\n const palette = ((): Palette => {\n switch (type) {\n case 'active':\n return {\n border: '#C59302',\n background: '#F5E080',\n };\n case 'error':\n return {\n border: '#C83521',\n background: '#EEC0A5',\n };\n default:\n return {\n border: '#F5E080',\n background: '#F5E080',\n };\n }\n })();\n return (\n <svg width=\"22\" height=\"22\" viewBox=\"0 0 22 22\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <mask id=\"path-1-inside-1_1_44\" fill=\"white\">\n <path d=\"M22 0L1.80043e-06 22L2.83099e-06 -8.97354e-07L22 0Z\" />\n </mask>\n <path d=\"M22 0L1.80043e-06 22L2.83099e-06 -8.97354e-07L22 0Z\" fill={palette.background} />\n <path\n d=\"M22 0L22.7071 0.707107L24.4142 -1L22 -1L22 0ZM1.80043e-06 22L-0.999998 22L-0.999998 24.4142L0.707109 22.7071L1.80043e-06 22ZM2.83099e-06 -8.97354e-07L2.87783e-06 -1L-0.999997 -1L-0.999997 -9.38143e-07L2.83099e-06 -8.97354e-07ZM21.2929 -0.707107L-0.707105 21.2929L0.707109 22.7071L22.7071 0.707107L21.2929 -0.707107ZM1 22L1 -8.56565e-07L-0.999997 -9.38143e-07L-0.999998 22L1 22ZM2.78414e-06 0.999999L22 1L22 -1L2.87783e-06 -1L2.78414e-06 0.999999Z\"\n fill={palette.border}\n mask=\"url(#path-1-inside-1_1_44)\"\n />\n </svg>\n );\n};\n\nexport default Triangle;\n","import React, {
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/components/StickyNote/Triangle.tsx","../../../src/components/StickyNote/StickyNote.tsx"],"sourcesContent":["interface TriangleProps {\n type: 'default' | 'active' | 'error';\n}\n\nexport interface Palette {\n border: string;\n background: string;\n}\n\nconst Triangle: React.FC<TriangleProps> = ({ type }) => {\n const palette = ((): Palette => {\n switch (type) {\n case 'active':\n return {\n border: '#C59302',\n background: '#F5E080',\n };\n case 'error':\n return {\n border: '#C83521',\n background: '#EEC0A5',\n };\n default:\n return {\n border: '#F5E080',\n background: '#F5E080',\n };\n }\n })();\n return (\n <svg width=\"22\" height=\"22\" viewBox=\"0 0 22 22\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <mask id=\"path-1-inside-1_1_44\" fill=\"white\">\n <path d=\"M22 0L1.80043e-06 22L2.83099e-06 -8.97354e-07L22 0Z\" />\n </mask>\n <path d=\"M22 0L1.80043e-06 22L2.83099e-06 -8.97354e-07L22 0Z\" fill={palette.background} />\n <path\n d=\"M22 0L22.7071 0.707107L24.4142 -1L22 -1L22 0ZM1.80043e-06 22L-0.999998 22L-0.999998 24.4142L0.707109 22.7071L1.80043e-06 22ZM2.83099e-06 -8.97354e-07L2.87783e-06 -1L-0.999997 -1L-0.999997 -9.38143e-07L2.83099e-06 -8.97354e-07ZM21.2929 -0.707107L-0.707105 21.2929L0.707109 22.7071L22.7071 0.707107L21.2929 -0.707107ZM1 22L1 -8.56565e-07L-0.999997 -9.38143e-07L-0.999998 22L1 22ZM2.78414e-06 0.999999L22 1L22 -1L2.87783e-06 -1L2.78414e-06 0.999999Z\"\n fill={palette.border}\n mask=\"url(#path-1-inside-1_1_44)\"\n />\n </svg>\n );\n};\n\nexport default Triangle;\n","import React, { useLayoutEffect, useRef } from 'react';\n\nimport classNames from 'classnames';\n\nimport { useHover } from '../../hooks/useHover';\nimport { usePseudoClasses } from '../../hooks/usePseudoClasses';\nimport Icon, { IconSize } from '../Icon';\nimport Triangle from './Triangle';\nimport { useUuid } from '../../hooks/useUuid';\nimport { getAriaDescribedBy } from '../../utils/accessibility';\nimport X from '../Icons/X';\n\nimport styles from './styles.module.scss';\n\nexport interface StickyNoteProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {\n /** Aria label for the delete/close button */\n arialabelXButton: string;\n /** Activates the error styling */\n error?: boolean;\n /** Error text to show below the note */\n errorText?: string;\n /** Error text id */\n errorTextId?: string;\n /** Text shown under the textarea */\n footerText?: string;\n /** Function run when clicking the delete/close button */\n onXButtonClick?: () => void;\n /** Function run if user clicks the component while it is disabled */\n onClickWhileDisabled?: () => void;\n /** Sets the data-testid attribute. */\n testId?: string;\n /** Timestamp shown over the textarea */\n timestamp: string;\n /** Classname for the outer wrapper */\n wrapperClassName?: string;\n}\n\nconst StickyNote: React.FC<StickyNoteProps> = (props: StickyNoteProps) => {\n const {\n wrapperClassName,\n timestamp,\n onXButtonClick,\n arialabelXButton,\n footerText,\n error,\n errorText,\n errorTextId,\n onClickWhileDisabled,\n testId,\n ...textareaProps\n } = props;\n const errorTextUuid = useUuid(errorTextId);\n const stickynoteRef = useRef<HTMLDivElement>(null);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const { isFocused: isTextareaFocused } = usePseudoClasses<HTMLTextAreaElement>(textareaRef);\n const { isHovered } = useHover<HTMLDivElement>(stickynoteRef);\n const triangleType = error ? 'error' : isTextareaFocused ? 'active' : 'default';\n\n const handleWrapperClick = (event: React.MouseEvent<HTMLDivElement> | React.KeyboardEvent<HTMLDivElement>): void => {\n if ((event.target as HTMLElement).closest('button')) {\n return;\n }\n if (textareaProps.disabled) {\n onClickWhileDisabled && onClickWhileDisabled();\n return;\n }\n textareaRef.current?.focus();\n };\n\n const resizeTextarea = (): void => {\n const textarea = textareaRef.current;\n if (!textarea) return;\n resizeTarget(textarea);\n };\n\n const resizeTarget = (target: HTMLTextAreaElement): void => {\n // Reset field height\n target.style.height = 'inherit';\n // Set new height\n target.style.height = `${target.scrollHeight}px`;\n };\n\n useLayoutEffect(() => {\n resizeTextarea();\n // Must run after the shadow DOM has been set up to work on microweb\n setTimeout(() => resizeTextarea(), 1000);\n }, []);\n\n const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>): void => {\n const textarea = e.target as HTMLTextAreaElement;\n resizeTarget(textarea);\n textareaProps.onChange && textareaProps.onChange(e);\n };\n\n return (\n <div>\n <div\n data-testid={testId}\n ref={stickynoteRef}\n className={classNames(styles['sticky-note'], wrapperClassName, {\n [styles['sticky-note--focused']]: isTextareaFocused,\n [styles['sticky-note--hovered']]: isHovered && !isTextareaFocused && !textareaProps.disabled,\n [styles['sticky-note--error']]: error,\n })}\n onClick={handleWrapperClick}\n role=\"textbox\"\n tabIndex={-1}\n onKeyDown={e => {\n if (e.key === 'Enter' || e.key === ' ') {\n handleWrapperClick(e as React.KeyboardEvent<HTMLDivElement>);\n }\n }}\n >\n <div className={classNames(styles['sticky-note__header'])}>\n {timestamp && <span className={styles['sticky-note__header__timestamp']}>{timestamp}</span>}\n </div>\n <textarea\n ref={textareaRef}\n data-testid={`${testId}-textarea`}\n className={classNames(styles['sticky-note__textarea'], textareaProps.className)}\n {...textareaProps}\n onChange={handleChange}\n aria-describedby={getAriaDescribedBy(props, errorTextUuid)}\n />\n <button\n onClick={onXButtonClick}\n aria-label={arialabelXButton}\n data-testid=\"closeButton\"\n className={classNames(styles['sticky-note__x-button'])}\n type=\"button\"\n >\n <Icon svgIcon={X} color=\"black\" size={IconSize.XXSmall} />\n </button>\n <div className={classNames(styles['sticky-note__footer'])}>{footerText && <span>{footerText}</span>}</div>\n <div className={classNames(styles['sticky-note__triangle'])}>\n <Triangle type={triangleType} />\n </div>\n </div>\n {error && (\n <p className={styles['sticky-note__error-text']} id={errorTextId}>\n {errorText}\n </p>\n )}\n </div>\n );\n};\n\nexport default StickyNote;\n"],"names":[],"mappings":"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"}
|
|
@@ -24,6 +24,8 @@ export interface TabsProps {
|
|
|
24
24
|
ariaLabelRightButton?: string;
|
|
25
25
|
/** Sets aria label on the "scroll to the left" button in TabList */
|
|
26
26
|
ariaLabelLeftButton?: string;
|
|
27
|
+
/** Overrides the default z-index of the tabs header */
|
|
28
|
+
zIndex?: number;
|
|
27
29
|
}
|
|
28
30
|
declare const TabsRoot: React.FC<TabsProps>;
|
|
29
31
|
type TabsComponent = typeof TabsRoot & {
|
package/components/Tabs/index.js
CHANGED
|
@@ -15,7 +15,8 @@ const TabsRoot = ({
|
|
|
15
15
|
sticky = true,
|
|
16
16
|
testId,
|
|
17
17
|
ariaLabelRightButton,
|
|
18
|
-
ariaLabelLeftButton
|
|
18
|
+
ariaLabelLeftButton,
|
|
19
|
+
zIndex
|
|
19
20
|
}) => {
|
|
20
21
|
const isControlled = activeTab !== void 0;
|
|
21
22
|
const [uncontrolledValue, setUncontrolledValue] = useState(0);
|
|
@@ -40,6 +41,9 @@ const TabsRoot = ({
|
|
|
40
41
|
className: classNames(styles["tab-list-wrapper"], {
|
|
41
42
|
[styles["tab-list-wrapper--sticky"]]: sticky
|
|
42
43
|
}),
|
|
44
|
+
style: {
|
|
45
|
+
zIndex
|
|
46
|
+
},
|
|
43
47
|
children: [
|
|
44
48
|
/* @__PURE__ */ jsx(
|
|
45
49
|
TabList,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/components/Tabs/Tabs.tsx"],"sourcesContent":["import React, { useState, useRef } from 'react';\n\nimport classNames from 'classnames';\n\nimport Tab from './Tab';\nimport TabList from './TabList';\nimport TabPanel from './TabPanel';\nimport designsystemlayout from '../../scss/layout.module.scss';\nimport { PaletteNames } from '../../theme/palette';\n\nimport styles from './styles.module.scss';\n\nexport type { TabProps } from './Tab';\nexport type TabsColors = Extract<PaletteNames, 'blueberry' | 'neutral' | 'white'>;\nexport type TabsOnColor = 'onblueberry' | 'onneutral' | 'onwhite';\n\nexport interface TabsProps {\n children?: React.ReactNode;\n /** Controlled state for Tabs component */\n activeTab?: number;\n /** Adds custom classes to the element. */\n className?: string;\n /** Sets the color of the tabs. Default: white */\n color?: TabsColors;\n /** Sets wether the component should use the container-breakout class. Default: true */\n containerBreakout?: boolean;\n /** Sets the background color of the tabs. Can only be used when the color is set to white. Default: onwhite */\n onColor?: TabsOnColor;\n /** Whether the tab list should be sticky */\n sticky?: boolean;\n /** Sets the data-testid attribute. */\n testId?: string;\n /** Sets aria label on the \"scroll to the right\" button in TabList */\n ariaLabelRightButton?: string;\n /** Sets aria label on the \"scroll to the left\" button in TabList */\n ariaLabelLeftButton?: string;\n}\n\nconst TabsRoot: React.FC<TabsProps> = ({\n activeTab,\n children,\n className,\n color = 'white',\n containerBreakout = true,\n onColor = 'onwhite',\n sticky = true,\n testId,\n ariaLabelRightButton,\n ariaLabelLeftButton,\n}) => {\n const isControlled = activeTab !== undefined;\n const [uncontrolledValue, setUncontrolledValue] = useState(0);\n const tabsRef = useRef<HTMLDivElement>(null);\n const tabPanelRef = useRef<HTMLDivElement>(null);\n const tabListRef = useRef<HTMLDivElement>(null);\n\n let onColorUsed: TabsOnColor = 'onwhite';\n if (color === 'white') {\n onColorUsed = onColor;\n }\n\n const onValueChange = (newValue: number): void => {\n if (!isControlled) {\n setUncontrolledValue(newValue);\n }\n };\n\n const activeTabIndex = isControlled ? activeTab : uncontrolledValue;\n\n return (\n <div className={classNames(className, containerBreakout && designsystemlayout['container-breakout'])} data-testid={testId}>\n <div\n ref={tabListRef}\n className={classNames(styles['tab-list-wrapper'], {\n [styles['tab-list-wrapper--sticky']]: sticky,\n })}\n >\n <TabList\n onTabListClick={(index: number) => onValueChange(index)}\n selectedTab={activeTabIndex}\n color={color}\n onColor={onColorUsed}\n ariaLabelLeftButton={ariaLabelLeftButton}\n ariaLabelRightButton={ariaLabelRightButton}\n >\n {children}\n </TabList>\n <div className={classNames(styles['panel-wrapper'], styles[`panel-wrapper--${color}`])}></div>\n </div>\n <div ref={tabsRef} style={{ marginTop: '-50px' }}>\n <TabPanel ref={tabPanelRef} color={color} isFirst={activeTabIndex == 0}>\n {React.Children.toArray(children)[activeTabIndex]}\n </TabPanel>\n </div>\n </div>\n );\n};\n\ntype TabsComponent = typeof TabsRoot & {\n Tab: typeof Tab;\n};\nconst Tabs = TabsRoot as TabsComponent;\nTabs.displayName = 'Tabs';\nTabs.Tab = Tab;\nTabs.Tab.displayName = 'Tabs.Tab';\n\nexport default Tabs;\n"],"names":[],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/components/Tabs/Tabs.tsx"],"sourcesContent":["import React, { useState, useRef } from 'react';\n\nimport classNames from 'classnames';\n\nimport Tab from './Tab';\nimport TabList from './TabList';\nimport TabPanel from './TabPanel';\nimport designsystemlayout from '../../scss/layout.module.scss';\nimport { PaletteNames } from '../../theme/palette';\n\nimport styles from './styles.module.scss';\n\nexport type { TabProps } from './Tab';\nexport type TabsColors = Extract<PaletteNames, 'blueberry' | 'neutral' | 'white'>;\nexport type TabsOnColor = 'onblueberry' | 'onneutral' | 'onwhite';\n\nexport interface TabsProps {\n children?: React.ReactNode;\n /** Controlled state for Tabs component */\n activeTab?: number;\n /** Adds custom classes to the element. */\n className?: string;\n /** Sets the color of the tabs. Default: white */\n color?: TabsColors;\n /** Sets wether the component should use the container-breakout class. Default: true */\n containerBreakout?: boolean;\n /** Sets the background color of the tabs. Can only be used when the color is set to white. Default: onwhite */\n onColor?: TabsOnColor;\n /** Whether the tab list should be sticky */\n sticky?: boolean;\n /** Sets the data-testid attribute. */\n testId?: string;\n /** Sets aria label on the \"scroll to the right\" button in TabList */\n ariaLabelRightButton?: string;\n /** Sets aria label on the \"scroll to the left\" button in TabList */\n ariaLabelLeftButton?: string;\n /** Overrides the default z-index of the tabs header */\n zIndex?: number;\n}\n\nconst TabsRoot: React.FC<TabsProps> = ({\n activeTab,\n children,\n className,\n color = 'white',\n containerBreakout = true,\n onColor = 'onwhite',\n sticky = true,\n testId,\n ariaLabelRightButton,\n ariaLabelLeftButton,\n zIndex,\n}) => {\n const isControlled = activeTab !== undefined;\n const [uncontrolledValue, setUncontrolledValue] = useState(0);\n const tabsRef = useRef<HTMLDivElement>(null);\n const tabPanelRef = useRef<HTMLDivElement>(null);\n const tabListRef = useRef<HTMLDivElement>(null);\n\n let onColorUsed: TabsOnColor = 'onwhite';\n if (color === 'white') {\n onColorUsed = onColor;\n }\n\n const onValueChange = (newValue: number): void => {\n if (!isControlled) {\n setUncontrolledValue(newValue);\n }\n };\n\n const activeTabIndex = isControlled ? activeTab : uncontrolledValue;\n\n return (\n <div className={classNames(className, containerBreakout && designsystemlayout['container-breakout'])} data-testid={testId}>\n <div\n ref={tabListRef}\n className={classNames(styles['tab-list-wrapper'], {\n [styles['tab-list-wrapper--sticky']]: sticky,\n })}\n style={{\n zIndex: zIndex,\n }}\n >\n <TabList\n onTabListClick={(index: number) => onValueChange(index)}\n selectedTab={activeTabIndex}\n color={color}\n onColor={onColorUsed}\n ariaLabelLeftButton={ariaLabelLeftButton}\n ariaLabelRightButton={ariaLabelRightButton}\n >\n {children}\n </TabList>\n <div className={classNames(styles['panel-wrapper'], styles[`panel-wrapper--${color}`])}></div>\n </div>\n <div ref={tabsRef} style={{ marginTop: '-50px' }}>\n <TabPanel ref={tabPanelRef} color={color} isFirst={activeTabIndex == 0}>\n {React.Children.toArray(children)[activeTabIndex]}\n </TabPanel>\n </div>\n </div>\n );\n};\n\ntype TabsComponent = typeof TabsRoot & {\n Tab: typeof Tab;\n};\nconst Tabs = TabsRoot as TabsComponent;\nTabs.displayName = 'Tabs';\nTabs.Tab = Tab;\nTabs.Tab.displayName = 'Tabs.Tab';\n\nexport default Tabs;\n"],"names":[],"mappings":";;;;;;;AAwCA,MAAM,WAAgC,CAAC;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,oBAAoB;AAAA,EACpB,UAAU;AAAA,EACV,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,eAAe,cAAc;AACnC,QAAM,CAAC,mBAAmB,oBAAoB,IAAI,SAAS,CAAC;AACtD,QAAA,UAAU,OAAuB,IAAI;AACrC,QAAA,cAAc,OAAuB,IAAI;AACzC,QAAA,aAAa,OAAuB,IAAI;AAE9C,MAAI,cAA2B;AAC/B,MAAI,UAAU,SAAS;AACP,kBAAA;AAAA,EAAA;AAGV,QAAA,gBAAgB,CAAC,aAA2B;AAChD,QAAI,CAAC,cAAc;AACjB,2BAAqB,QAAQ;AAAA,IAAA;AAAA,EAEjC;AAEM,QAAA,iBAAiB,eAAe,YAAY;AAGhD,SAAA,qBAAC,OAAI,EAAA,WAAW,WAAW,WAAW,qBAAqB,mBAAmB,oBAAoB,CAAC,GAAG,eAAa,QACjH,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAK;AAAA,QACL,WAAW,WAAW,OAAO,kBAAkB,GAAG;AAAA,UAChD,CAAC,OAAO,0BAA0B,CAAC,GAAG;AAAA,QAAA,CACvC;AAAA,QACD,OAAO;AAAA,UACL;AAAA,QACF;AAAA,QAEA,UAAA;AAAA,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,gBAAgB,CAAC,UAAkB,cAAc,KAAK;AAAA,cACtD,aAAa;AAAA,cACb;AAAA,cACA,SAAS;AAAA,cACT;AAAA,cACA;AAAA,cAEC;AAAA,YAAA;AAAA,UACH;AAAA,UACC,oBAAA,OAAA,EAAI,WAAW,WAAW,OAAO,eAAe,GAAG,OAAO,kBAAkB,KAAK,EAAE,CAAC,EAAG,CAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAC1F;AAAA,IACA,oBAAC,OAAI,EAAA,KAAK,SAAS,OAAO,EAAE,WAAW,QAAA,GACrC,UAAA,oBAAC,UAAS,EAAA,KAAK,aAAa,OAAc,SAAS,kBAAkB,GAClE,UAAM,MAAA,SAAS,QAAQ,QAAQ,EAAE,cAAc,EAClD,CAAA,EACF,CAAA;AAAA,EAAA,GACF;AAEJ;AAKA,MAAM,OAAO;AACb,KAAK,cAAc;AACnB,KAAK,MAAM;AACX,KAAK,IAAI,cAAc;"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
type OutsideEvents = keyof PickByValue<HTMLElementEventMap, MouseEvent | FocusEvent>;
|
|
2
2
|
/**
|
|
3
|
-
* Custom hook for klikk eller fokus utenfor et gitt element
|
|
4
|
-
* @param ref Sjekker om det klikkes utenfor dette elementet
|
|
5
|
-
* @param
|
|
3
|
+
* Custom hook for klikk eller fokus utenfor et gitt element (eller flere elementer)
|
|
4
|
+
* @param ref Sjekker om det klikkes utenfor dette elementet/elementene
|
|
5
|
+
* @param callback Callback-funksjon ved klikk utenfor elementet/elementene
|
|
6
6
|
* @param events Type eventer å lytte på. Default: mousedown
|
|
7
7
|
*/
|
|
8
|
-
export declare const useOutsideEvent: (ref: React.RefObject<HTMLElement
|
|
8
|
+
export declare const useOutsideEvent: (ref: React.RefObject<HTMLElement> | React.RefObject<HTMLElement>[], callback: (event: HTMLElementEventMap[OutsideEvents]) => void, events?: OutsideEvents[]) => void;
|
|
9
9
|
export {};
|
package/hooks/useOutsideEvent.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { useEffect } from "react";
|
|
2
|
-
const useOutsideEvent = (ref,
|
|
2
|
+
const useOutsideEvent = (ref, callback, events = ["mousedown"]) => {
|
|
3
|
+
const refArray = Array.isArray(ref) ? ref : [ref];
|
|
3
4
|
const handleOutsideEvent = (event) => {
|
|
4
|
-
if (
|
|
5
|
-
|
|
5
|
+
if (refArray.every((ref2) => ref2.current && !event.composedPath().includes(ref2.current))) {
|
|
6
|
+
callback(event);
|
|
6
7
|
}
|
|
7
8
|
};
|
|
8
9
|
useEffect(() => {
|
|
@@ -10,7 +11,7 @@ const useOutsideEvent = (ref, handleClick, events = ["mousedown"]) => {
|
|
|
10
11
|
return () => {
|
|
11
12
|
events.forEach((eventName) => document.removeEventListener(eventName, handleOutsideEvent));
|
|
12
13
|
};
|
|
13
|
-
}, [
|
|
14
|
+
}, [refArray, callback, events]);
|
|
14
15
|
};
|
|
15
16
|
export {
|
|
16
17
|
useOutsideEvent
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useOutsideEvent.js","sources":["../../src/hooks/useOutsideEvent.ts"],"sourcesContent":["import { useEffect } from 'react';\n\ntype OutsideEvents = keyof PickByValue<HTMLElementEventMap, MouseEvent | FocusEvent>;\n\n/**\n * Custom hook for klikk eller fokus utenfor et gitt element\n * @param ref Sjekker om det klikkes utenfor dette elementet\n * @param
|
|
1
|
+
{"version":3,"file":"useOutsideEvent.js","sources":["../../src/hooks/useOutsideEvent.ts"],"sourcesContent":["import { useEffect } from 'react';\n\ntype OutsideEvents = keyof PickByValue<HTMLElementEventMap, MouseEvent | FocusEvent>;\n\n/**\n * Custom hook for klikk eller fokus utenfor et gitt element (eller flere elementer)\n * @param ref Sjekker om det klikkes utenfor dette elementet/elementene\n * @param callback Callback-funksjon ved klikk utenfor elementet/elementene\n * @param events Type eventer å lytte på. Default: mousedown\n */\nexport const useOutsideEvent = (\n ref: React.RefObject<HTMLElement> | React.RefObject<HTMLElement>[],\n callback: (event: HTMLElementEventMap[OutsideEvents]) => void,\n events: OutsideEvents[] = ['mousedown']\n): void => {\n const refArray = Array.isArray(ref) ? ref : [ref];\n\n const handleOutsideEvent = (event: HTMLElementEventMap[OutsideEvents]): void => {\n if (refArray.every(ref => ref.current && !event.composedPath().includes(ref.current))) {\n callback(event);\n }\n };\n\n useEffect(() => {\n events.forEach(eventName => document.addEventListener(eventName, handleOutsideEvent));\n\n return (): void => {\n events.forEach(eventName => document.removeEventListener(eventName, handleOutsideEvent));\n };\n }, [refArray, callback, events]);\n};\n"],"names":["ref"],"mappings":";AAUO,MAAM,kBAAkB,CAC7B,KACA,UACA,SAA0B,CAAC,WAAW,MAC7B;AACT,QAAM,WAAW,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAC,GAAG;AAE1C,QAAA,qBAAqB,CAAC,UAAoD;AAC9E,QAAI,SAAS,MAAM,CAAAA,SAAOA,KAAI,WAAW,CAAC,MAAM,aAAA,EAAe,SAASA,KAAI,OAAO,CAAC,GAAG;AACrF,eAAS,KAAK;AAAA,IAAA;AAAA,EAElB;AAEA,YAAU,MAAM;AACd,WAAO,QAAQ,CAAa,cAAA,SAAS,iBAAiB,WAAW,kBAAkB,CAAC;AAEpF,WAAO,MAAY;AACjB,aAAO,QAAQ,CAAa,cAAA,SAAS,oBAAoB,WAAW,kBAAkB,CAAC;AAAA,IACzF;AAAA,EACC,GAAA,CAAC,UAAU,UAAU,MAAM,CAAC;AACjC;"}
|