@helsenorge/designsystem-react 10.5.0 → 10.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 +13 -0
- package/Trigger.js.map +1 -1
- package/components/Dropdown/index.js +9 -6
- package/components/Dropdown/index.js.map +1 -1
- package/components/PopMenu/index.js.map +1 -1
- package/components/PopMenu/styles.module.scss +8 -2
- package/components/Trigger/Trigger.d.ts +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
## [10.5.0](https://github.com/helsenorge/designsystem/branchCompare?baseVersion=GTv10.4.1&targetVersion=GTv10.5.0) (2025-03-06)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
- **dropdown:** mulig å sette minimumsbredde på dropdown
|
|
6
|
+
([c57f803](https://github.com/helsenorge/designsystem/commit/c57f8037c9da11ab6d7ffbfe6557a044a216ba39)), closes
|
|
7
|
+
[#346470](https://github.com/helsenorge/designsystem/issues/346470)
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **language:** eksporter LanguageContext
|
|
12
|
+
([e0e841a](https://github.com/helsenorge/designsystem/commit/e0e841a13237bbadfebf9b2098d873a00a5eda10))
|
|
13
|
+
|
|
1
14
|
## [10.4.1](https://github.com/helsenorge/designsystem/branchCompare?baseVersion=GTv10.4.0&targetVersion=GTv10.4.1) (2025-03-05)
|
|
2
15
|
|
|
3
16
|
### Bug Fixes
|
package/Trigger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Trigger.js","sources":["../src/components/Trigger/HelpSign.tsx","../src/components/Trigger/Trigger.tsx"],"sourcesContent":["import React from 'react';\n\nimport { getIcon, SvgPathProps } from '../Icon';\n\nconst HelpSign: React.FC<SvgPathProps> = ({ size, isHovered }: SvgPathProps): React.ReactElement => {\n const normal = (\n <path d=\"M18.854 19.678c0-2.268 1.701-4.74 5.126-4.74 3.358 0 5.172 2.222 5.172 4.536 0 1.793-.952 3.064-2.268 3.992l-.976.682c-.749.521-1.134 1.27-1.134 2.154 0 .047 0 .16.023.296h-2.269a46.85 46.85 0 0 0-.01-.139 8.554 8.554 0 0 1-.036-.724c0-1.36.522-2.471 1.84-3.424l1.042-.75c.75-.544 1.066-1.201 1.066-1.974 0-1.178-.793-2.29-2.45-2.29-1.679 0-2.563 1.293-2.563 2.585 0 .34.045.772.136 1.022l-2.564-.181a3.903 3.903 0 0 1-.135-1.044Zm3.176 10.186c0-.908.726-1.678 1.656-1.678.908 0 1.656.77 1.656 1.678 0 .907-.748 1.657-1.656 1.657-.93 0-1.656-.75-1.656-1.657Z\" />\n );\n\n const normalHover = (\n <path d=\"M18.854 18.178c0-2.268 1.701-4.74 5.126-4.74 3.358 0 5.172 2.223 5.172 4.536 0 1.793-.952 3.064-2.268 3.992l-.976.682c-.749.521-1.134 1.27-1.134 2.154 0 .047 0 .16.023.296h-2.269a46.85 46.85 0 0 0-.01-.139 8.554 8.554 0 0 1-.036-.724c0-1.36.522-2.471 1.838-3.424l1.044-.75c.75-.544 1.066-1.201 1.066-1.974 0-1.178-.793-2.29-2.45-2.29-1.679 0-2.563 1.293-2.563 2.585 0 .34.045.772.135 1.022l-2.563-.181a3.903 3.903 0 0 1-.135-1.044Zm3.176 11.686c0-.908.725-1.678 1.655-1.678.908 0 1.657.77 1.657 1.678 0 .907-.749 1.657-1.657 1.657-.93 0-1.655-.75-1.655-1.657Z\" />\n );\n\n const xSmall = (\n <path d=\"M23.98 14.937c-3.425 0-5.127 2.473-5.127 4.741 0 .363.047.726.137 1.044l2.563.182c-.09-.25-.136-.681-.136-1.022 0-1.292.885-2.586 2.563-2.586 1.658 0 2.45 1.112 2.45 2.291 0 .772-.317 1.43-1.065 1.974l-1.043.749c-1.317.953-1.84 2.065-1.84 3.425 0 .319.024.567.047.862h2.267c-.021-.135-.021-.25-.021-.295 0-.884.385-1.633 1.133-2.154l.976-.681c1.317-.93 2.27-2.2 2.27-3.993 0-2.314-1.816-4.537-5.174-4.537m-.294 13.248c-.93 0-1.656.773-1.656 1.678a1.65 1.65 0 0 0 1.656 1.657c.907 0 1.656-.748 1.656-1.657 0-.905-.749-1.678-1.656-1.678\" />\n );\n\n const xSmallHover = (\n <path d=\"M18.853 18.289c0-2.268 1.701-4.742 5.127-4.742 3.357 0 5.173 2.223 5.173 4.537 0 1.794-.953 3.065-2.27 3.994l-.976.681c-.747.52-1.133 1.27-1.133 2.154 0 .046 0 .16.022.295h-2.267a39.324 39.324 0 0 0-.01-.125 8.468 8.468 0 0 1-.037-.737c0-1.36.523-2.472 1.839-3.425l1.043-.75c.748-.543 1.065-1.201 1.065-1.973 0-1.18-.792-2.29-2.45-2.29-1.678 0-2.562 1.293-2.562 2.585 0 .341.045.772.135 1.022l-2.563-.183a3.914 3.914 0 0 1-.136-1.043Zm3.176 11.575c0-.907.726-1.679 1.656-1.679.908 0 1.657.772 1.657 1.68 0 .907-.749 1.656-1.657 1.656-.93 0-1.656-.749-1.656-1.657Z\" />\n );\n\n return getIcon({ size, isHovered, normal, normalHover, xSmall, xSmallHover });\n};\n\nexport default HelpSign;\n","import React from 'react';\n\nimport classNames from 'classnames';\n\nimport HelpSign from './HelpSign';\nimport { AnalyticsId, IconSize } from '../../constants';\nimport { useHover } from '../../hooks/useHover';\nimport { getColor } from '../../theme/currys';\nimport { getAriaLabelAttributes } from '../../utils/accessibility';\nimport { mergeRefs } from '../../utils/refs';\nimport Icon, { SvgIcon } from '../Icon';\n\nimport styles from './styles.module.scss';\n\nexport type TriggerTags = 'button' | 'span';\n\nexport type TriggerVariant = 'help'; // @todo Support variant='info' in later version\n\nexport type TriggerSize = 'medium' | 'large';\n\nexport type TriggerOnColor = 'onlight' | 'ondark';\n\nexport interface TriggerProps extends Pick<React.InputHTMLAttributes<HTMLButtonElement>, 'onClick' | 'aria-haspopup' | 'aria-controls'> {\n /**\n * Sets aria-label of the trigger. ariaLabel or ariaLabelledById MUST be set!\n */\n ariaLabel?: string;\n /**\n * Sets aria-labelledby of the trigger. ariaLabel or ariaLabelledById MUST be set!\n */\n ariaLabelledById?: string;\n /**\n * Controls the icon and color. Default: help.\n */\n variant?: TriggerVariant;\n /**\n * Changes the design based on the background the trigger is placed on. Default: onlight.\n */\n onColor?: TriggerOnColor;\n /**\n * Size of the trigger. Default: medium.\n */\n size?: TriggerSize;\n /**\n * Indicates that the trigger is in use.\n */\n selected?: boolean;\n /**\n * Indicates that the trigger is hovered. Used in combination with htmlMarkup=span to force visual hover state.\n */\n isHovered?: boolean;\n /**\n * Changes the underlying element of the trigger. If set to span, the trigger will be a non-interactive icon. Default: button\n */\n htmlMarkup?: TriggerTags;\n /**\n * Classname will be applied to the button element.\n */\n className?: string;\n /**\n * Optional test id.\n */\n testId?: string;\n}\n\nconst iconMap: Record<TriggerVariant, SvgIcon> = {\n help: HelpSign,\n //info: InfoSignStroke, // @todo Support variant='info' in later version\n};\n\nconst iconSizeMap: Record<TriggerSize, IconSize> = {\n medium: IconSize.XSmall,\n large: IconSize.Small,\n};\n\nconst getIconColor = (onColor: TriggerOnColor, variant: TriggerVariant, isActive: boolean): string | undefined => {\n if (onColor === 'ondark') {\n return 'white';\n }\n\n const depth = isActive ? 800 : 600;\n\n if (variant === 'help') {\n return getColor('plum', depth);\n }\n\n if (variant === 'info') {\n return getColor('blueberry', depth);\n }\n};\n\nconst Trigger = React.forwardRef<HTMLButtonElement, TriggerProps>(\n (\n {\n ariaLabel,\n ariaLabelledById,\n variant = 'help',\n onColor = 'onlight',\n size = 'medium',\n selected = false,\n isHovered,\n htmlMarkup = 'button',\n className,\n testId,\n ...rest\n },\n ref\n ) => {\n const { isHovered: buttonIsHovered, hoverRef } = useHover<HTMLButtonElement>();\n\n const triggerClasses = classNames(\n styles.trigger,\n onColor === 'onlight' && styles[`trigger--${variant}`], // variants look the same when onColor=ondark\n onColor === 'ondark' && styles[`trigger--${onColor}`],\n styles[`trigger--${size}`],\n isHovered && styles[`trigger--hovered`],\n selected && styles[`trigger--selected`],\n className\n );\n\n const iconColor = getIconColor(onColor, variant, isHovered || buttonIsHovered || selected);\n\n const icon = <Icon svgIcon={iconMap[variant]} size={iconSizeMap[size]} color={iconColor} isHovered={isHovered || buttonIsHovered} />;\n\n if (htmlMarkup === 'span') {\n return (\n <span data-testid={testId} data-analyticsid={AnalyticsId.Trigger} className={triggerClasses}>\n {icon}\n </span>\n );\n }\n\n const ariaLabelAttributes = getAriaLabelAttributes({ label: ariaLabel, id: ariaLabelledById });\n\n return (\n <button\n aria-label={ariaLabel}\n type=\"button\"\n data-testid={testId}\n data-analyticsid={AnalyticsId.Trigger}\n className={triggerClasses}\n ref={mergeRefs([ref, hoverRef])}\n aria-expanded={selected}\n {...ariaLabelAttributes}\n {...rest}\n >\n {icon}\n </button>\n );\n }\n);\n\nTrigger.displayName = 'Trigger';\n\nexport default Trigger;\n"],"names":["React"],"mappings":";;;;;;;;;;AAIA,MAAM,WAAmC,CAAC,EAAE,MAAM,gBAAkD;AAClG,QAAM,SACJ,oBAAC,QAAK,EAAA,GAAE,ijBAAijB,CAAA;AAG3jB,QAAM,cACJ,oBAAC,QAAK,EAAA,GAAE,kjBAAkjB,CAAA;AAG5jB,QAAM,SACJ,oBAAC,QAAK,EAAA,GAAE,yhBAAyhB,CAAA;AAGniB,QAAM,cACJ,oBAAC,QAAK,EAAA,GAAE,sjBAAsjB,CAAA;AAGzjB,SAAA,QAAQ,EAAE,MAAM,WAAW,QAAQ,aAAa,QAAQ,aAAa;AAC9E;
|
|
1
|
+
{"version":3,"file":"Trigger.js","sources":["../src/components/Trigger/HelpSign.tsx","../src/components/Trigger/Trigger.tsx"],"sourcesContent":["import React from 'react';\n\nimport { getIcon, SvgPathProps } from '../Icon';\n\nconst HelpSign: React.FC<SvgPathProps> = ({ size, isHovered }: SvgPathProps): React.ReactElement => {\n const normal = (\n <path d=\"M18.854 19.678c0-2.268 1.701-4.74 5.126-4.74 3.358 0 5.172 2.222 5.172 4.536 0 1.793-.952 3.064-2.268 3.992l-.976.682c-.749.521-1.134 1.27-1.134 2.154 0 .047 0 .16.023.296h-2.269a46.85 46.85 0 0 0-.01-.139 8.554 8.554 0 0 1-.036-.724c0-1.36.522-2.471 1.84-3.424l1.042-.75c.75-.544 1.066-1.201 1.066-1.974 0-1.178-.793-2.29-2.45-2.29-1.679 0-2.563 1.293-2.563 2.585 0 .34.045.772.136 1.022l-2.564-.181a3.903 3.903 0 0 1-.135-1.044Zm3.176 10.186c0-.908.726-1.678 1.656-1.678.908 0 1.656.77 1.656 1.678 0 .907-.748 1.657-1.656 1.657-.93 0-1.656-.75-1.656-1.657Z\" />\n );\n\n const normalHover = (\n <path d=\"M18.854 18.178c0-2.268 1.701-4.74 5.126-4.74 3.358 0 5.172 2.223 5.172 4.536 0 1.793-.952 3.064-2.268 3.992l-.976.682c-.749.521-1.134 1.27-1.134 2.154 0 .047 0 .16.023.296h-2.269a46.85 46.85 0 0 0-.01-.139 8.554 8.554 0 0 1-.036-.724c0-1.36.522-2.471 1.838-3.424l1.044-.75c.75-.544 1.066-1.201 1.066-1.974 0-1.178-.793-2.29-2.45-2.29-1.679 0-2.563 1.293-2.563 2.585 0 .34.045.772.135 1.022l-2.563-.181a3.903 3.903 0 0 1-.135-1.044Zm3.176 11.686c0-.908.725-1.678 1.655-1.678.908 0 1.657.77 1.657 1.678 0 .907-.749 1.657-1.657 1.657-.93 0-1.655-.75-1.655-1.657Z\" />\n );\n\n const xSmall = (\n <path d=\"M23.98 14.937c-3.425 0-5.127 2.473-5.127 4.741 0 .363.047.726.137 1.044l2.563.182c-.09-.25-.136-.681-.136-1.022 0-1.292.885-2.586 2.563-2.586 1.658 0 2.45 1.112 2.45 2.291 0 .772-.317 1.43-1.065 1.974l-1.043.749c-1.317.953-1.84 2.065-1.84 3.425 0 .319.024.567.047.862h2.267c-.021-.135-.021-.25-.021-.295 0-.884.385-1.633 1.133-2.154l.976-.681c1.317-.93 2.27-2.2 2.27-3.993 0-2.314-1.816-4.537-5.174-4.537m-.294 13.248c-.93 0-1.656.773-1.656 1.678a1.65 1.65 0 0 0 1.656 1.657c.907 0 1.656-.748 1.656-1.657 0-.905-.749-1.678-1.656-1.678\" />\n );\n\n const xSmallHover = (\n <path d=\"M18.853 18.289c0-2.268 1.701-4.742 5.127-4.742 3.357 0 5.173 2.223 5.173 4.537 0 1.794-.953 3.065-2.27 3.994l-.976.681c-.747.52-1.133 1.27-1.133 2.154 0 .046 0 .16.022.295h-2.267a39.324 39.324 0 0 0-.01-.125 8.468 8.468 0 0 1-.037-.737c0-1.36.523-2.472 1.839-3.425l1.043-.75c.748-.543 1.065-1.201 1.065-1.973 0-1.18-.792-2.29-2.45-2.29-1.678 0-2.562 1.293-2.562 2.585 0 .341.045.772.135 1.022l-2.563-.183a3.914 3.914 0 0 1-.136-1.043Zm3.176 11.575c0-.907.726-1.679 1.656-1.679.908 0 1.657.772 1.657 1.68 0 .907-.749 1.656-1.657 1.656-.93 0-1.656-.749-1.656-1.657Z\" />\n );\n\n return getIcon({ size, isHovered, normal, normalHover, xSmall, xSmallHover });\n};\n\nexport default HelpSign;\n","import React from 'react';\n\nimport classNames from 'classnames';\n\nimport HelpSign from './HelpSign';\nimport { AnalyticsId, IconSize } from '../../constants';\nimport { useHover } from '../../hooks/useHover';\nimport { getColor } from '../../theme/currys';\nimport { getAriaLabelAttributes } from '../../utils/accessibility';\nimport { mergeRefs } from '../../utils/refs';\nimport Icon, { SvgIcon } from '../Icon';\n\nimport styles from './styles.module.scss';\n\nexport type TriggerTags = 'button' | 'span';\n\nexport type TriggerVariant = 'help'; // @todo Support variant='info' in later version\n\nexport type TriggerSize = 'medium' | 'large';\n\nexport type TriggerOnColor = 'onlight' | 'ondark';\n\nexport interface TriggerProps extends Pick<React.InputHTMLAttributes<HTMLButtonElement>, 'onClick' | 'aria-haspopup' | 'aria-controls'> {\n /**\n * Sets aria-label of the trigger. ariaLabel or ariaLabelledById MUST be set!\n */\n ariaLabel?: string;\n /**\n * Sets aria-labelledby of the trigger. ariaLabel or ariaLabelledById MUST be set!\n */\n ariaLabelledById?: string;\n /**\n * Controls the icon and color. Default: help.\n */\n /** @deprecated This will be removed in next major version */\n variant?: TriggerVariant;\n /**\n * Changes the design based on the background the trigger is placed on. Default: onlight.\n */\n onColor?: TriggerOnColor;\n /**\n * Size of the trigger. Default: medium.\n */\n size?: TriggerSize;\n /**\n * Indicates that the trigger is in use.\n */\n selected?: boolean;\n /**\n * Indicates that the trigger is hovered. Used in combination with htmlMarkup=span to force visual hover state.\n */\n isHovered?: boolean;\n /**\n * Changes the underlying element of the trigger. If set to span, the trigger will be a non-interactive icon. Default: button\n */\n htmlMarkup?: TriggerTags;\n /**\n * Classname will be applied to the button element.\n */\n className?: string;\n /**\n * Optional test id.\n */\n testId?: string;\n}\n\nconst iconMap: Record<TriggerVariant, SvgIcon> = {\n help: HelpSign,\n //info: InfoSignStroke, // @todo Support variant='info' in later version\n};\n\nconst iconSizeMap: Record<TriggerSize, IconSize> = {\n medium: IconSize.XSmall,\n large: IconSize.Small,\n};\n\nconst getIconColor = (onColor: TriggerOnColor, variant: TriggerVariant, isActive: boolean): string | undefined => {\n if (onColor === 'ondark') {\n return 'white';\n }\n\n const depth = isActive ? 800 : 600;\n\n if (variant === 'help') {\n return getColor('plum', depth);\n }\n\n if (variant === 'info') {\n return getColor('blueberry', depth);\n }\n};\n\nconst Trigger = React.forwardRef<HTMLButtonElement, TriggerProps>(\n (\n {\n ariaLabel,\n ariaLabelledById,\n variant = 'help',\n onColor = 'onlight',\n size = 'medium',\n selected = false,\n isHovered,\n htmlMarkup = 'button',\n className,\n testId,\n ...rest\n },\n ref\n ) => {\n const { isHovered: buttonIsHovered, hoverRef } = useHover<HTMLButtonElement>();\n\n const triggerClasses = classNames(\n styles.trigger,\n onColor === 'onlight' && styles[`trigger--${variant}`], // variants look the same when onColor=ondark\n onColor === 'ondark' && styles[`trigger--${onColor}`],\n styles[`trigger--${size}`],\n isHovered && styles[`trigger--hovered`],\n selected && styles[`trigger--selected`],\n className\n );\n\n const iconColor = getIconColor(onColor, variant, isHovered || buttonIsHovered || selected);\n\n const icon = <Icon svgIcon={iconMap[variant]} size={iconSizeMap[size]} color={iconColor} isHovered={isHovered || buttonIsHovered} />;\n\n if (htmlMarkup === 'span') {\n return (\n <span data-testid={testId} data-analyticsid={AnalyticsId.Trigger} className={triggerClasses}>\n {icon}\n </span>\n );\n }\n\n const ariaLabelAttributes = getAriaLabelAttributes({ label: ariaLabel, id: ariaLabelledById });\n\n return (\n <button\n aria-label={ariaLabel}\n type=\"button\"\n data-testid={testId}\n data-analyticsid={AnalyticsId.Trigger}\n className={triggerClasses}\n ref={mergeRefs([ref, hoverRef])}\n aria-expanded={selected}\n {...ariaLabelAttributes}\n {...rest}\n >\n {icon}\n </button>\n );\n }\n);\n\nTrigger.displayName = 'Trigger';\n\nexport default Trigger;\n"],"names":["React"],"mappings":";;;;;;;;;;AAIA,MAAM,WAAmC,CAAC,EAAE,MAAM,gBAAkD;AAClG,QAAM,SACJ,oBAAC,QAAK,EAAA,GAAE,ijBAAijB,CAAA;AAG3jB,QAAM,cACJ,oBAAC,QAAK,EAAA,GAAE,kjBAAkjB,CAAA;AAG5jB,QAAM,SACJ,oBAAC,QAAK,EAAA,GAAE,yhBAAyhB,CAAA;AAGniB,QAAM,cACJ,oBAAC,QAAK,EAAA,GAAE,sjBAAsjB,CAAA;AAGzjB,SAAA,QAAQ,EAAE,MAAM,WAAW,QAAQ,aAAa,QAAQ,aAAa;AAC9E;AC4CA,MAAM,UAA2C;AAAA,EAC/C,MAAM;AAAA;AAER;AAEA,MAAM,cAA6C;AAAA,EACjD,QAAQ,SAAS;AAAA,EACjB,OAAO,SAAS;AAClB;AAEA,MAAM,eAAe,CAAC,SAAyB,SAAyB,aAA0C;AAChH,MAAI,YAAY,UAAU;AACjB,WAAA;AAAA,EAAA;AAGH,QAAA,QAAQ,WAAW,MAAM;AAE/B,MAAI,YAAY,QAAQ;AACf,WAAA,SAAS,QAAQ,KAAK;AAAA,EAAA;AAG/B,MAAI,YAAY,QAAQ;AACf,WAAA,SAAS,aAAa,KAAK;AAAA,EAAA;AAEtC;AAEA,MAAM,UAAUA,eAAM;AAAA,EACpB,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV,UAAU;AAAA,IACV,OAAO;AAAA,IACP,WAAW;AAAA,IACX;AAAA,IACA,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA,GAAG;AAAA,KAEL,QACG;AACH,UAAM,EAAE,WAAW,iBAAiB,SAAA,IAAa,SAA4B;AAE7E,UAAM,iBAAiB;AAAA,MACrB,OAAO;AAAA,MACP,YAAY,aAAa,OAAO,YAAY,OAAO,EAAE;AAAA;AAAA,MACrD,YAAY,YAAY,OAAO,YAAY,OAAO,EAAE;AAAA,MACpD,OAAO,YAAY,IAAI,EAAE;AAAA,MACzB,aAAa,OAAO,kBAAkB;AAAA,MACtC,YAAY,OAAO,mBAAmB;AAAA,MACtC;AAAA,IACF;AAEA,UAAM,YAAY,aAAa,SAAS,SAAS,aAAa,mBAAmB,QAAQ;AAEzF,UAAM,OAAO,oBAAC,MAAK,EAAA,SAAS,QAAQ,OAAO,GAAG,MAAM,YAAY,IAAI,GAAG,OAAO,WAAW,WAAW,aAAa,iBAAiB;AAElI,QAAI,eAAe,QAAQ;AAEvB,aAAA,oBAAC,UAAK,eAAa,QAAQ,oBAAkB,YAAY,SAAS,WAAW,gBAC1E,UACH,KAAA,CAAA;AAAA,IAAA;AAIJ,UAAM,sBAAsB,uBAAuB,EAAE,OAAO,WAAW,IAAI,kBAAkB;AAG3F,WAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,cAAY;AAAA,QACZ,MAAK;AAAA,QACL,eAAa;AAAA,QACb,oBAAkB,YAAY;AAAA,QAC9B,WAAW;AAAA,QACX,KAAK,UAAU,CAAC,KAAK,QAAQ,CAAC;AAAA,QAC9B,iBAAe;AAAA,QACd,GAAG;AAAA,QACH,GAAG;AAAA,QAEH,UAAA;AAAA,MAAA;AAAA,IACH;AAAA,EAAA;AAGN;AAEA,QAAQ,cAAc;"}
|
|
@@ -44,13 +44,15 @@ const Dropdown = (props) => {
|
|
|
44
44
|
const dropdownRef = useRef(null);
|
|
45
45
|
const optionsRef = useRef(null);
|
|
46
46
|
const { hoverRef: buttonRef, isHovered } = useHover();
|
|
47
|
+
const openedByKeyboard = useRef(false);
|
|
47
48
|
const { value: isOpen, toggleValue: toggleIsOpen } = useToggle(!disabled && open, onToggle);
|
|
48
49
|
const inputRefList = useRef(React__default.Children.map(children, () => React__default.createRef()));
|
|
49
50
|
const [currentIndex, setCurrentIndex] = useState();
|
|
50
51
|
const labelId = useUuid();
|
|
51
52
|
const toggleLabelId = useUuid();
|
|
52
53
|
const optionIdPrefix = useUuid();
|
|
53
|
-
const handleOpen = () => {
|
|
54
|
+
const handleOpen = (isKeyboard) => {
|
|
55
|
+
openedByKeyboard.current = isKeyboard;
|
|
54
56
|
toggleIsOpen();
|
|
55
57
|
};
|
|
56
58
|
const handleClose = () => {
|
|
@@ -60,7 +62,7 @@ const Dropdown = (props) => {
|
|
|
60
62
|
};
|
|
61
63
|
useEffect(() => {
|
|
62
64
|
var _a, _b, _c;
|
|
63
|
-
if (isOpen) {
|
|
65
|
+
if (isOpen && openedByKeyboard.current) {
|
|
64
66
|
(_c = (_b = (_a = inputRefList.current) == null ? void 0 : _a.find((inputRef, index) => {
|
|
65
67
|
if (inputRef.current && !inputRef.current.hasAttribute("disabled")) {
|
|
66
68
|
setCurrentIndex(index);
|
|
@@ -75,7 +77,7 @@ const Dropdown = (props) => {
|
|
|
75
77
|
return;
|
|
76
78
|
}
|
|
77
79
|
if (!isOpen) {
|
|
78
|
-
handleOpen();
|
|
80
|
+
handleOpen(true);
|
|
79
81
|
event.preventDefault();
|
|
80
82
|
return;
|
|
81
83
|
} else if (event.key === KeyboardEventKey.Escape && isOpen) {
|
|
@@ -95,7 +97,7 @@ const Dropdown = (props) => {
|
|
|
95
97
|
} else if (event.key === KeyboardEventKey.Enter && index !== -1) {
|
|
96
98
|
nextIndex = index;
|
|
97
99
|
}
|
|
98
|
-
if (nextIndex !== -1) {
|
|
100
|
+
if (nextIndex !== -1 && event.key !== KeyboardEventKey.Space) {
|
|
99
101
|
event.preventDefault();
|
|
100
102
|
(_a = inputRefList.current[nextIndex].current) == null ? void 0 : _a.focus();
|
|
101
103
|
setCurrentIndex(nextIndex);
|
|
@@ -107,7 +109,8 @@ const Dropdown = (props) => {
|
|
|
107
109
|
KeyboardEventKey.End,
|
|
108
110
|
KeyboardEventKey.Enter,
|
|
109
111
|
KeyboardEventKey.Escape,
|
|
110
|
-
KeyboardEventKey.Home
|
|
112
|
+
KeyboardEventKey.Home,
|
|
113
|
+
KeyboardEventKey.Space
|
|
111
114
|
]);
|
|
112
115
|
useOutsideEvent(dropdownRef, () => isOpen && handleClose());
|
|
113
116
|
const toggleClasses = classNames(
|
|
@@ -133,7 +136,7 @@ const Dropdown = (props) => {
|
|
|
133
136
|
"button",
|
|
134
137
|
{
|
|
135
138
|
type: "button",
|
|
136
|
-
onClick: () => !isOpen && handleOpen(),
|
|
139
|
+
onClick: () => !isOpen && handleOpen(false),
|
|
137
140
|
className: toggleClasses,
|
|
138
141
|
ref: buttonRef,
|
|
139
142
|
"data-testid": testId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/components/Dropdown/Dropdown.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\n\nimport classNames from 'classnames';\n\nimport {\n AnalyticsId,\n IconSize,\n KeyboardEventKey,\n ZIndex,\n theme,\n useHover,\n useKeyboardEvent,\n useOutsideEvent,\n useToggle,\n useUuid,\n} from '../..';\nimport { isComponent } from '../../utils/component';\nimport { mergeRefs } from '../../utils/refs';\nimport Button from '../Button';\nimport Checkbox, { CheckboxProps } from '../Checkbox';\nimport Icon from '../Icon';\nimport PlusSmall from '../Icons/PlusSmall';\nimport RadioButton, { RadioButtonProps } from '../RadioButton';\n\nimport styles from './styles.module.scss';\n\nexport enum DropdownOnColor {\n onwhite = 'onwhite',\n ongrey = 'ongrey',\n onblueberry = 'onblueberry',\n oncherry = 'oncherry',\n}\n\nexport interface DropdownProps {\n /** Label for dropdown. Visible for screen readers */\n label: string;\n /** Text on the trigger button that opens the dropdown */\n placeholder: string;\n /** Sets the dropdown content */\n children: React.ReactNode;\n /** Close button text */\n closeText?: string;\n /** Minimum width for the dropdown in pixels. Does not affect trigger button */\n dropdownMinWidth?: number;\n /** No close button */\n noCloseButton?: boolean;\n /** Called when dropdown is open/closed */\n onToggle?: (isOpen: boolean) => void;\n /** Whether the dropdown is open or not */\n open?: boolean;\n /** Changes the visuals of the dropdown */\n onColor?: keyof typeof DropdownOnColor;\n /** Makes the background of the trigger transparent */\n transparent?: boolean;\n /** Makes the width of the full component adjust to its parent */\n fluid?: boolean;\n /** Makes the dropdown disabled */\n disabled?: boolean;\n /** Sets the data-testid attribute on the dropdown button */\n testId?: string;\n /** Overrides the default z-index of the DropDownContent */\n zIndex?: number;\n}\n\nconst Dropdown: React.FC<DropdownProps> = props => {\n const {\n label,\n placeholder,\n closeText = 'Lukk',\n noCloseButton = false,\n onToggle,\n dropdownMinWidth,\n open = false,\n children,\n onColor = DropdownOnColor.onwhite,\n transparent = false,\n fluid = false,\n testId,\n disabled,\n zIndex = ZIndex.PopOver,\n } = props;\n const dropdownRef = useRef<HTMLDivElement>(null);\n const optionsRef = useRef<HTMLUListElement>(null);\n const { hoverRef: buttonRef, isHovered } = useHover<HTMLButtonElement>();\n const { value: isOpen, toggleValue: toggleIsOpen } = useToggle(!disabled && open, onToggle);\n const inputRefList = useRef(React.Children.map(children, () => React.createRef<HTMLElement>()));\n const [currentIndex, setCurrentIndex] = useState<number>();\n const labelId = useUuid();\n const toggleLabelId = useUuid();\n const optionIdPrefix = useUuid();\n\n const handleOpen = (): void => {\n toggleIsOpen();\n };\n\n const handleClose = (): void => {\n toggleIsOpen();\n buttonRef.current?.focus();\n };\n\n useEffect(() => {\n if (isOpen) {\n inputRefList.current\n ?.find((inputRef, index) => {\n if (inputRef.current && !inputRef.current.hasAttribute('disabled')) {\n setCurrentIndex(index);\n return true;\n }\n })\n ?.current?.focus();\n }\n }, [isOpen]);\n\n const handleKeyboardNavigation = (event: KeyboardEvent): void => {\n if (!inputRefList.current) {\n return;\n }\n\n if (!isOpen) {\n handleOpen();\n event.preventDefault();\n return;\n } else if (event.key === KeyboardEventKey.Escape && isOpen) {\n handleClose();\n return;\n }\n\n const index = inputRefList.current.findIndex(x => x.current === event.target);\n let nextIndex = index;\n\n if (event.key === KeyboardEventKey.Home) {\n nextIndex = 0;\n } else if (event.key === KeyboardEventKey.End) {\n nextIndex = inputRefList.current.length - 1;\n } else if (event.key === KeyboardEventKey.ArrowDown && index < inputRefList.current.length - 1) {\n nextIndex = index + 1;\n } else if (event.key === KeyboardEventKey.ArrowUp && index > 0) {\n nextIndex = index - 1;\n } else if (event.key === KeyboardEventKey.Enter && index !== -1) {\n nextIndex = index;\n }\n\n if (nextIndex !== -1) {\n event.preventDefault();\n\n inputRefList.current[nextIndex].current?.focus();\n setCurrentIndex(nextIndex);\n }\n };\n\n useKeyboardEvent(dropdownRef, handleKeyboardNavigation, [\n KeyboardEventKey.ArrowDown,\n KeyboardEventKey.ArrowUp,\n KeyboardEventKey.End,\n KeyboardEventKey.Enter,\n KeyboardEventKey.Escape,\n KeyboardEventKey.Home,\n ]);\n\n useOutsideEvent(dropdownRef, () => isOpen && handleClose());\n\n const toggleClasses = classNames(\n styles.dropdown__toggle,\n !disabled && {\n [styles['dropdown__toggle--on-white']]: onColor === DropdownOnColor.onwhite,\n [styles['dropdown__toggle--on-grey']]: onColor === DropdownOnColor.ongrey,\n [styles['dropdown__toggle--on-blueberry']]: onColor === DropdownOnColor.onblueberry,\n [styles['dropdown__toggle--on-cherry']]: onColor === DropdownOnColor.oncherry,\n [styles['dropdown__toggle--transparent']]: transparent,\n [styles['dropdown__toggle--fluid']]: fluid,\n [styles['dropdown__toggle--open']]: isOpen,\n }\n );\n\n const contentClasses = classNames(styles.dropdown__content, isOpen && styles['dropdown__content--open']);\n\n const renderChildren = React.Children.map(children, (child, index) => {\n const role = isComponent<RadioButtonProps>(child, RadioButton)\n ? 'menuitemradio'\n : isComponent<CheckboxProps>(child, Checkbox)\n ? 'menuitemcheckbox'\n : 'menuitem';\n\n return (\n <li className={styles.dropdown__input} role={role} id={`${optionIdPrefix}-${index}`}>\n {React.isValidElement(child) && inputRefList.current && inputRefList.current[index]\n ? React.cloneElement(child as React.ReactElement, { ref: mergeRefs([child.props.ref, inputRefList.current[index]]) })\n : child}\n </li>\n );\n });\n\n return (\n <div className={styles.dropdown} ref={dropdownRef}>\n <span id={labelId} className={styles.dropdown__label}>\n {label}\n </span>\n <button\n type=\"button\"\n onClick={(): false | void => !isOpen && handleOpen()}\n className={toggleClasses}\n ref={buttonRef}\n data-testid={testId}\n data-analyticsid={AnalyticsId.Dropdown}\n disabled={disabled}\n aria-labelledby={toggleLabelId}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen}\n >\n <span id={toggleLabelId} className={styles.dropdown__toggle__label}>\n {placeholder}\n </span>\n <Icon\n color={disabled ? theme.palette.neutral700 : theme.palette.blueberry600}\n svgIcon={PlusSmall}\n className={styles.dropdown__icon}\n isHovered={!disabled && isHovered}\n size={IconSize.XSmall}\n />\n </button>\n <div className={contentClasses} style={{ width: fluid ? '100%' : `auto`, minWidth: dropdownMinWidth ?? 'auto', zIndex: zIndex }}>\n <ul\n className={styles.dropdown__options}\n role=\"menu\"\n aria-labelledby={labelId}\n tabIndex={-1}\n aria-activedescendant={typeof currentIndex !== 'undefined' ? `${optionIdPrefix}-${currentIndex}` : undefined}\n ref={optionsRef}\n >\n {renderChildren}\n </ul>\n {!noCloseButton && (\n <div className={styles.dropdown__close}>\n <Button onClick={handleClose} aria-expanded={isOpen}>\n {closeText}\n </Button>\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default Dropdown;\n"],"names":["DropdownOnColor","React"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/components/Dropdown/Dropdown.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\n\nimport classNames from 'classnames';\n\nimport {\n AnalyticsId,\n IconSize,\n KeyboardEventKey,\n ZIndex,\n theme,\n useHover,\n useKeyboardEvent,\n useOutsideEvent,\n useToggle,\n useUuid,\n} from '../..';\nimport { isComponent } from '../../utils/component';\nimport { mergeRefs } from '../../utils/refs';\nimport Button from '../Button';\nimport Checkbox, { CheckboxProps } from '../Checkbox';\nimport Icon from '../Icon';\nimport PlusSmall from '../Icons/PlusSmall';\nimport RadioButton, { RadioButtonProps } from '../RadioButton';\n\nimport styles from './styles.module.scss';\n\nexport enum DropdownOnColor {\n onwhite = 'onwhite',\n ongrey = 'ongrey',\n onblueberry = 'onblueberry',\n oncherry = 'oncherry',\n}\n\nexport interface DropdownProps {\n /** Label for dropdown. Visible for screen readers */\n label: string;\n /** Text on the trigger button that opens the dropdown */\n placeholder: string;\n /** Sets the dropdown content */\n children: React.ReactNode;\n /** Close button text */\n closeText?: string;\n /** Minimum width for the dropdown in pixels. Does not affect trigger button */\n dropdownMinWidth?: number;\n /** No close button */\n noCloseButton?: boolean;\n /** Called when dropdown is open/closed */\n onToggle?: (isOpen: boolean) => void;\n /** Whether the dropdown is open or not */\n open?: boolean;\n /** Changes the visuals of the dropdown */\n onColor?: keyof typeof DropdownOnColor;\n /** Makes the background of the trigger transparent */\n transparent?: boolean;\n /** Makes the width of the full component adjust to its parent */\n fluid?: boolean;\n /** Makes the dropdown disabled */\n disabled?: boolean;\n /** Sets the data-testid attribute on the dropdown button */\n testId?: string;\n /** Overrides the default z-index of the DropDownContent */\n zIndex?: number;\n}\n\nconst Dropdown: React.FC<DropdownProps> = props => {\n const {\n label,\n placeholder,\n closeText = 'Lukk',\n noCloseButton = false,\n onToggle,\n dropdownMinWidth,\n open = false,\n children,\n onColor = DropdownOnColor.onwhite,\n transparent = false,\n fluid = false,\n testId,\n disabled,\n zIndex = ZIndex.PopOver,\n } = props;\n const dropdownRef = useRef<HTMLDivElement>(null);\n const optionsRef = useRef<HTMLUListElement>(null);\n const { hoverRef: buttonRef, isHovered } = useHover<HTMLButtonElement>();\n const openedByKeyboard = useRef<boolean>(false);\n const { value: isOpen, toggleValue: toggleIsOpen } = useToggle(!disabled && open, onToggle);\n const inputRefList = useRef(React.Children.map(children, () => React.createRef<HTMLElement>()));\n const [currentIndex, setCurrentIndex] = useState<number>();\n const labelId = useUuid();\n const toggleLabelId = useUuid();\n const optionIdPrefix = useUuid();\n\n const handleOpen = (isKeyboard: boolean): void => {\n openedByKeyboard.current = isKeyboard;\n toggleIsOpen();\n };\n\n const handleClose = (): void => {\n toggleIsOpen();\n buttonRef.current?.focus();\n };\n\n useEffect(() => {\n if (isOpen && openedByKeyboard.current) {\n inputRefList.current\n ?.find((inputRef, index) => {\n if (inputRef.current && !inputRef.current.hasAttribute('disabled')) {\n setCurrentIndex(index);\n return true;\n }\n })\n ?.current?.focus();\n }\n }, [isOpen]);\n\n const handleKeyboardNavigation = (event: KeyboardEvent): void => {\n if (!inputRefList.current) {\n return;\n }\n\n if (!isOpen) {\n handleOpen(true);\n event.preventDefault();\n return;\n } else if (event.key === KeyboardEventKey.Escape && isOpen) {\n handleClose();\n return;\n }\n\n const index = inputRefList.current.findIndex(x => x.current === event.target);\n let nextIndex = index;\n\n if (event.key === KeyboardEventKey.Home) {\n nextIndex = 0;\n } else if (event.key === KeyboardEventKey.End) {\n nextIndex = inputRefList.current.length - 1;\n } else if (event.key === KeyboardEventKey.ArrowDown && index < inputRefList.current.length - 1) {\n nextIndex = index + 1;\n } else if (event.key === KeyboardEventKey.ArrowUp && index > 0) {\n nextIndex = index - 1;\n } else if (event.key === KeyboardEventKey.Enter && index !== -1) {\n nextIndex = index;\n }\n\n if (nextIndex !== -1 && event.key !== KeyboardEventKey.Space) {\n event.preventDefault();\n\n inputRefList.current[nextIndex].current?.focus();\n setCurrentIndex(nextIndex);\n }\n };\n\n useKeyboardEvent(dropdownRef, handleKeyboardNavigation, [\n KeyboardEventKey.ArrowDown,\n KeyboardEventKey.ArrowUp,\n KeyboardEventKey.End,\n KeyboardEventKey.Enter,\n KeyboardEventKey.Escape,\n KeyboardEventKey.Home,\n KeyboardEventKey.Space,\n ]);\n\n useOutsideEvent(dropdownRef, () => isOpen && handleClose());\n\n const toggleClasses = classNames(\n styles.dropdown__toggle,\n !disabled && {\n [styles['dropdown__toggle--on-white']]: onColor === DropdownOnColor.onwhite,\n [styles['dropdown__toggle--on-grey']]: onColor === DropdownOnColor.ongrey,\n [styles['dropdown__toggle--on-blueberry']]: onColor === DropdownOnColor.onblueberry,\n [styles['dropdown__toggle--on-cherry']]: onColor === DropdownOnColor.oncherry,\n [styles['dropdown__toggle--transparent']]: transparent,\n [styles['dropdown__toggle--fluid']]: fluid,\n [styles['dropdown__toggle--open']]: isOpen,\n }\n );\n\n const contentClasses = classNames(styles.dropdown__content, isOpen && styles['dropdown__content--open']);\n\n const renderChildren = React.Children.map(children, (child, index) => {\n const role = isComponent<RadioButtonProps>(child, RadioButton)\n ? 'menuitemradio'\n : isComponent<CheckboxProps>(child, Checkbox)\n ? 'menuitemcheckbox'\n : 'menuitem';\n\n return (\n <li className={styles.dropdown__input} role={role} id={`${optionIdPrefix}-${index}`}>\n {React.isValidElement(child) && inputRefList.current && inputRefList.current[index]\n ? React.cloneElement(child as React.ReactElement, { ref: mergeRefs([child.props.ref, inputRefList.current[index]]) })\n : child}\n </li>\n );\n });\n\n return (\n <div className={styles.dropdown} ref={dropdownRef}>\n <span id={labelId} className={styles.dropdown__label}>\n {label}\n </span>\n <button\n type=\"button\"\n onClick={(): false | void => !isOpen && handleOpen(false)}\n className={toggleClasses}\n ref={buttonRef}\n data-testid={testId}\n data-analyticsid={AnalyticsId.Dropdown}\n disabled={disabled}\n aria-labelledby={toggleLabelId}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen}\n >\n <span id={toggleLabelId} className={styles.dropdown__toggle__label}>\n {placeholder}\n </span>\n <Icon\n color={disabled ? theme.palette.neutral700 : theme.palette.blueberry600}\n svgIcon={PlusSmall}\n className={styles.dropdown__icon}\n isHovered={!disabled && isHovered}\n size={IconSize.XSmall}\n />\n </button>\n <div className={contentClasses} style={{ width: fluid ? '100%' : `auto`, minWidth: dropdownMinWidth ?? 'auto', zIndex: zIndex }}>\n <ul\n className={styles.dropdown__options}\n role=\"menu\"\n aria-labelledby={labelId}\n tabIndex={-1}\n aria-activedescendant={typeof currentIndex !== 'undefined' ? `${optionIdPrefix}-${currentIndex}` : undefined}\n ref={optionsRef}\n >\n {renderChildren}\n </ul>\n {!noCloseButton && (\n <div className={styles.dropdown__close}>\n <Button onClick={handleClose} aria-expanded={isOpen}>\n {closeText}\n </Button>\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default Dropdown;\n"],"names":["DropdownOnColor","React"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/components/PopMenu/PopMenu.tsx"],"sourcesContent":["import React, { useRef, useState } from 'react';\n\nimport classNames from 'classnames';\n\nimport { AnalyticsId, IconSize } from '../../constants';\nimport { useBreakpoint } from '../../hooks/useBreakpoint';\nimport { useHover } from '../../hooks/useHover';\nimport { useOutsideEvent } from '../../hooks/useOutsideEvent';\nimport { getColor } from '../../theme/currys';\nimport { breakpoints } from '../../theme/grid';\nimport { isComponent } from '../../utils/component';\nimport Icon, { SvgIcon } from '../Icon';\nimport { IconName } from '../Icons/IconNames';\nimport VerticalDots from '../Icons/VerticalDots';\nimport X from '../Icons/X';\nimport LazyIcon from '../LazyIcon';\nimport LinkList, { LinkListProps, LinkProps } from '../LinkList';\nimport PopOver from '../PopOver';\n\nimport styles from './styles.module.scss';\n\nexport enum PopMenuVariant {\n onWhite = 'on-white',\n onGray = 'on-gray',\n onBlueberry = 'on-blueberry',\n}\n\nexport enum PopMenuLabelPosition {\n right = 'right',\n left = 'left',\n}\n\nexport interface PopMenuProps {\n /** Content shown inside PopOver. Can only be a LinkList */\n children: React.ReactElement<LinkListProps>;\n /** Adds custom classes to the popover element. */\n popOverClassName?: string;\n /** Adds custom classes to the element. */\n popMenuClassName?: string;\n /** Changes responsive design for the trigger buttons. */\n popMenuVariant?: PopMenuVariant;\n /** Sets the data-testid attribute for the button that opens. */\n openButtonTestId?: string;\n /** Sets the data-testid attribute for the button that closes. */\n closeButtonTestId?: string;\n /** Sets the data-testid attribute for the popover. */\n popOverTestId?: string;\n /** Sets the arial-label attribute for the openButton. */\n openButtonAriaLabel?: string;\n /** Sets the arial-label attribute for the closeButton. */\n closeButtonAriaLabel?: string;\n /** Sets the icon on the trigger button. */\n svgIcon?: SvgIcon | IconName;\n /** Optional text next to the trigger button. */\n labelText?: string;\n /** Placement of the label text relative to the trigger button. */\n labelTextPosition?: PopMenuLabelPosition;\n}\n\nexport const PopMenu: React.FC<PopMenuProps> = (props: PopMenuProps) => {\n const triggerButtonRef = useRef<HTMLButtonElement>(null);\n const iconRef = useRef<HTMLDivElement>(null);\n const popOverRef = useRef<HTMLDivElement>(null);\n const outerRef = useRef<HTMLDivElement>(null);\n const [isOpen, setIsOpen] = useState(false);\n const {\n children,\n popOverClassName,\n popMenuClassName,\n openButtonTestId,\n closeButtonTestId,\n popOverTestId,\n popMenuVariant = PopMenuVariant.onWhite,\n openButtonAriaLabel,\n closeButtonAriaLabel,\n svgIcon,\n labelText,\n labelTextPosition = PopMenuLabelPosition.right,\n } = props;\n const buttonClasses = classNames(styles['pop-menu-button'], {\n [styles[`pop-menu-button--${popMenuVariant}`]]: popMenuVariant,\n });\n const breakpoint = useBreakpoint();\n const mobile = breakpoint < breakpoints.md;\n\n useOutsideEvent(outerRef, () => {\n setIsOpen(false);\n });\n\n const { isHovered: triggerButtonIsHovered } = useHover(triggerButtonRef);\n const mobileIconSize = mobile ? IconSize.XSmall : IconSize.Small;\n\n const handleClick = (cb?: () => void): void => {\n setIsOpen(false);\n cb && cb();\n };\n\n const renderChildren = () => {\n if (isComponent<LinkListProps>(children, LinkList)) {\n return (\n <PopOver\n testId={popOverTestId}\n className={classNames(styles['pop-menu__pop-over'], popOverClassName)}\n arrowClassName={styles['pop-menu__pop-over-arrow']}\n controllerRef={iconRef}\n popOverRef={popOverRef}\n >\n {React.Children.map(children, child =>\n React.cloneElement(child, {\n children: React.Children.map(child.props.children, child =>\n isComponent<LinkProps>(child, LinkList.Link)\n ? React.cloneElement(child, {\n onClick: (event: React.MouseEvent<HTMLAnchorElement | HTMLButtonElement>) =>\n handleClick(() => child.props.onClick && child.props.onClick(event)),\n })\n : child\n ),\n })\n )}\n </PopOver>\n );\n }\n };\n\n const toggleOpenOnClick = (e?: React.MouseEvent<HTMLElement, MouseEvent>): void => {\n e && e.stopPropagation();\n setIsOpen(!isOpen);\n };\n\n const iconComponent =\n svgIcon && typeof svgIcon === 'string' ? (\n <LazyIcon iconName={svgIcon} size={IconSize.XSmall} isHovered={triggerButtonIsHovered} />\n ) : (\n svgIcon && <Icon svgIcon={svgIcon} size={IconSize.XSmall} isHovered={triggerButtonIsHovered} />\n );\n\n const openIcon = svgIcon ? (\n iconComponent\n ) : (\n <Icon svgIcon={svgIcon ?? VerticalDots} color={getColor('black')} size={mobileIconSize} isHovered={triggerButtonIsHovered} />\n );\n\n const closeIcon = <Icon svgIcon={X} color={getColor('black')} size={mobileIconSize} isHovered={triggerButtonIsHovered} />;\n\n const triggerButton = (\n <button\n ref={triggerButtonRef}\n data-testid={isOpen ? closeButtonTestId : openButtonTestId}\n className={buttonClasses}\n aria-label={isOpen ? closeButtonAriaLabel : openButtonAriaLabel}\n aria-expanded={isOpen}\n onClick={toggleOpenOnClick}\n type=\"button\"\n >\n {labelText && labelTextPosition == PopMenuLabelPosition.left && <span>{labelText}</span>}\n {<div ref={iconRef}>{isOpen ? closeIcon : openIcon}</div>}\n {labelText && labelTextPosition == PopMenuLabelPosition.right && <span>{labelText}</span>}\n </button>\n );\n\n return (\n <div ref={outerRef} className={classNames(styles['pop-menu-button'], popMenuClassName)} data-analyticsid={AnalyticsId.PopMenu}>\n {triggerButton}\n {isOpen && renderChildren()}\n </div>\n );\n};\n\nexport default PopMenu;\n"],"names":["PopMenuVariant","PopMenuLabelPosition","React","child"],"mappings":";;;;;;;;;;;;;;;;;AAqBY,IAAA,mCAAAA,oBAAL;AACLA,kBAAA,SAAU,IAAA;AACVA,kBAAA,QAAS,IAAA;AACTA,kBAAA,aAAc,IAAA;AAHJA,SAAAA;AAAA,GAAA,kBAAA,CAAA,CAAA;AAMA,IAAA,yCAAAC,0BAAL;AACLA,wBAAA,OAAQ,IAAA;AACRA,wBAAA,MAAO,IAAA;AAFGA,SAAAA;AAAA,GAAA,wBAAA,CAAA,CAAA;AAgCC,MAAA,UAAkC,CAAC,UAAwB;AAChE,QAAA,mBAAmB,OAA0B,IAAI;AACjD,QAAA,UAAU,OAAuB,IAAI;AACrC,QAAA,aAAa,OAAuB,IAAI;AACxC,QAAA,WAAW,OAAuB,IAAI;AAC5C,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AACpC,QAAA;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,iBAAiB;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,oBAAoB;AAAA;AAAA,EAAA,IAClB;AACJ,QAAM,gBAAgB,WAAW,OAAO,iBAAiB,GAAG;AAAA,IAC1D,CAAC,OAAO,oBAAoB,cAAc,EAAE,CAAC,GAAG;AAAA,EAAA,CACjD;AACD,QAAM,aAAa,cAAc;AAC3B,QAAA,SAAS,aAAa,YAAY;AAExC,kBAAgB,UAAU,MAAM;AAC9B,cAAU,KAAK;AAAA,EAAA,CAChB;AAED,QAAM,EAAE,WAAW,2BAA2B,SAAS,gBAAgB;AACvE,QAAM,iBAAiB,SAAS,SAAS,SAAS,SAAS;AAErD,QAAA,cAAc,CAAC,OAA0B;AAC7C,cAAU,KAAK;AACf,UAAM,GAAG;AAAA,EACX;AAEA,QAAM,iBAAiB,
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/components/PopMenu/PopMenu.tsx"],"sourcesContent":["import React, { useRef, useState } from 'react';\n\nimport classNames from 'classnames';\n\nimport { AnalyticsId, IconSize } from '../../constants';\nimport { useBreakpoint } from '../../hooks/useBreakpoint';\nimport { useHover } from '../../hooks/useHover';\nimport { useOutsideEvent } from '../../hooks/useOutsideEvent';\nimport { getColor } from '../../theme/currys';\nimport { breakpoints } from '../../theme/grid';\nimport { isComponent } from '../../utils/component';\nimport Icon, { SvgIcon } from '../Icon';\nimport { IconName } from '../Icons/IconNames';\nimport VerticalDots from '../Icons/VerticalDots';\nimport X from '../Icons/X';\nimport LazyIcon from '../LazyIcon';\nimport LinkList, { LinkListProps, LinkProps } from '../LinkList';\nimport PopOver from '../PopOver';\n\nimport styles from './styles.module.scss';\n\nexport enum PopMenuVariant {\n onWhite = 'on-white',\n onGray = 'on-gray',\n onBlueberry = 'on-blueberry',\n}\n\nexport enum PopMenuLabelPosition {\n right = 'right',\n left = 'left',\n}\n\nexport interface PopMenuProps {\n /** Content shown inside PopOver. Can only be a LinkList */\n children: React.ReactElement<LinkListProps>;\n /** Adds custom classes to the popover element. */\n popOverClassName?: string;\n /** Adds custom classes to the element. */\n popMenuClassName?: string;\n /** Changes responsive design for the trigger buttons. */\n popMenuVariant?: PopMenuVariant;\n /** Sets the data-testid attribute for the button that opens. */\n openButtonTestId?: string;\n /** Sets the data-testid attribute for the button that closes. */\n closeButtonTestId?: string;\n /** Sets the data-testid attribute for the popover. */\n popOverTestId?: string;\n /** Sets the arial-label attribute for the openButton. */\n openButtonAriaLabel?: string;\n /** Sets the arial-label attribute for the closeButton. */\n closeButtonAriaLabel?: string;\n /** Sets the icon on the trigger button. */\n svgIcon?: SvgIcon | IconName;\n /** Optional text next to the trigger button. */\n labelText?: string;\n /** Placement of the label text relative to the trigger button. */\n labelTextPosition?: PopMenuLabelPosition;\n}\n\nexport const PopMenu: React.FC<PopMenuProps> = (props: PopMenuProps) => {\n const triggerButtonRef = useRef<HTMLButtonElement>(null);\n const iconRef = useRef<HTMLDivElement>(null);\n const popOverRef = useRef<HTMLDivElement>(null);\n const outerRef = useRef<HTMLDivElement>(null);\n const [isOpen, setIsOpen] = useState(false);\n const {\n children,\n popOverClassName,\n popMenuClassName,\n openButtonTestId,\n closeButtonTestId,\n popOverTestId,\n popMenuVariant = PopMenuVariant.onWhite,\n openButtonAriaLabel,\n closeButtonAriaLabel,\n svgIcon,\n labelText,\n labelTextPosition = PopMenuLabelPosition.right,\n } = props;\n const buttonClasses = classNames(styles['pop-menu-button'], {\n [styles[`pop-menu-button--${popMenuVariant}`]]: popMenuVariant,\n });\n const breakpoint = useBreakpoint();\n const mobile = breakpoint < breakpoints.md;\n\n useOutsideEvent(outerRef, () => {\n setIsOpen(false);\n });\n\n const { isHovered: triggerButtonIsHovered } = useHover(triggerButtonRef);\n const mobileIconSize = mobile ? IconSize.XSmall : IconSize.Small;\n\n const handleClick = (cb?: () => void): void => {\n setIsOpen(false);\n cb && cb();\n };\n\n const renderChildren = (): React.ReactElement | undefined => {\n if (isComponent<LinkListProps>(children, LinkList)) {\n return (\n <PopOver\n testId={popOverTestId}\n className={classNames(styles['pop-menu__pop-over'], popOverClassName)}\n arrowClassName={styles['pop-menu__pop-over-arrow']}\n controllerRef={iconRef}\n popOverRef={popOverRef}\n >\n {React.Children.map(children, child =>\n React.cloneElement(child, {\n children: React.Children.map(child.props.children, child =>\n isComponent<LinkProps>(child, LinkList.Link)\n ? React.cloneElement(child, {\n onClick: (event: React.MouseEvent<HTMLAnchorElement | HTMLButtonElement>) =>\n handleClick(() => child.props.onClick && child.props.onClick(event)),\n })\n : child\n ),\n })\n )}\n </PopOver>\n );\n }\n };\n\n const toggleOpenOnClick = (e?: React.MouseEvent<HTMLElement, MouseEvent>): void => {\n e && e.stopPropagation();\n setIsOpen(!isOpen);\n };\n\n const iconComponent =\n svgIcon && typeof svgIcon === 'string' ? (\n <LazyIcon iconName={svgIcon} size={IconSize.XSmall} isHovered={triggerButtonIsHovered} />\n ) : (\n svgIcon && <Icon svgIcon={svgIcon} size={IconSize.XSmall} isHovered={triggerButtonIsHovered} />\n );\n\n const openIcon = svgIcon ? (\n iconComponent\n ) : (\n <Icon svgIcon={svgIcon ?? VerticalDots} color={getColor('black')} size={mobileIconSize} isHovered={triggerButtonIsHovered} />\n );\n\n const closeIcon = <Icon svgIcon={X} color={getColor('black')} size={mobileIconSize} isHovered={triggerButtonIsHovered} />;\n\n const triggerButton = (\n <button\n ref={triggerButtonRef}\n data-testid={isOpen ? closeButtonTestId : openButtonTestId}\n className={buttonClasses}\n aria-label={isOpen ? closeButtonAriaLabel : openButtonAriaLabel}\n aria-expanded={isOpen}\n onClick={toggleOpenOnClick}\n type=\"button\"\n >\n {labelText && labelTextPosition == PopMenuLabelPosition.left && <span>{labelText}</span>}\n {<div ref={iconRef}>{isOpen ? closeIcon : openIcon}</div>}\n {labelText && labelTextPosition == PopMenuLabelPosition.right && <span>{labelText}</span>}\n </button>\n );\n\n return (\n <div ref={outerRef} className={classNames(styles['pop-menu-button'], popMenuClassName)} data-analyticsid={AnalyticsId.PopMenu}>\n {triggerButton}\n {isOpen && renderChildren()}\n </div>\n );\n};\n\nexport default PopMenu;\n"],"names":["PopMenuVariant","PopMenuLabelPosition","React","child"],"mappings":"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"}
|
|
@@ -116,14 +116,20 @@ html :focus > .pop-menu-button {
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
li:first-of-type {
|
|
119
|
-
|
|
119
|
+
border-top: none;
|
|
120
|
+
|
|
121
|
+
a,
|
|
122
|
+
button {
|
|
120
123
|
border-top-left-radius: 0.5625rem;
|
|
121
124
|
border-top-right-radius: 0.5625rem;
|
|
122
125
|
}
|
|
123
126
|
}
|
|
124
127
|
|
|
125
128
|
li:last-of-type {
|
|
126
|
-
|
|
129
|
+
border-bottom: none;
|
|
130
|
+
|
|
131
|
+
a,
|
|
132
|
+
button {
|
|
127
133
|
border-bottom-left-radius: 0.5625rem;
|
|
128
134
|
border-bottom-right-radius: 0.5625rem;
|
|
129
135
|
}
|
|
@@ -15,6 +15,7 @@ export interface TriggerProps extends Pick<React.InputHTMLAttributes<HTMLButtonE
|
|
|
15
15
|
/**
|
|
16
16
|
* Controls the icon and color. Default: help.
|
|
17
17
|
*/
|
|
18
|
+
/** @deprecated This will be removed in next major version */
|
|
18
19
|
variant?: TriggerVariant;
|
|
19
20
|
/**
|
|
20
21
|
* Changes the design based on the background the trigger is placed on. Default: onlight.
|