@helsenorge/designsystem-react 11.7.0 → 11.8.0-beta.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 CHANGED
@@ -1,3 +1,17 @@
1
+ ## 11.8.0-beta.0 (2025-08-28)
2
+
3
+
4
+ ### Features
5
+
6
+ * **formgroup:** flyttet ref og tabindex til errorwrapper p tag ([0ff1c3b](https://github.com/helsenorge/designsystem/commit/0ff1c3bdc942c220060d3065c7a561a556058141))
7
+
8
+ ## [11.7.1](https://github.com/helsenorge/designsystem/branchCompare?baseVersion=GTv11.7.0&targetVersion=GTv11.7.1) (2025-08-25)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **useBreakpoint:** oppdaterer breakpoint etter første render ([545999e](https://github.com/helsenorge/designsystem/commit/545999e0741ab9e4ce1ecbc7e993e7aef68b6394)), closes [#348789](https://github.com/helsenorge/designsystem/issues/348789)
14
+
1
15
  ## [11.7.0](https://github.com/helsenorge/designsystem/branchCompare?baseVersion=GTv11.6.0&targetVersion=GTv11.7.0) (2025-08-13)
2
16
 
3
17
 
package/ErrorWrapper.js CHANGED
@@ -4,7 +4,7 @@ import styles from "./components/ErrorWrapper/styles.module.scss";
4
4
  const ErrorWrapper = (props) => {
5
5
  const errorWrapperClasses = classNames(props.errorText && styles[`error-wrapper--with-error`], props.className);
6
6
  return /* @__PURE__ */ jsxs("div", { className: errorWrapperClasses, "data-testid": props.testId, children: [
7
- props.errorText && /* @__PURE__ */ jsx("p", { className: styles["error-wrapper__errors"], id: props.errorTextId, children: props.errorText }),
7
+ props.errorText && /* @__PURE__ */ jsx("p", { className: styles["error-wrapper__errors"], id: props.errorTextId, ref: props.errorMessageRef, tabIndex: -1, children: props.errorText }),
8
8
  props.children
9
9
  ] });
10
10
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ErrorWrapper.js","sources":["../src/components/ErrorWrapper/ErrorWrapper.tsx"],"sourcesContent":["import React from 'react';\n\nimport cn from 'classnames';\n\nimport styles from './styles.module.scss';\n\nexport interface ErrorWrapperClassNameProps {\n errorWrapperClassName?: string;\n}\n\nexport interface ErrorWrapperProps {\n /** Form component */\n children?: React.ReactNode;\n /** Error message */\n errorText?: string;\n /** Error text id */\n errorTextId?: string;\n /** Adds custom classes to the element. */\n className?: string;\n /** Sets the data-testid attribute. */\n testId?: string;\n}\n\nexport const ErrorWrapper: React.FC<ErrorWrapperProps> = props => {\n const errorWrapperClasses = cn(props.errorText && styles[`error-wrapper--with-error`], props.className);\n\n return (\n <div className={errorWrapperClasses} data-testid={props.testId}>\n {props.errorText && (\n <p className={styles['error-wrapper__errors']} id={props.errorTextId}>\n {props.errorText}\n </p>\n )}\n {props.children}\n </div>\n );\n};\n\nexport default ErrorWrapper;\n"],"names":["cn"],"mappings":";;;AAuBO,MAAM,eAA4C,CAAS,UAAA;AAC1D,QAAA,sBAAsBA,WAAG,MAAM,aAAa,OAAO,2BAA2B,GAAG,MAAM,SAAS;AAEtG,8BACG,OAAI,EAAA,WAAW,qBAAqB,eAAa,MAAM,QACrD,UAAA;AAAA,IAAM,MAAA,aACJ,oBAAA,KAAA,EAAE,WAAW,OAAO,uBAAuB,GAAG,IAAI,MAAM,aACtD,UAAA,MAAM,UACT,CAAA;AAAA,IAED,MAAM;AAAA,EAAA,GACT;AAEJ;"}
1
+ {"version":3,"file":"ErrorWrapper.js","sources":["../src/components/ErrorWrapper/ErrorWrapper.tsx"],"sourcesContent":["import React from 'react';\n\nimport cn from 'classnames';\n\nimport styles from './styles.module.scss';\n\nexport interface ErrorWrapperClassNameProps {\n errorWrapperClassName?: string;\n}\n\nexport interface ErrorWrapperProps {\n /** Form component */\n children?: React.ReactNode;\n /** Error message */\n errorText?: string;\n /** Error text id */\n errorTextId?: string;\n /** Adds custom classes to the element. */\n className?: string;\n /** Adds a ref to the error message p tag */\n errorMessageRef?: React.ForwardedRef<HTMLDivElement>;\n /** Sets the data-testid attribute. */\n testId?: string;\n}\n\nexport const ErrorWrapper: React.FC<ErrorWrapperProps> = props => {\n const errorWrapperClasses = cn(props.errorText && styles[`error-wrapper--with-error`], props.className);\n\n return (\n <div className={errorWrapperClasses} data-testid={props.testId}>\n {props.errorText && (\n <p className={styles['error-wrapper__errors']} id={props.errorTextId} ref={props.errorMessageRef} tabIndex={-1}>\n {props.errorText}\n </p>\n )}\n {props.children}\n </div>\n );\n};\n\nexport default ErrorWrapper;\n"],"names":["cn"],"mappings":";;;AAyBO,MAAM,eAA4C,CAAS,UAAA;AAC1D,QAAA,sBAAsBA,WAAG,MAAM,aAAa,OAAO,2BAA2B,GAAG,MAAM,SAAS;AAEtG,8BACG,OAAI,EAAA,WAAW,qBAAqB,eAAa,MAAM,QACrD,UAAA;AAAA,IAAA,MAAM,aACJ,oBAAA,KAAA,EAAE,WAAW,OAAO,uBAAuB,GAAG,IAAI,MAAM,aAAa,KAAK,MAAM,iBAAiB,UAAU,IACzG,gBAAM,WACT;AAAA,IAED,MAAM;AAAA,EAAA,GACT;AAEJ;"}
package/FormGroup.js CHANGED
@@ -122,9 +122,19 @@ const FormGroup = React__default.forwardRef((props, ref) => {
122
122
  ] })
123
123
  ] });
124
124
  };
125
- return /* @__PURE__ */ jsxs("div", { "data-testid": props.testId, "data-analyticsid": AnalyticsId.FormGroup, className: formGroupWrapperClasses, ref, tabIndex: -1, children: [
125
+ return /* @__PURE__ */ jsxs("div", { "data-testid": props.testId, "data-analyticsid": AnalyticsId.FormGroup, className: formGroupWrapperClasses, children: [
126
126
  props.title && /* @__PURE__ */ jsx(Title, { className: titleClasses, htmlMarkup: "h4", appearance: "title4", margin: { marginTop: 0, marginBottom: error ? 1 : 2 }, children: props.title }),
127
- renderError ? /* @__PURE__ */ jsx(ErrorWrapper, { className: errorWrapperClassName, errorText: error, testId: errorWrapperTestId, errorTextId: errorTextUuid, children: formGroupContent() }) : formGroupContent()
127
+ renderError ? /* @__PURE__ */ jsx(
128
+ ErrorWrapper,
129
+ {
130
+ className: errorWrapperClassName,
131
+ errorText: error,
132
+ testId: errorWrapperTestId,
133
+ errorTextId: errorTextUuid,
134
+ errorMessageRef: ref,
135
+ children: formGroupContent()
136
+ }
137
+ ) : formGroupContent()
128
138
  ] });
129
139
  });
130
140
  FormGroup.displayName = "FormGroup";
package/FormGroup.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"FormGroup.js","sources":["../src/components/FormGroup/FormGroup.tsx"],"sourcesContent":["import React, { useState } from 'react';\n\nimport classNames from 'classnames';\n\nimport { AnalyticsId, FormOnColor, FormSize } from '../../constants';\nimport { useUuid } from '../../hooks/useUuid';\nimport { isComponent } from '../../utils/component';\nimport Checkbox, { CheckboxProps } from '../Checkbox/Checkbox';\nimport ErrorWrapper from '../ErrorWrapper';\nimport FormLayout, { FormLayoutProps } from '../FormLayout';\nimport Input, { InputProps } from '../Input/Input';\nimport RadioButton, { RadioButtonProps, getRadioLabelClasses } from '../RadioButton/RadioButton';\nimport Select, { SelectProps } from '../Select';\nimport Slider, { SliderProps } from '../Slider';\nimport Textarea, { TextareaProps } from '../Textarea';\nimport Title from '../Title';\n\nimport formGroupStyles from './styles.module.scss';\n\nexport type FormGroupTags = 'fieldset' | 'div';\n\nexport interface FormGroupProps {\n /** Can be used as a replacement text for legend in cases where the group title already exists externally */\n ariaLabelledBy?: string;\n /** title for the the fieldset */\n title?: string;\n /** text placed in the legend tag of the fieldset */\n legend?: string;\n /** Items in the FormGroup component */\n children?: React.ReactNode;\n /** Adds custom classes to the element. */\n className?: string;\n /** Adds custom classes to the errorWrapper. */\n errorWrapperClassName?: string;\n /** Adds custom classes to the fieldset element. */\n fieldsetClassName?: string;\n /** Changes the visuals of the formgroup */\n onColor?: keyof typeof FormOnColor;\n /** Changes the visuals of the formgroup */\n size?: keyof typeof FormSize;\n /** Error message */\n error?: string;\n /** Error text id */\n errorTextId?: string;\n /** Sets the data-testid attribute. */\n testId?: string;\n /** Sets the data-testid attribute for the error-wrapper. */\n errorWrapperTestId?: string;\n /** Unique name for the child input element */\n name?: string;\n /** Unique name for the fieldset */\n fieldsetName?: string;\n /** Sets div instead of fieldset tag */\n htmlMarkup?: FormGroupTags;\n /** Renders the error component (Default: true) */\n renderError?: boolean;\n}\n\nexport const FormGroup = React.forwardRef((props: FormGroupProps, ref: React.ForwardedRef<HTMLDivElement>) => {\n const {\n ariaLabelledBy,\n className,\n fieldsetClassName,\n onColor = FormOnColor.onwhite,\n size = FormSize.medium,\n error,\n errorTextId,\n name,\n htmlMarkup = 'fieldset',\n renderError = true,\n errorWrapperClassName,\n errorWrapperTestId,\n } = props;\n const [checkedRadioId, setCheckedRadioId] = useState<string>();\n const radioGroupId = useUuid();\n const errorTextUuid = useUuid(errorTextId);\n const onDark = onColor === FormOnColor.ondark;\n const isLarge = size === FormSize.large;\n const formGroupWrapperClasses = classNames(formGroupStyles['form-group-wrapper'], className);\n const titleClasses = classNames({\n [formGroupStyles['form-group-wrapper__title--on-dark']]: onDark && !error,\n });\n\n const legendClasses = classNames(formGroupStyles['field-set__legend'], {\n [formGroupStyles['field-set__legend--on-dark']]: onDark && !error,\n });\n\n const fieldsetClasses = classNames(formGroupStyles['field-set'], fieldsetClassName);\n\n const mapFormComponent = (child: React.ReactNode, index: number): React.ReactNode => {\n if (isComponent<FormLayoutProps>(child, FormLayout)) {\n return React.cloneElement(child, {\n size,\n mapHelper: mapFormComponent,\n });\n } else if (isComponent<FormGroupProps>(child, FormGroup)) {\n return React.cloneElement(child, {\n onColor,\n size,\n error,\n renderError: false,\n errorTextId: errorTextUuid,\n });\n } else if (isComponent<CheckboxProps>(child, Checkbox)) {\n return React.cloneElement(child, {\n name: name ?? child.props.name,\n onColor,\n size,\n error: !!error,\n errorTextId: errorTextUuid,\n });\n } else if (isComponent<RadioButtonProps>(child, RadioButton)) {\n const radioId = typeof child.props.inputId === 'undefined' ? radioGroupId + index : child.props.inputId;\n return React.cloneElement(child, {\n inputId: radioId,\n name: name ?? child.props.name,\n onColor,\n size,\n onChange: (event: React.ChangeEvent<HTMLInputElement>) => {\n setCheckedRadioId(event.target.id);\n child.props.onChange && child.props.onChange(event);\n },\n error: !!error,\n errorTextId: errorTextUuid,\n labelClassNames: getRadioLabelClasses(radioId, onColor as FormOnColor, isLarge, checkedRadioId),\n });\n } else if (isComponent<InputProps>(child, Input)) {\n return React.cloneElement(child, {\n name: name ?? child.props.name,\n onColor,\n size,\n error: !!error,\n errorTextId: errorTextUuid,\n });\n } else if (isComponent<TextareaProps>(child, Textarea)) {\n return React.cloneElement(child, {\n name: name ?? child.props.name,\n onColor,\n error: !!error,\n errorTextId: errorTextUuid,\n });\n } else if (isComponent<SelectProps>(child, Select)) {\n return React.cloneElement(child, {\n name: name ?? child.props.name,\n onColor,\n error: !!error,\n errorTextId: errorTextUuid,\n });\n } else if (isComponent<SliderProps>(child, Slider)) {\n return React.cloneElement(child, {\n name: name ?? child.props.name,\n error: !!error,\n errorTextId: errorTextUuid,\n });\n }\n return child;\n };\n\n const formGroupContent = (): React.ReactNode => {\n return (\n <div>\n {htmlMarkup === 'div' && (\n <div className={fieldsetClasses}>\n {props.legend && <h5 className={legendClasses}>{props.legend}</h5>}\n {React.Children.map(props.children, mapFormComponent)}\n </div>\n )}\n {htmlMarkup === 'fieldset' && (\n <fieldset aria-labelledby={ariaLabelledBy} name={props.fieldsetName} className={fieldsetClasses}>\n {props.legend && <legend className={legendClasses}>{props.legend}</legend>}\n {React.Children.map(props.children, mapFormComponent)}\n </fieldset>\n )}\n </div>\n );\n };\n\n return (\n <div data-testid={props.testId} data-analyticsid={AnalyticsId.FormGroup} className={formGroupWrapperClasses} ref={ref} tabIndex={-1}>\n {props.title && (\n <Title className={titleClasses} htmlMarkup={'h4'} appearance={'title4'} margin={{ marginTop: 0, marginBottom: error ? 1 : 2 }}>\n {props.title}\n </Title>\n )}\n {renderError ? (\n <ErrorWrapper className={errorWrapperClassName} errorText={error} testId={errorWrapperTestId} errorTextId={errorTextUuid}>\n {formGroupContent()}\n </ErrorWrapper>\n ) : (\n formGroupContent()\n )}\n </div>\n );\n});\n\nFormGroup.displayName = 'FormGroup';\n\nexport default FormGroup;\n"],"names":["React"],"mappings":"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"}
1
+ {"version":3,"file":"FormGroup.js","sources":["../src/components/FormGroup/FormGroup.tsx"],"sourcesContent":["import React, { useState } from 'react';\n\nimport classNames from 'classnames';\n\nimport { AnalyticsId, FormOnColor, FormSize } from '../../constants';\nimport { useUuid } from '../../hooks/useUuid';\nimport { isComponent } from '../../utils/component';\nimport Checkbox, { CheckboxProps } from '../Checkbox/Checkbox';\nimport ErrorWrapper from '../ErrorWrapper';\nimport FormLayout, { FormLayoutProps } from '../FormLayout';\nimport Input, { InputProps } from '../Input/Input';\nimport RadioButton, { RadioButtonProps, getRadioLabelClasses } from '../RadioButton/RadioButton';\nimport Select, { SelectProps } from '../Select';\nimport Slider, { SliderProps } from '../Slider';\nimport Textarea, { TextareaProps } from '../Textarea';\nimport Title from '../Title';\n\nimport formGroupStyles from './styles.module.scss';\n\nexport type FormGroupTags = 'fieldset' | 'div';\n\nexport interface FormGroupProps {\n /** Can be used as a replacement text for legend in cases where the group title already exists externally */\n ariaLabelledBy?: string;\n /** title for the the fieldset */\n title?: string;\n /** text placed in the legend tag of the fieldset */\n legend?: string;\n /** Items in the FormGroup component */\n children?: React.ReactNode;\n /** Adds custom classes to the element. */\n className?: string;\n /** Adds custom classes to the errorWrapper. */\n errorWrapperClassName?: string;\n /** Adds custom classes to the fieldset element. */\n fieldsetClassName?: string;\n /** Changes the visuals of the formgroup */\n onColor?: keyof typeof FormOnColor;\n /** Changes the visuals of the formgroup */\n size?: keyof typeof FormSize;\n /** Error message */\n error?: string;\n /** Error text id */\n errorTextId?: string;\n /** Sets the data-testid attribute. */\n testId?: string;\n /** Sets the data-testid attribute for the error-wrapper. */\n errorWrapperTestId?: string;\n /** Unique name for the child input element */\n name?: string;\n /** Unique name for the fieldset */\n fieldsetName?: string;\n /** Sets div instead of fieldset tag */\n htmlMarkup?: FormGroupTags;\n /** Renders the error component (Default: true) */\n renderError?: boolean;\n}\n\nexport const FormGroup = React.forwardRef((props: FormGroupProps, ref: React.ForwardedRef<HTMLDivElement>) => {\n const {\n ariaLabelledBy,\n className,\n fieldsetClassName,\n onColor = FormOnColor.onwhite,\n size = FormSize.medium,\n error,\n errorTextId,\n name,\n htmlMarkup = 'fieldset',\n renderError = true,\n errorWrapperClassName,\n errorWrapperTestId,\n } = props;\n const [checkedRadioId, setCheckedRadioId] = useState<string>();\n const radioGroupId = useUuid();\n const errorTextUuid = useUuid(errorTextId);\n const onDark = onColor === FormOnColor.ondark;\n const isLarge = size === FormSize.large;\n const formGroupWrapperClasses = classNames(formGroupStyles['form-group-wrapper'], className);\n const titleClasses = classNames({\n [formGroupStyles['form-group-wrapper__title--on-dark']]: onDark && !error,\n });\n\n const legendClasses = classNames(formGroupStyles['field-set__legend'], {\n [formGroupStyles['field-set__legend--on-dark']]: onDark && !error,\n });\n\n const fieldsetClasses = classNames(formGroupStyles['field-set'], fieldsetClassName);\n\n const mapFormComponent = (child: React.ReactNode, index: number): React.ReactNode => {\n if (isComponent<FormLayoutProps>(child, FormLayout)) {\n return React.cloneElement(child, {\n size,\n mapHelper: mapFormComponent,\n });\n } else if (isComponent<FormGroupProps>(child, FormGroup)) {\n return React.cloneElement(child, {\n onColor,\n size,\n error,\n renderError: false,\n errorTextId: errorTextUuid,\n });\n } else if (isComponent<CheckboxProps>(child, Checkbox)) {\n return React.cloneElement(child, {\n name: name ?? child.props.name,\n onColor,\n size,\n error: !!error,\n errorTextId: errorTextUuid,\n });\n } else if (isComponent<RadioButtonProps>(child, RadioButton)) {\n const radioId = typeof child.props.inputId === 'undefined' ? radioGroupId + index : child.props.inputId;\n return React.cloneElement(child, {\n inputId: radioId,\n name: name ?? child.props.name,\n onColor,\n size,\n onChange: (event: React.ChangeEvent<HTMLInputElement>) => {\n setCheckedRadioId(event.target.id);\n child.props.onChange && child.props.onChange(event);\n },\n error: !!error,\n errorTextId: errorTextUuid,\n labelClassNames: getRadioLabelClasses(radioId, onColor as FormOnColor, isLarge, checkedRadioId),\n });\n } else if (isComponent<InputProps>(child, Input)) {\n return React.cloneElement(child, {\n name: name ?? child.props.name,\n onColor,\n size,\n error: !!error,\n errorTextId: errorTextUuid,\n });\n } else if (isComponent<TextareaProps>(child, Textarea)) {\n return React.cloneElement(child, {\n name: name ?? child.props.name,\n onColor,\n error: !!error,\n errorTextId: errorTextUuid,\n });\n } else if (isComponent<SelectProps>(child, Select)) {\n return React.cloneElement(child, {\n name: name ?? child.props.name,\n onColor,\n error: !!error,\n errorTextId: errorTextUuid,\n });\n } else if (isComponent<SliderProps>(child, Slider)) {\n return React.cloneElement(child, {\n name: name ?? child.props.name,\n error: !!error,\n errorTextId: errorTextUuid,\n });\n }\n return child;\n };\n\n const formGroupContent = (): React.ReactNode => {\n return (\n <div>\n {htmlMarkup === 'div' && (\n <div className={fieldsetClasses}>\n {props.legend && <h5 className={legendClasses}>{props.legend}</h5>}\n {React.Children.map(props.children, mapFormComponent)}\n </div>\n )}\n {htmlMarkup === 'fieldset' && (\n <fieldset aria-labelledby={ariaLabelledBy} name={props.fieldsetName} className={fieldsetClasses}>\n {props.legend && <legend className={legendClasses}>{props.legend}</legend>}\n {React.Children.map(props.children, mapFormComponent)}\n </fieldset>\n )}\n </div>\n );\n };\n\n return (\n <div data-testid={props.testId} data-analyticsid={AnalyticsId.FormGroup} className={formGroupWrapperClasses}>\n {props.title && (\n <Title className={titleClasses} htmlMarkup={'h4'} appearance={'title4'} margin={{ marginTop: 0, marginBottom: error ? 1 : 2 }}>\n {props.title}\n </Title>\n )}\n {renderError ? (\n <ErrorWrapper\n className={errorWrapperClassName}\n errorText={error}\n testId={errorWrapperTestId}\n errorTextId={errorTextUuid}\n errorMessageRef={ref}\n >\n {formGroupContent()}\n </ErrorWrapper>\n ) : (\n formGroupContent()\n )}\n </div>\n );\n});\n\nFormGroup.displayName = 'FormGroup';\n\nexport default FormGroup;\n"],"names":["React"],"mappings":"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"}
@@ -11,6 +11,8 @@ export interface ErrorWrapperProps {
11
11
  errorTextId?: string;
12
12
  /** Adds custom classes to the element. */
13
13
  className?: string;
14
+ /** Adds a ref to the error message p tag */
15
+ errorMessageRef?: React.ForwardedRef<HTMLDivElement>;
14
16
  /** Sets the data-testid attribute. */
15
17
  testId?: string;
16
18
  }
@@ -20,9 +20,10 @@ function getCurrentBreakpoint() {
20
20
  return (matched == null ? void 0 : matched.breakpoint) ?? Breakpoint.xxs;
21
21
  }
22
22
  const useBreakpoint = () => {
23
- const [breakpoint, setBreakpoint] = useState(
24
- typeof window.matchMedia !== "undefined" ? getCurrentBreakpoint() : Breakpoint.xxs
25
- );
23
+ const [breakpoint, setBreakpoint] = useState(Breakpoint.xxs);
24
+ useEffect(() => {
25
+ setBreakpoint(getCurrentBreakpoint());
26
+ }, []);
26
27
  useEffect(() => {
27
28
  const mediaQueryList = Object.values(screen).map((mediaQuery) => {
28
29
  const mq = window.matchMedia(mediaQuery);
@@ -1 +1 @@
1
- {"version":3,"file":"useBreakpoint.js","sources":["../../src/hooks/useBreakpoint.ts"],"sourcesContent":["import { useState, useEffect } from 'react';\n\nimport { breakpoints, screen } from '../theme/grid';\n\nexport enum Breakpoint {\n xxs = breakpoints.xxs,\n xs = breakpoints.xs,\n sm = breakpoints.sm,\n md = breakpoints.md,\n lg = breakpoints.lg,\n xl = breakpoints.xl,\n}\n\nfunction getCurrentBreakpoint(): Breakpoint {\n // We read from largest -> smallest or vice versa\n // so that the first match is the \"highest\" one that applies\n const mediaQueryList = Object.entries(screen)\n .reverse() // e.g. check xl, lg, md, etc. in descending order\n .map(([size, mediaQuery]) => {\n return {\n breakpoint: Breakpoint[size as keyof typeof Breakpoint],\n mq: window.matchMedia(mediaQuery),\n };\n });\n\n const matched = mediaQueryList.find(entry => entry.mq.matches);\n return matched?.breakpoint ?? Breakpoint.xxs;\n}\n\nexport const useBreakpoint = (): Breakpoint => {\n const [breakpoint, setBreakpoint] = useState<Breakpoint>(\n typeof window.matchMedia !== 'undefined' ? getCurrentBreakpoint() : Breakpoint.xxs\n );\n\n useEffect(() => {\n const mediaQueryList = Object.values(screen).map(mediaQuery => {\n const mq = window.matchMedia(mediaQuery);\n // iOS <=13 har ikke støtte for addEventListener/removeEventListener på MediaQueryList,\n // men har støtte for addListener\n const handler = (): void => {\n setBreakpoint(getCurrentBreakpoint());\n };\n\n if (mq.addEventListener) {\n mq.addEventListener('change', handler);\n } else if (mq.addListener) {\n mq.addListener(handler);\n }\n return { mq, handler };\n });\n\n return (): void => {\n mediaQueryList.forEach(({ mq, handler }) => {\n if (mq.removeEventListener) {\n mq.removeEventListener('change', handler);\n } else if (mq.removeListener) {\n mq.removeListener(handler);\n }\n });\n };\n }, []);\n\n return breakpoint;\n};\n"],"names":["Breakpoint"],"mappings":";;AAIY,IAAA,cAAL,CAAKA,gBAAL;AACLA,cAAAA,YAAA,KAAM,IAAA,YAAY,GAAlB,IAAA;AACAA,cAAAA,YAAA,IAAK,IAAA,YAAY,EAAjB,IAAA;AACAA,cAAAA,YAAA,IAAK,IAAA,YAAY,EAAjB,IAAA;AACAA,cAAAA,YAAA,IAAK,IAAA,YAAY,EAAjB,IAAA;AACAA,cAAAA,YAAA,IAAK,IAAA,YAAY,EAAjB,IAAA;AACAA,cAAAA,YAAA,IAAK,IAAA,YAAY,EAAjB,IAAA;AANUA,SAAAA;AAAA,GAAA,cAAA,CAAA,CAAA;AASZ,SAAS,uBAAmC;AAG1C,QAAM,iBAAiB,OAAO,QAAQ,MAAM,EACzC,QACA,EAAA,IAAI,CAAC,CAAC,MAAM,UAAU,MAAM;AACpB,WAAA;AAAA,MACL,YAAY,WAAW,IAA+B;AAAA,MACtD,IAAI,OAAO,WAAW,UAAU;AAAA,IAClC;AAAA,EAAA,CACD;AAEH,QAAM,UAAU,eAAe,KAAK,CAAS,UAAA,MAAM,GAAG,OAAO;AACtD,UAAA,mCAAS,eAAc,WAAW;AAC3C;AAEO,MAAM,gBAAgB,MAAkB;AACvC,QAAA,CAAC,YAAY,aAAa,IAAI;AAAA,IAClC,OAAO,OAAO,eAAe,cAAc,qBAAA,IAAyB,WAAW;AAAA,EACjF;AAEA,YAAU,MAAM;AACd,UAAM,iBAAiB,OAAO,OAAO,MAAM,EAAE,IAAI,CAAc,eAAA;AACvD,YAAA,KAAK,OAAO,WAAW,UAAU;AAGvC,YAAM,UAAU,MAAY;AAC1B,sBAAc,sBAAsB;AAAA,MACtC;AAEA,UAAI,GAAG,kBAAkB;AACpB,WAAA,iBAAiB,UAAU,OAAO;AAAA,MAAA,WAC5B,GAAG,aAAa;AACzB,WAAG,YAAY,OAAO;AAAA,MAAA;AAEjB,aAAA,EAAE,IAAI,QAAQ;AAAA,IAAA,CACtB;AAED,WAAO,MAAY;AACjB,qBAAe,QAAQ,CAAC,EAAE,IAAI,cAAc;AAC1C,YAAI,GAAG,qBAAqB;AACvB,aAAA,oBAAoB,UAAU,OAAO;AAAA,QAAA,WAC/B,GAAG,gBAAgB;AAC5B,aAAG,eAAe,OAAO;AAAA,QAAA;AAAA,MAC3B,CACD;AAAA,IACH;AAAA,EACF,GAAG,EAAE;AAEE,SAAA;AACT;"}
1
+ {"version":3,"file":"useBreakpoint.js","sources":["../../src/hooks/useBreakpoint.ts"],"sourcesContent":["import { useState, useEffect } from 'react';\n\nimport { breakpoints, screen } from '../theme/grid';\n\nexport enum Breakpoint {\n xxs = breakpoints.xxs,\n xs = breakpoints.xs,\n sm = breakpoints.sm,\n md = breakpoints.md,\n lg = breakpoints.lg,\n xl = breakpoints.xl,\n}\n\nfunction getCurrentBreakpoint(): Breakpoint {\n // We read from largest -> smallest or vice versa\n // so that the first match is the \"highest\" one that applies\n const mediaQueryList = Object.entries(screen)\n .reverse() // e.g. check xl, lg, md, etc. in descending order\n .map(([size, mediaQuery]) => {\n return {\n breakpoint: Breakpoint[size as keyof typeof Breakpoint],\n mq: window.matchMedia(mediaQuery),\n };\n });\n\n const matched = mediaQueryList.find(entry => entry.mq.matches);\n return matched?.breakpoint ?? Breakpoint.xxs;\n}\n\nexport const useBreakpoint = (): Breakpoint => {\n const [breakpoint, setBreakpoint] = useState<Breakpoint>(Breakpoint.xxs);\n\n useEffect(() => {\n // Oppdater breakpoint i useEffect for å støtte server side rendering\n setBreakpoint(getCurrentBreakpoint());\n }, []);\n\n useEffect(() => {\n const mediaQueryList = Object.values(screen).map(mediaQuery => {\n const mq = window.matchMedia(mediaQuery);\n // iOS <=13 har ikke støtte for addEventListener/removeEventListener på MediaQueryList,\n // men har støtte for addListener\n const handler = (): void => {\n setBreakpoint(getCurrentBreakpoint());\n };\n\n if (mq.addEventListener) {\n mq.addEventListener('change', handler);\n } else if (mq.addListener) {\n mq.addListener(handler);\n }\n return { mq, handler };\n });\n\n return (): void => {\n mediaQueryList.forEach(({ mq, handler }) => {\n if (mq.removeEventListener) {\n mq.removeEventListener('change', handler);\n } else if (mq.removeListener) {\n mq.removeListener(handler);\n }\n });\n };\n }, []);\n\n return breakpoint;\n};\n"],"names":["Breakpoint"],"mappings":";;AAIY,IAAA,cAAL,CAAKA,gBAAL;AACLA,cAAAA,YAAA,KAAM,IAAA,YAAY,GAAlB,IAAA;AACAA,cAAAA,YAAA,IAAK,IAAA,YAAY,EAAjB,IAAA;AACAA,cAAAA,YAAA,IAAK,IAAA,YAAY,EAAjB,IAAA;AACAA,cAAAA,YAAA,IAAK,IAAA,YAAY,EAAjB,IAAA;AACAA,cAAAA,YAAA,IAAK,IAAA,YAAY,EAAjB,IAAA;AACAA,cAAAA,YAAA,IAAK,IAAA,YAAY,EAAjB,IAAA;AANUA,SAAAA;AAAA,GAAA,cAAA,CAAA,CAAA;AASZ,SAAS,uBAAmC;AAG1C,QAAM,iBAAiB,OAAO,QAAQ,MAAM,EACzC,QACA,EAAA,IAAI,CAAC,CAAC,MAAM,UAAU,MAAM;AACpB,WAAA;AAAA,MACL,YAAY,WAAW,IAA+B;AAAA,MACtD,IAAI,OAAO,WAAW,UAAU;AAAA,IAClC;AAAA,EAAA,CACD;AAEH,QAAM,UAAU,eAAe,KAAK,CAAS,UAAA,MAAM,GAAG,OAAO;AACtD,UAAA,mCAAS,eAAc,WAAW;AAC3C;AAEO,MAAM,gBAAgB,MAAkB;AAC7C,QAAM,CAAC,YAAY,aAAa,IAAI,SAAqB,WAAW,GAAG;AAEvE,YAAU,MAAM;AAEd,kBAAc,sBAAsB;AAAA,EACtC,GAAG,EAAE;AAEL,YAAU,MAAM;AACd,UAAM,iBAAiB,OAAO,OAAO,MAAM,EAAE,IAAI,CAAc,eAAA;AACvD,YAAA,KAAK,OAAO,WAAW,UAAU;AAGvC,YAAM,UAAU,MAAY;AAC1B,sBAAc,sBAAsB;AAAA,MACtC;AAEA,UAAI,GAAG,kBAAkB;AACpB,WAAA,iBAAiB,UAAU,OAAO;AAAA,MAAA,WAC5B,GAAG,aAAa;AACzB,WAAG,YAAY,OAAO;AAAA,MAAA;AAEjB,aAAA,EAAE,IAAI,QAAQ;AAAA,IAAA,CACtB;AAED,WAAO,MAAY;AACjB,qBAAe,QAAQ,CAAC,EAAE,IAAI,cAAc;AAC1C,YAAI,GAAG,qBAAqB;AACvB,aAAA,oBAAoB,UAAU,OAAO;AAAA,QAAA,WAC/B,GAAG,gBAAgB;AAC5B,aAAG,eAAe,OAAO;AAAA,QAAA;AAAA,MAC3B,CACD;AAAA,IACH;AAAA,EACF,GAAG,EAAE;AAEE,SAAA;AACT;"}
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "url": "git+https://github.com/helsenorge/designsystem.git"
8
8
  },
9
9
  "homepage": "https://helsenorge.design",
10
- "version": "11.7.0",
10
+ "version": "11.8.0-beta.0",
11
11
  "author": "Helsenorge",
12
12
  "license": "MIT",
13
13
  "dependencies": {