@helsenorge/designsystem-react 8.0.1 → 8.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/CHANGELOG.md +12 -0
- package/components/HorizontalScroll/HorizontalScroll.js +16 -15
- package/components/HorizontalScroll/HorizontalScroll.js.map +1 -1
- package/components/RadioButton/styles.module.scss +1 -1
- package/components/Tabs/TabList/TabItem.d.ts +13 -0
- package/components/Tabs/TabList/TabItem.js +45 -0
- package/components/Tabs/TabList/TabItem.js.map +1 -0
- package/components/Tabs/TabList/TabList.js +23 -50
- package/components/Tabs/TabList/TabList.js.map +1 -1
- package/components/Tabs/Tabs.d.ts +3 -0
- package/components/Tabs/Tabs.js +45 -39
- package/components/Tabs/Tabs.js.map +1 -1
- package/components/Validation/ValidationSummary.js +20 -12
- package/components/Validation/ValidationSummary.js.map +1 -1
- package/hooks/usestopPropagation.d.ts +6 -0
- package/hooks/usestopPropagation.js +15 -0
- package/hooks/usestopPropagation.js.map +1 -0
- package/package.json +1 -1
- package/scss/supernova/styles/colors.css +9 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## [8.0.2](https://github.com/helsenorge/designsystem/branchCompare?baseVersion=GTv8.0.1&targetVersion=GTv8.0.2) (2024-08-22)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
- lightbox uu forbedringer ([8026ee9](https://github.com/helsenorge/designsystem/commit/8026ee9fc1acb94cd1b9e9d12ff1a190beca31d3)), closes
|
|
6
|
+
[#329075](https://github.com/helsenorge/designsystem/issues/329075)
|
|
7
|
+
- radiobutton-scss bygger når designsystem tas i bruk
|
|
8
|
+
([867b0ec](https://github.com/helsenorge/designsystem/commit/867b0ec36002ed16fda4f7e6dae07bad4b805c46)), closes
|
|
9
|
+
[#330427](https://github.com/helsenorge/designsystem/issues/330427)
|
|
10
|
+
|
|
11
|
+
## [8.0.1](https://github.com/helsenorge/designsystem/branchCompare?baseVersion=GTv8.0.0&targetVersion=GTv8.0.1) (2024-08-15)
|
|
12
|
+
|
|
1
13
|
## 8.0.0-beta.6 (2024-08-15)
|
|
2
14
|
|
|
3
15
|
### Features
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import r, { useRef as e } from "react";
|
|
2
2
|
import i from "classnames";
|
|
3
3
|
import { useIsVisible as c } from "../../hooks/useIsVisible.js";
|
|
4
|
-
import { useSize as
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
import { useSize as p } from "../../hooks/useSize.js";
|
|
5
|
+
import { useStopPropagation as g } from "../../hooks/usestopPropagation.js";
|
|
6
|
+
import t from "../HorizontalScroll/styles.module.scss";
|
|
7
|
+
const m = "3px", x = ({ children: d, childWidth: _, testId: h, ...l }) => {
|
|
8
|
+
const o = e(null), a = e(null), s = e(null), u = c(a, 1, { root: o == null ? void 0 : o.current, rootMargin: m }, !0), f = c(s, 1, { root: o == null ? void 0 : o.current, rootMargin: m }, !0), { width: v = 0 } = p(o) || {}, z = _ > v, b = i(t.horizontalscroll__viewport, z && t["horizontalscroll__viewport--overflow"]), n = l["aria-label"] || l["aria-labelledby"];
|
|
9
|
+
return g(o, ["touchstart", "touchmove"]), /* @__PURE__ */ r.createElement("div", { className: t.horizontalscroll, "data-testid": h }, /* @__PURE__ */ r.createElement(
|
|
9
10
|
"div",
|
|
10
11
|
{
|
|
11
12
|
className: b,
|
|
12
|
-
ref:
|
|
13
|
+
ref: o,
|
|
13
14
|
tabIndex: n ? 0 : void 0,
|
|
14
15
|
role: n ? "region" : void 0,
|
|
15
16
|
...l
|
|
@@ -18,9 +19,9 @@ const d = "3px", O = ({ children: m, childWidth: _, testId: f, ...l }) => {
|
|
|
18
19
|
"div",
|
|
19
20
|
{
|
|
20
21
|
className: i(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
!
|
|
22
|
+
t.horizontalscroll__indicator,
|
|
23
|
+
t["horizontalscroll__indicator--left"],
|
|
24
|
+
!u && t["horizontalscroll__indicator--visible"]
|
|
24
25
|
)
|
|
25
26
|
}
|
|
26
27
|
),
|
|
@@ -28,19 +29,19 @@ const d = "3px", O = ({ children: m, childWidth: _, testId: f, ...l }) => {
|
|
|
28
29
|
"div",
|
|
29
30
|
{
|
|
30
31
|
className: i(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
!
|
|
32
|
+
t.horizontalscroll__indicator,
|
|
33
|
+
t["horizontalscroll__indicator--right"],
|
|
34
|
+
!f && t["horizontalscroll__indicator--visible"]
|
|
34
35
|
)
|
|
35
36
|
}
|
|
36
37
|
),
|
|
37
38
|
/* @__PURE__ */ r.createElement("div", { ref: a }),
|
|
38
|
-
|
|
39
|
+
d,
|
|
39
40
|
/* @__PURE__ */ r.createElement("div", { ref: s })
|
|
40
41
|
));
|
|
41
42
|
};
|
|
42
43
|
export {
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
x as HorizontalScroll,
|
|
45
|
+
x as default
|
|
45
46
|
};
|
|
46
47
|
//# sourceMappingURL=HorizontalScroll.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HorizontalScroll.js","sources":["../../../src/components/HorizontalScroll/HorizontalScroll.tsx"],"sourcesContent":["import React, { useRef } from 'react';\n\nimport classNames from 'classnames';\n\nimport { useIsVisible } from '../../hooks/useIsVisible';\nimport { useSize } from '../../hooks/useSize';\nimport { AriaLabelAttributes } from '../../utils/accessibility';\n\nimport styles from './styles.module.scss';\n\n// Scrolle-indikator vises/skjules når det er x px igjen til venstre eller høyre side\nconst ROOT_MARGIN_OFFSET = '3px';\n\ninterface HorizontalScrollProps {\n children?: React.ReactNode;\n /**\n * Bredden på elementet som potensielt vil scrolle horisontalt i px\n */\n childWidth: number;\n /** Sets the data-testid attribute. */\n testId?: string;\n}\n\nexport const HorizontalScroll: React.FC<HorizontalScrollProps & AriaLabelAttributes> = ({ children, childWidth, testId, ...rest }) => {\n const viewportRef = useRef<HTMLDivElement>(null);\n const leftRef = useRef<HTMLDivElement>(null);\n const rightRef = useRef<HTMLDivElement>(null);\n const leftIsVisible = useIsVisible(leftRef, 1, { root: viewportRef?.current, rootMargin: ROOT_MARGIN_OFFSET }, true);\n const rightIsVisible = useIsVisible(rightRef, 1, { root: viewportRef?.current, rootMargin: ROOT_MARGIN_OFFSET }, true);\n const { width: viewPortWidth = 0 } = useSize(viewportRef) || {};\n\n const isOverflowing = childWidth > viewPortWidth;\n const viewportClasses = classNames(styles.horizontalscroll__viewport, isOverflowing && styles['horizontalscroll__viewport--overflow']);\n const hasAriaAttributes = rest['aria-label'] || rest['aria-labelledby'];\n\n return (\n <div className={styles.horizontalscroll} data-testid={testId}>\n {/* viewport-diven må ta tabIndex for å løse et annet UU-problem, at div med overflow: scroll må kunne navigeres med keyboard. */}\n {/* Enten aria-label eller aria-labelledbyid må settes */}\n <div\n className={viewportClasses}\n ref={viewportRef}\n tabIndex={hasAriaAttributes ? 0 : undefined}\n role={hasAriaAttributes ? 'region' : undefined}\n {...rest}\n >\n <div\n className={classNames(\n styles.horizontalscroll__indicator,\n styles['horizontalscroll__indicator--left'],\n !leftIsVisible && styles['horizontalscroll__indicator--visible']\n )}\n />\n <div\n className={classNames(\n styles.horizontalscroll__indicator,\n styles['horizontalscroll__indicator--right'],\n !rightIsVisible && styles['horizontalscroll__indicator--visible']\n )}\n />\n <div ref={leftRef} />\n {children}\n <div ref={rightRef} />\n </div>\n </div>\n );\n};\n\nexport default HorizontalScroll;\n"],"names":["ROOT_MARGIN_OFFSET","HorizontalScroll","children","childWidth","testId","rest","viewportRef","useRef","leftRef","rightRef","leftIsVisible","useIsVisible","rightIsVisible","viewPortWidth","useSize","isOverflowing","viewportClasses","classNames","styles","hasAriaAttributes","React"],"mappings":"
|
|
1
|
+
{"version":3,"file":"HorizontalScroll.js","sources":["../../../src/components/HorizontalScroll/HorizontalScroll.tsx"],"sourcesContent":["import React, { useRef } from 'react';\n\nimport classNames from 'classnames';\n\nimport { useIsVisible } from '../../hooks/useIsVisible';\nimport { useSize } from '../../hooks/useSize';\nimport { useStopPropagation } from '../../hooks/usestopPropagation';\nimport { AriaLabelAttributes } from '../../utils/accessibility';\n\nimport styles from './styles.module.scss';\n\n// Scrolle-indikator vises/skjules når det er x px igjen til venstre eller høyre side\nconst ROOT_MARGIN_OFFSET = '3px';\n\ninterface HorizontalScrollProps {\n children?: React.ReactNode;\n /**\n * Bredden på elementet som potensielt vil scrolle horisontalt i px\n */\n childWidth: number;\n /** Sets the data-testid attribute. */\n testId?: string;\n}\n\nexport const HorizontalScroll: React.FC<HorizontalScrollProps & AriaLabelAttributes> = ({ children, childWidth, testId, ...rest }) => {\n const viewportRef = useRef<HTMLDivElement>(null);\n const leftRef = useRef<HTMLDivElement>(null);\n const rightRef = useRef<HTMLDivElement>(null);\n const leftIsVisible = useIsVisible(leftRef, 1, { root: viewportRef?.current, rootMargin: ROOT_MARGIN_OFFSET }, true);\n const rightIsVisible = useIsVisible(rightRef, 1, { root: viewportRef?.current, rootMargin: ROOT_MARGIN_OFFSET }, true);\n const { width: viewPortWidth = 0 } = useSize(viewportRef) || {};\n\n const isOverflowing = childWidth > viewPortWidth;\n const viewportClasses = classNames(styles.horizontalscroll__viewport, isOverflowing && styles['horizontalscroll__viewport--overflow']);\n const hasAriaAttributes = rest['aria-label'] || rest['aria-labelledby'];\n\n useStopPropagation(viewportRef, ['touchstart', 'touchmove']);\n\n return (\n <div className={styles.horizontalscroll} data-testid={testId}>\n {/* viewport-diven må ta tabIndex for å løse et annet UU-problem, at div med overflow: scroll må kunne navigeres med keyboard. */}\n {/* Enten aria-label eller aria-labelledbyid må settes */}\n <div\n className={viewportClasses}\n ref={viewportRef}\n tabIndex={hasAriaAttributes ? 0 : undefined}\n role={hasAriaAttributes ? 'region' : undefined}\n {...rest}\n >\n <div\n className={classNames(\n styles.horizontalscroll__indicator,\n styles['horizontalscroll__indicator--left'],\n !leftIsVisible && styles['horizontalscroll__indicator--visible']\n )}\n />\n <div\n className={classNames(\n styles.horizontalscroll__indicator,\n styles['horizontalscroll__indicator--right'],\n !rightIsVisible && styles['horizontalscroll__indicator--visible']\n )}\n />\n <div ref={leftRef} />\n {children}\n <div ref={rightRef} />\n </div>\n </div>\n );\n};\n\nexport default HorizontalScroll;\n"],"names":["ROOT_MARGIN_OFFSET","HorizontalScroll","children","childWidth","testId","rest","viewportRef","useRef","leftRef","rightRef","leftIsVisible","useIsVisible","rightIsVisible","viewPortWidth","useSize","isOverflowing","viewportClasses","classNames","styles","hasAriaAttributes","useStopPropagation","React"],"mappings":";;;;;;AAYA,MAAMA,IAAqB,OAYdC,IAA0E,CAAC,EAAE,UAAAC,GAAU,YAAAC,GAAY,QAAAC,GAAQ,GAAGC,QAAW;AAC9H,QAAAC,IAAcC,EAAuB,IAAI,GACzCC,IAAUD,EAAuB,IAAI,GACrCE,IAAWF,EAAuB,IAAI,GACtCG,IAAgBC,EAAaH,GAAS,GAAG,EAAE,MAAMF,KAAA,gBAAAA,EAAa,SAAS,YAAYN,EAAmB,GAAG,EAAI,GAC7GY,IAAiBD,EAAaF,GAAU,GAAG,EAAE,MAAMH,KAAA,gBAAAA,EAAa,SAAS,YAAYN,EAAmB,GAAG,EAAI,GAC/G,EAAE,OAAOa,IAAgB,MAAMC,EAAQR,CAAW,KAAK,IAEvDS,IAAgBZ,IAAaU,GAC7BG,IAAkBC,EAAWC,EAAO,4BAA4BH,KAAiBG,EAAO,sCAAsC,CAAC,GAC/HC,IAAoBd,EAAK,YAAY,KAAKA,EAAK,iBAAiB;AAEtE,SAAAe,EAAmBd,GAAa,CAAC,cAAc,WAAW,CAAC,mCAGxD,OAAI,EAAA,WAAWY,EAAO,kBAAkB,eAAad,EAGpD,GAAAiB,gBAAAA,EAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWL;AAAA,MACX,KAAKV;AAAA,MACL,UAAUa,IAAoB,IAAI;AAAA,MAClC,MAAMA,IAAoB,WAAW;AAAA,MACpC,GAAGd;AAAA,IAAA;AAAA,IAEJgB,gBAAAA,EAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAWJ;AAAA,UACTC,EAAO;AAAA,UACPA,EAAO,mCAAmC;AAAA,UAC1C,CAACR,KAAiBQ,EAAO,sCAAsC;AAAA,QACjE;AAAA,MAAA;AAAA,IACF;AAAA,IACAG,gBAAAA,EAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAWJ;AAAA,UACTC,EAAO;AAAA,UACPA,EAAO,oCAAoC;AAAA,UAC3C,CAACN,KAAkBM,EAAO,sCAAsC;AAAA,QAClE;AAAA,MAAA;AAAA,IACF;AAAA,IACAG,gBAAAA,EAAA,cAAC,OAAI,EAAA,KAAKb,EAAS,CAAA;AAAA,IAClBN;AAAA,IACDmB,gBAAAA,EAAA,cAAC,OAAI,EAAA,KAAKZ,EAAU,CAAA;AAAA,EAAA,CAExB;AAEJ;"}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
$encoded-color: string.slice(meta.inspect($neutral600), 2);
|
|
13
13
|
|
|
14
|
-
background-image: url("data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' fill='none' rx='100' ry='100' stroke='%23
|
|
14
|
+
background-image: url("data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' fill='none' rx='100' ry='100' stroke='%23" + $encoded-color + "' stroke-width='4' stroke-dasharray='0.5, 7' stroke-dashoffset='0' stroke-linecap='square'/%3e%3c/svg%3e");
|
|
15
15
|
border-radius: 100px;
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { TabProps } from '../Tab';
|
|
3
|
+
import { TabsColors } from '../Tabs';
|
|
4
|
+
interface TabItemProps {
|
|
5
|
+
tabProps: TabProps;
|
|
6
|
+
index: number;
|
|
7
|
+
color: TabsColors;
|
|
8
|
+
selectedTab: number;
|
|
9
|
+
tabRefs: React.MutableRefObject<React.RefObject<HTMLButtonElement>[] | null | undefined>;
|
|
10
|
+
onTabListClick: (index: number) => void;
|
|
11
|
+
}
|
|
12
|
+
declare const TabItem: React.FC<TabItemProps>;
|
|
13
|
+
export default TabItem;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import a, { useRef as R, useEffect as E } from "react";
|
|
2
|
+
import T from "classnames";
|
|
3
|
+
import { useIsVisible as y } from "../../../hooks/useIsVisible.js";
|
|
4
|
+
import { palette as i } from "../../../theme/palette.js";
|
|
5
|
+
import { Icon as C } from "../../Icon/Icon.js";
|
|
6
|
+
import { IconSize as f } from "../../../constants.js";
|
|
7
|
+
import { LazyIcon as z } from "../../LazyIcon/LazyIcon.js";
|
|
8
|
+
import l from "../../Tabs/TabList/styles.module.scss";
|
|
9
|
+
const w = (e) => {
|
|
10
|
+
const t = e.index === e.selectedTab, { title: d, onTabClick: o, icon: n, testId: u } = e.tabProps, _ = () => {
|
|
11
|
+
o && o(e.index), e.onTabListClick(e.index), s(e.index);
|
|
12
|
+
}, x = T(l["tab-list__tab"], l[`tab-list__tab--${e.color}`], {
|
|
13
|
+
[l["tab-list__tab--selected"]]: t,
|
|
14
|
+
[l["tab-list__tab--first"]]: e.index == 0
|
|
15
|
+
}), I = e.tabRefs.current && e.tabRefs.current[e.index], s = (k) => {
|
|
16
|
+
var m;
|
|
17
|
+
const c = e.tabRefs.current && e.tabRefs.current[k];
|
|
18
|
+
(m = c == null ? void 0 : c.current) == null || m.scrollIntoView({ behavior: "smooth", inline: "center", block: "nearest" });
|
|
19
|
+
}, r = R(null), b = y(r);
|
|
20
|
+
return E(() => {
|
|
21
|
+
t && b && s(e.index);
|
|
22
|
+
}, [t && b]), /* @__PURE__ */ a.createElement("li", { role: "presentation", ref: r }, /* @__PURE__ */ a.createElement(
|
|
23
|
+
"button",
|
|
24
|
+
{
|
|
25
|
+
role: "tab",
|
|
26
|
+
"aria-selected": t,
|
|
27
|
+
onClick: _,
|
|
28
|
+
className: x,
|
|
29
|
+
"data-testid": u,
|
|
30
|
+
ref: I
|
|
31
|
+
},
|
|
32
|
+
/* @__PURE__ */ a.createElement("span", { className: l["tab-list__tab__title-and-icon"] }, n && (typeof n == "string" ? /* @__PURE__ */ a.createElement(
|
|
33
|
+
z,
|
|
34
|
+
{
|
|
35
|
+
iconName: n,
|
|
36
|
+
size: f.XSmall,
|
|
37
|
+
color: t ? i.black : i.blueberry500
|
|
38
|
+
}
|
|
39
|
+
) : /* @__PURE__ */ a.createElement(C, { svgIcon: n, size: f.XSmall, color: t ? i.black : i.blueberry500 })), d)
|
|
40
|
+
));
|
|
41
|
+
};
|
|
42
|
+
export {
|
|
43
|
+
w as default
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=TabItem.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TabItem.js","sources":["../../../../src/components/Tabs/TabList/TabItem.tsx"],"sourcesContent":["import React, { useEffect, useRef } from 'react';\n\nimport classNames from 'classnames';\n\nimport { useIsVisible } from '../../../hooks/useIsVisible';\nimport { palette } from '../../../theme/palette';\nimport Icon, { IconSize } from '../../Icon';\nimport { IconName } from '../../Icons/IconNames';\nimport LazyIcon from '../../LazyIcon';\nimport { TabProps } from '../Tab';\nimport { TabsColors } from '../Tabs';\n\nimport styles from './styles.module.scss';\n\ninterface TabItemProps {\n tabProps: TabProps;\n index: number;\n color: TabsColors;\n selectedTab: number;\n tabRefs: React.MutableRefObject<React.RefObject<HTMLButtonElement>[] | null | undefined>;\n onTabListClick: (index: number) => void;\n}\n\nconst TabItem: React.FC<TabItemProps> = props => {\n const isSelected = props.index === props.selectedTab;\n const { title, onTabClick, icon, testId } = props.tabProps;\n const handleClick = (): void => {\n onTabClick && onTabClick(props.index);\n props.onTabListClick(props.index);\n scrollToTab(props.index);\n };\n const tabButtonClasses = classNames(styles['tab-list__tab'], styles[`tab-list__tab--${props.color}`], {\n [styles['tab-list__tab--selected']]: isSelected,\n [styles['tab-list__tab--first']]: props.index == 0,\n });\n\n const currentRef = props.tabRefs.current && props.tabRefs.current[props.index];\n\n const scrollToTab = (index: number): void => {\n const currentRef = props.tabRefs.current && props.tabRefs.current[index];\n currentRef?.current?.scrollIntoView({ behavior: 'smooth', inline: 'center', block: 'nearest' });\n };\n\n const itemRef = useRef<HTMLLIElement>(null);\n const isVisible = useIsVisible(itemRef);\n\n useEffect(() => {\n if (isSelected && isVisible) {\n scrollToTab(props.index);\n }\n }, [isSelected && isVisible]);\n\n return (\n <li role=\"presentation\" ref={itemRef}>\n <button\n role=\"tab\"\n aria-selected={isSelected}\n onClick={handleClick}\n className={tabButtonClasses}\n data-testid={testId}\n ref={currentRef as React.RefObject<HTMLButtonElement>}\n >\n <span className={styles['tab-list__tab__title-and-icon']}>\n {icon &&\n (typeof icon === 'string' ? (\n <LazyIcon\n iconName={icon as IconName}\n size={IconSize.XSmall}\n color={isSelected ? palette[`black`] : palette['blueberry500']}\n />\n ) : (\n <Icon svgIcon={icon} size={IconSize.XSmall} color={isSelected ? palette[`black`] : palette['blueberry500']} />\n ))}\n {title}\n </span>\n </button>\n </li>\n );\n};\n\nexport default TabItem;\n"],"names":["TabItem","props","isSelected","title","onTabClick","icon","testId","handleClick","scrollToTab","tabButtonClasses","classNames","styles","currentRef","index","itemRef","useRef","isVisible","useIsVisible","useEffect","React","LazyIcon","IconSize","palette","Icon"],"mappings":";;;;;;;;AAuBA,MAAMA,IAAkC,CAASC,MAAA;AACzC,QAAAC,IAAaD,EAAM,UAAUA,EAAM,aACnC,EAAE,OAAAE,GAAO,YAAAC,GAAY,MAAAC,GAAM,QAAAC,MAAWL,EAAM,UAC5CM,IAAc,MAAY;AAChB,IAAAH,KAAAA,EAAWH,EAAM,KAAK,GAC9BA,EAAA,eAAeA,EAAM,KAAK,GAChCO,EAAYP,EAAM,KAAK;AAAA,EAAA,GAEnBQ,IAAmBC,EAAWC,EAAO,eAAe,GAAGA,EAAO,kBAAkBV,EAAM,KAAK,EAAE,GAAG;AAAA,IACpG,CAACU,EAAO,yBAAyB,CAAC,GAAGT;AAAA,IACrC,CAACS,EAAO,sBAAsB,CAAC,GAAGV,EAAM,SAAS;AAAA,EAAA,CAClD,GAEKW,IAAaX,EAAM,QAAQ,WAAWA,EAAM,QAAQ,QAAQA,EAAM,KAAK,GAEvEO,IAAc,CAACK,MAAwB;;AAC3C,UAAMD,IAAaX,EAAM,QAAQ,WAAWA,EAAM,QAAQ,QAAQY,CAAK;AACvED,KAAAA,IAAAA,KAAAA,gBAAAA,EAAY,YAAZA,QAAAA,EAAqB,eAAe,EAAE,UAAU,UAAU,QAAQ,UAAU,OAAO,UAAA;AAAA,EAAW,GAG1FE,IAAUC,EAAsB,IAAI,GACpCC,IAAYC,EAAaH,CAAO;AAEtC,SAAAI,EAAU,MAAM;AACd,IAAIhB,KAAcc,KAChBR,EAAYP,EAAM,KAAK;AAAA,EACzB,GACC,CAACC,KAAcc,CAAS,CAAC,GAGzBG,gBAAAA,EAAA,cAAA,MAAA,EAAG,MAAK,gBAAe,KAAKL,KAC3BK,gBAAAA,EAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,iBAAejB;AAAA,MACf,SAASK;AAAA,MACT,WAAWE;AAAA,MACX,eAAaH;AAAA,MACb,KAAKM;AAAA,IAAA;AAAA,IAELO,gBAAAA,EAAA,cAAC,UAAK,WAAWR,EAAO,+BAA+B,EACpD,GAAAN,MACE,OAAOA,KAAS,WACfc,gBAAAA,EAAA;AAAA,MAACC;AAAA,MAAA;AAAA,QACC,UAAUf;AAAA,QACV,MAAMgB,EAAS;AAAA,QACf,OAAOnB,IAAaoB,EAAQ,QAAWA,EAAQ;AAAA,MAAc;AAAA,IAAA,IAG9DH,gBAAAA,EAAA,cAAAI,GAAA,EAAK,SAASlB,GAAM,MAAMgB,EAAS,QAAQ,OAAOnB,IAAaoB,EAAQ,QAAWA,EAAQ,aAAc,CAAG,IAE/GnB,CACH;AAAA,EAAA,CAEJ;AAEJ;"}
|
|
@@ -1,55 +1,28 @@
|
|
|
1
|
-
import t, { useRef as
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import { useRovingFocus as
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
[o["tab-list__tab--first"]]: e == 0
|
|
23
|
-
}), $ = r.current && r.current[e], u = (g) => {
|
|
24
|
-
var _;
|
|
25
|
-
const c = r.current && r.current[g];
|
|
26
|
-
(_ = c == null ? void 0 : c.current) == null || _.scrollIntoView({ behavior: "smooth", inline: "center", block: "nearest" });
|
|
27
|
-
};
|
|
28
|
-
return s && R && u(e), /* @__PURE__ */ t.createElement("li", { role: "presentation", key: `${n}` }, /* @__PURE__ */ t.createElement(
|
|
29
|
-
"button",
|
|
30
|
-
{
|
|
31
|
-
role: "tab",
|
|
32
|
-
"aria-selected": s,
|
|
33
|
-
onClick: N,
|
|
34
|
-
className: S,
|
|
35
|
-
key: `${n}`,
|
|
36
|
-
"data-testid": z,
|
|
37
|
-
ref: $
|
|
38
|
-
},
|
|
39
|
-
/* @__PURE__ */ t.createElement("span", { className: o["tab-list__tab__title-and-icon"] }, l && (typeof l == "string" ? /* @__PURE__ */ t.createElement(
|
|
40
|
-
X,
|
|
41
|
-
{
|
|
42
|
-
iconName: l,
|
|
43
|
-
size: y.XSmall,
|
|
44
|
-
color: s ? a.black : a.blueberry500
|
|
45
|
-
}
|
|
46
|
-
) : /* @__PURE__ */ t.createElement(w, { svgIcon: l, size: y.XSmall, color: s ? a.black : a.blueberry500 })), n)
|
|
47
|
-
));
|
|
1
|
+
import t, { useRef as l } from "react";
|
|
2
|
+
import b from "classnames";
|
|
3
|
+
import R from "./TabItem.js";
|
|
4
|
+
import { useRovingFocus as C } from "../../../hooks/useRovingFocus.js";
|
|
5
|
+
import { isComponent as T } from "../../../utils/component.js";
|
|
6
|
+
import d from "../Tab.js";
|
|
7
|
+
import i from "../../Tabs/TabList/styles.module.scss";
|
|
8
|
+
const g = (m) => {
|
|
9
|
+
const { selectedTab: n, onTabListClick: r, children: o, color: p = "white", type: f = "normal" } = m, s = l(null), a = l(t.Children.map(o, () => t.createRef()));
|
|
10
|
+
C(r, a, s, !0);
|
|
11
|
+
const c = b(i["tab-list"], i[`tab-list--${f}`]);
|
|
12
|
+
return /* @__PURE__ */ t.createElement("ul", { className: c, ref: s, role: "tablist", "aria-orientation": "horizontal" }, t.Children.map(o, (e, u) => T(e, d) ? /* @__PURE__ */ t.createElement(
|
|
13
|
+
R,
|
|
14
|
+
{
|
|
15
|
+
tabRefs: a,
|
|
16
|
+
key: e.props.title,
|
|
17
|
+
index: u,
|
|
18
|
+
selectedTab: n,
|
|
19
|
+
onTabListClick: r,
|
|
20
|
+
tabProps: e.props,
|
|
21
|
+
color: p
|
|
48
22
|
}
|
|
49
|
-
|
|
50
|
-
}));
|
|
23
|
+
) : null));
|
|
51
24
|
};
|
|
52
25
|
export {
|
|
53
|
-
|
|
26
|
+
g as default
|
|
54
27
|
};
|
|
55
28
|
//# sourceMappingURL=TabList.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TabList.js","sources":["../../../../src/components/Tabs/TabList/TabList.tsx"],"sourcesContent":["import React, { useRef } from 'react';\n\nimport classNames from 'classnames';\n\nimport
|
|
1
|
+
{"version":3,"file":"TabList.js","sources":["../../../../src/components/Tabs/TabList/TabList.tsx"],"sourcesContent":["import React, { useRef } from 'react';\n\nimport classNames from 'classnames';\n\nimport TabItem from './TabItem';\nimport { useRovingFocus } from '../../../hooks/useRovingFocus';\nimport { isComponent } from '../../../utils/component';\nimport Tab, { TabProps } from '../Tab';\nimport { TabsColors, TabsType } from '../Tabs';\n\nimport styles from './styles.module.scss';\ninterface TabListProps {\n children: React.ReactNode;\n onTabListClick: (index: number) => void;\n selectedTab: number;\n color?: TabsColors;\n type?: TabsType;\n}\n\nconst TabList: React.FC<TabListProps> = props => {\n const { selectedTab, onTabListClick, children, color = 'white', type = 'normal' } = props;\n\n const listRef = useRef<HTMLUListElement>(null);\n\n const tabRefs = useRef(React.Children.map(children, () => React.createRef<HTMLButtonElement>()));\n useRovingFocus(onTabListClick, tabRefs, listRef, true);\n\n const tablistClasses = classNames(styles['tab-list'], styles[`tab-list--${type}`]);\n\n return (\n <ul className={tablistClasses} ref={listRef} role=\"tablist\" aria-orientation=\"horizontal\">\n {React.Children.map(children, (child, index) => {\n if (isComponent<TabProps>(child, Tab)) {\n return (\n <TabItem\n tabRefs={tabRefs}\n key={child.props.title}\n index={index}\n selectedTab={selectedTab}\n onTabListClick={onTabListClick}\n tabProps={child.props}\n color={color}\n />\n );\n }\n return null;\n })}\n </ul>\n );\n};\n\nexport default TabList;\n"],"names":["TabList","props","selectedTab","onTabListClick","children","color","type","listRef","useRef","tabRefs","React","useRovingFocus","tablistClasses","classNames","styles","child","index","isComponent","Tab","TabItem"],"mappings":";;;;;;;AAmBA,MAAMA,IAAkC,CAASC,MAAA;AACzC,QAAA,EAAE,aAAAC,GAAa,gBAAAC,GAAgB,UAAAC,GAAU,OAAAC,IAAQ,SAAS,MAAAC,IAAO,SAAa,IAAAL,GAE9EM,IAAUC,EAAyB,IAAI,GAEvCC,IAAUD,EAAOE,EAAM,SAAS,IAAIN,GAAU,MAAMM,EAAM,UAA8B,CAAA,CAAC;AAChF,EAAAC,EAAAR,GAAgBM,GAASF,GAAS,EAAI;AAE/C,QAAAK,IAAiBC,EAAWC,EAAO,UAAU,GAAGA,EAAO,aAAaR,CAAI,EAAE,CAAC;AAEjF,yCACG,MAAG,EAAA,WAAWM,GAAgB,KAAKL,GAAS,MAAK,WAAU,oBAAiB,aAAA,GAC1EG,EAAM,SAAS,IAAIN,GAAU,CAACW,GAAOC,MAChCC,EAAsBF,GAAOG,CAAG,IAEhCR,gBAAAA,EAAA;AAAA,IAACS;AAAA,IAAA;AAAA,MACC,SAAAV;AAAA,MACA,KAAKM,EAAM,MAAM;AAAA,MACjB,OAAAC;AAAA,MACA,aAAAd;AAAA,MACA,gBAAAC;AAAA,MACA,UAAUY,EAAM;AAAA,MAChB,OAAAV;AAAA,IAAA;AAAA,EAAA,IAIC,IACR,CACH;AAEJ;"}
|
|
@@ -4,6 +4,7 @@ import { PaletteNames } from '../../theme/palette';
|
|
|
4
4
|
export type { TabProps } from './Tab';
|
|
5
5
|
export type TabsColors = Extract<PaletteNames, 'blueberry' | 'neutral' | 'white'>;
|
|
6
6
|
export type TabsType = 'normal' | 'framed';
|
|
7
|
+
export type TabsTouchBehaviour = 'swipe' | 'none';
|
|
7
8
|
export interface TabsProps {
|
|
8
9
|
children?: React.ReactNode;
|
|
9
10
|
/** Controlled state for Tabs component */
|
|
@@ -14,6 +15,8 @@ export interface TabsProps {
|
|
|
14
15
|
color?: TabsColors;
|
|
15
16
|
/** Whether the tab list should be sticky */
|
|
16
17
|
sticky?: boolean;
|
|
18
|
+
/** Determines how Tabs respons to touch events. */
|
|
19
|
+
touchBehaviour?: TabsTouchBehaviour;
|
|
17
20
|
/** Sets the data-testid attribute. */
|
|
18
21
|
testId?: string;
|
|
19
22
|
/** Sets the visual type of the tabs */
|
package/components/Tabs/Tabs.js
CHANGED
|
@@ -1,53 +1,59 @@
|
|
|
1
|
-
import r, { useState as c, useRef as
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import { isMobileUA as z } from "../../utils/mobile.js";
|
|
1
|
+
import r, { useState as c, useRef as E, useEffect as C } from "react";
|
|
2
|
+
import S from "classnames";
|
|
3
|
+
import j from "./Tab.js";
|
|
4
|
+
import q from "./TabList/TabList.js";
|
|
5
|
+
import z from "./TabPanel/TabPanel.js";
|
|
6
|
+
import { isMobileUA as G } from "../../utils/mobile.js";
|
|
8
7
|
import l from "../Tabs/styles.module.scss";
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
const H = 75, J = ({
|
|
9
|
+
activeTab: w,
|
|
10
|
+
children: m,
|
|
11
|
+
className: M,
|
|
12
|
+
color: f = "white",
|
|
13
|
+
sticky: N = !0,
|
|
14
|
+
testId: g,
|
|
15
|
+
type: u = "normal",
|
|
16
|
+
touchBehaviour: L = "swipe"
|
|
17
|
+
}) => {
|
|
18
|
+
const X = w !== void 0, [x, y] = c(0), [d, D] = c(0), [p, P] = c(0), [k, a] = c(0), [U, h] = c(null), R = G(), n = E(null), s = E(null), _ = E(null), T = (t, o) => {
|
|
19
|
+
X || (y(t), t > o ? (a(0), I()) : t < o && (a(0), F()));
|
|
14
20
|
}, F = () => {
|
|
15
|
-
|
|
21
|
+
R && h("right");
|
|
16
22
|
}, I = () => {
|
|
17
|
-
|
|
18
|
-
},
|
|
19
|
-
|
|
23
|
+
R && h("left");
|
|
24
|
+
}, $ = () => {
|
|
25
|
+
h(null);
|
|
26
|
+
}, e = X ? w : x;
|
|
27
|
+
return C(() => {
|
|
20
28
|
const t = (i) => {
|
|
21
|
-
k(i.touches[0].clientX);
|
|
22
|
-
}, o = (i) => {
|
|
23
29
|
D(i.touches[0].clientX);
|
|
30
|
+
}, o = (i) => {
|
|
31
|
+
P(i.touches[0].clientX);
|
|
24
32
|
const b = i.touches[0].clientX - d;
|
|
25
33
|
e === 0 && b > 0 || e === r.Children.count(m) - 1 && b < 0 ? a(0) : a(b);
|
|
26
|
-
},
|
|
27
|
-
Math.abs(
|
|
34
|
+
}, A = () => {
|
|
35
|
+
Math.abs(p - d) >= H && (p > d ? T(Math.max(0, e - 1), e) : T(Math.min(r.Children.count(m) - 1, e + 1), e)), a(0);
|
|
28
36
|
};
|
|
29
|
-
return n.current && (n.current.addEventListener("touchstart", t), n.current.addEventListener("touchmove", o), n.current.addEventListener("touchend",
|
|
30
|
-
n.current && (n.current.removeEventListener("touchstart", t), n.current.removeEventListener("touchmove", o), n.current.removeEventListener("touchend",
|
|
37
|
+
return L === "swipe" && n.current && (n.current.addEventListener("touchstart", t), n.current.addEventListener("touchmove", o), n.current.addEventListener("touchend", A)), () => {
|
|
38
|
+
n.current && (n.current.removeEventListener("touchstart", t), n.current.removeEventListener("touchmove", o), n.current.removeEventListener("touchend", A));
|
|
31
39
|
};
|
|
32
|
-
}, [d,
|
|
40
|
+
}, [L, d, p, e]), C(() => {
|
|
33
41
|
const t = () => {
|
|
34
|
-
|
|
42
|
+
$();
|
|
35
43
|
};
|
|
36
44
|
return s.current && s.current.addEventListener("animationend", t), () => {
|
|
37
45
|
s.current && s.current.removeEventListener("animationend", t);
|
|
38
46
|
};
|
|
39
|
-
}, [])
|
|
40
|
-
const { isOutsideWindow: O } = q(R, n);
|
|
41
|
-
return /* @__PURE__ */ r.createElement("div", { className: M, "data-testid": g }, /* @__PURE__ */ r.createElement(
|
|
47
|
+
}, []), /* @__PURE__ */ r.createElement("div", { className: M, "data-testid": g }, /* @__PURE__ */ r.createElement(
|
|
42
48
|
"div",
|
|
43
49
|
{
|
|
44
|
-
ref:
|
|
45
|
-
className:
|
|
46
|
-
[l["tab-list-wrapper--sticky"]]: N
|
|
50
|
+
ref: _,
|
|
51
|
+
className: S(l["tab-list-wrapper"], {
|
|
52
|
+
[l["tab-list-wrapper--sticky"]]: N
|
|
47
53
|
})
|
|
48
54
|
},
|
|
49
55
|
/* @__PURE__ */ r.createElement(
|
|
50
|
-
|
|
56
|
+
q,
|
|
51
57
|
{
|
|
52
58
|
onTabListClick: (t) => T(t, e),
|
|
53
59
|
selectedTab: e,
|
|
@@ -59,28 +65,28 @@ const B = 75, G = ({ activeTab: L, children: m, className: M, color: f = "white"
|
|
|
59
65
|
/* @__PURE__ */ r.createElement(
|
|
60
66
|
"div",
|
|
61
67
|
{
|
|
62
|
-
className:
|
|
68
|
+
className: S(l["panel-wrapper"], l[`panel-wrapper--${f}`], {
|
|
63
69
|
[l["panel-wrapper--framed"]]: u == "framed"
|
|
64
70
|
})
|
|
65
71
|
}
|
|
66
72
|
)
|
|
67
73
|
), /* @__PURE__ */ r.createElement("div", { ref: n, style: { marginTop: u == "framed" ? "-40px" : "" } }, /* @__PURE__ */ r.createElement(
|
|
68
|
-
|
|
74
|
+
z,
|
|
69
75
|
{
|
|
70
76
|
ref: s,
|
|
71
77
|
color: f,
|
|
72
78
|
type: u,
|
|
73
79
|
isFirst: e == 0,
|
|
74
|
-
translateX:
|
|
80
|
+
translateX: k,
|
|
75
81
|
animate: U
|
|
76
82
|
},
|
|
77
83
|
r.Children.toArray(m)[e]
|
|
78
84
|
)));
|
|
79
|
-
},
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
85
|
+
}, v = J;
|
|
86
|
+
v.displayName = "Tabs";
|
|
87
|
+
v.Tab = j;
|
|
88
|
+
v.Tab.displayName = "Tabs.Tab";
|
|
83
89
|
export {
|
|
84
|
-
|
|
90
|
+
v as default
|
|
85
91
|
};
|
|
86
92
|
//# sourceMappingURL=Tabs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tabs.js","sources":["../../../src/components/Tabs/Tabs.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\n\nimport classNames from 'classnames';\n\nimport Tab from './Tab';\nimport TabList from './TabList';\nimport TabPanel from './TabPanel';\nimport { useSticky } from '../../hooks/useSticky';\nimport { PaletteNames } from '../../theme/palette';\nimport { isMobileUA } from '../../utils/mobile';\n\nimport styles from './styles.module.scss';\n\nexport type { TabProps } from './Tab';\nexport type TabsColors = Extract<PaletteNames, 'blueberry' | 'neutral' | 'white'>;\nexport type TabsType = 'normal' | 'framed';\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 /** Whether the tab list should be sticky */\n sticky?: boolean;\n /** Sets the data-testid attribute. */\n testId?: string;\n /** Sets the visual type of the tabs */\n type?: TabsType;\n}\n\nconst swipeDistanceThreshold = 75;\n\nconst TabsRoot: React.FC<TabsProps> = ({ activeTab, children, className, color = 'white', sticky = true, testId, type = 'normal' }) => {\n const isControlled = activeTab !== undefined;\n const [uncontrolledValue, setUncontrolledValue] = useState(0);\n const [touchStartX, setTouchStartX] = useState(0);\n const [touchEndX, setTouchEndX] = useState(0);\n const [translateX, setTranslateX] = useState(0);\n const [panelAnimation, setPanelAnimation] = useState<'left' | 'right' | null>(null);\n const mobile = isMobileUA();\n const tabsRef = useRef<HTMLDivElement>(null);\n const tabPanelRef = useRef<HTMLDivElement>(null);\n const tabListRef = useRef<HTMLDivElement>(null);\n\n const onValueChange = (newValue: number, oldValue: number): void => {\n if (!isControlled) {\n setUncontrolledValue(newValue);\n if (newValue > oldValue) {\n // make sure that the translateX is reset so the animation does not go outside the screen\n setTranslateX(0);\n onLeftSwipe();\n } else if (newValue < oldValue) {\n // make sure that the translateX is reset so the animation does not go outside the screen\n setTranslateX(0);\n onRightSwipe();\n }\n }\n };\n\n const onRightSwipe = (): void => {\n mobile && setPanelAnimation('right');\n };\n\n const onLeftSwipe = (): void => {\n mobile && setPanelAnimation('left');\n };\n\n const resetAnimation = (): void => {\n setPanelAnimation(null);\n };\n\n const activeTabIndex = isControlled ? activeTab : uncontrolledValue;\n\n useEffect(() => {\n const handleTouchStart = (event: TouchEvent): void => {\n setTouchStartX(event.touches[0].clientX);\n };\n\n const handleTouchMove = (event: TouchEvent): void => {\n setTouchEndX(event.touches[0].clientX);\n const newTranslateX = event.touches[0].clientX - touchStartX;\n\n if (activeTabIndex === 0 && newTranslateX > 0) {\n setTranslateX(0);\n } else if (activeTabIndex === React.Children.count(children) - 1 && newTranslateX < 0) {\n setTranslateX(0);\n } else {\n setTranslateX(newTranslateX);\n }\n };\n\n const handleTouchEnd = (): void => {\n const swipeDistance = Math.abs(touchEndX - touchStartX);\n if (swipeDistance >= swipeDistanceThreshold) {\n if (touchEndX > touchStartX) {\n // User swiped right\n onValueChange(Math.max(0, activeTabIndex - 1), activeTabIndex);\n } else {\n // User swiped left\n onValueChange(Math.min(React.Children.count(children) - 1, activeTabIndex + 1), activeTabIndex);\n }\n }\n setTranslateX(0);\n };\n\n if (tabsRef.current) {\n tabsRef.current.addEventListener('touchstart', handleTouchStart);\n tabsRef.current.addEventListener('touchmove', handleTouchMove);\n tabsRef.current.addEventListener('touchend', handleTouchEnd);\n }\n return () => {\n if (tabsRef.current) {\n tabsRef.current.removeEventListener('touchstart', handleTouchStart);\n tabsRef.current.removeEventListener('touchmove', handleTouchMove);\n tabsRef.current.removeEventListener('touchend', handleTouchEnd);\n }\n };\n }, [touchStartX, touchEndX, activeTabIndex]);\n\n useEffect(() => {\n const handleAnimationEnd = (): void => {\n resetAnimation();\n };\n\n if (tabPanelRef.current) {\n tabPanelRef.current.addEventListener('animationend', handleAnimationEnd);\n }\n\n return () => {\n if (tabPanelRef.current) {\n tabPanelRef.current.removeEventListener('animationend', handleAnimationEnd);\n }\n };\n }, []);\n\n const { isOutsideWindow } = useSticky(tabListRef, tabsRef);\n\n return (\n <div className={className} data-testid={testId}>\n <div\n ref={tabListRef}\n className={classNames(styles['tab-list-wrapper'], {\n [styles['tab-list-wrapper--sticky']]: sticky && isOutsideWindow,\n })}\n >\n <TabList\n onTabListClick={(index: number) => onValueChange(index, activeTabIndex)}\n selectedTab={activeTabIndex}\n color={color}\n type={type}\n >\n {children}\n </TabList>\n <div\n className={classNames(styles['panel-wrapper'], styles[`panel-wrapper--${color}`], {\n [styles['panel-wrapper--framed']]: type == 'framed',\n })}\n ></div>\n </div>\n <div ref={tabsRef} style={{ marginTop: type == 'framed' ? '-40px' : '' }}>\n <TabPanel\n ref={tabPanelRef}\n color={color}\n type={type}\n isFirst={activeTabIndex == 0}\n translateX={translateX}\n animate={panelAnimation}\n >\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":["swipeDistanceThreshold","TabsRoot","activeTab","children","className","color","sticky","testId","type","isControlled","uncontrolledValue","setUncontrolledValue","useState","touchStartX","setTouchStartX","touchEndX","setTouchEndX","translateX","setTranslateX","panelAnimation","setPanelAnimation","mobile","isMobileUA","tabsRef","useRef","tabPanelRef","tabListRef","onValueChange","newValue","oldValue","onLeftSwipe","onRightSwipe","resetAnimation","activeTabIndex","useEffect","handleTouchStart","event","handleTouchMove","newTranslateX","React","handleTouchEnd","handleAnimationEnd","isOutsideWindow","useSticky","classNames","styles","TabList","index","TabPanel","Tabs","Tab"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Tabs.js","sources":["../../../src/components/Tabs/Tabs.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\n\nimport classNames from 'classnames';\n\nimport Tab from './Tab';\nimport TabList from './TabList';\nimport TabPanel from './TabPanel';\nimport { PaletteNames } from '../../theme/palette';\nimport { isMobileUA } from '../../utils/mobile';\n\nimport styles from './styles.module.scss';\n\nexport type { TabProps } from './Tab';\nexport type TabsColors = Extract<PaletteNames, 'blueberry' | 'neutral' | 'white'>;\nexport type TabsType = 'normal' | 'framed';\nexport type TabsTouchBehaviour = 'swipe' | 'none';\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 /** Whether the tab list should be sticky */\n sticky?: boolean;\n /** Determines how Tabs respons to touch events. */\n touchBehaviour?: TabsTouchBehaviour;\n /** Sets the data-testid attribute. */\n testId?: string;\n /** Sets the visual type of the tabs */\n type?: TabsType;\n}\n\nconst swipeDistanceThreshold = 75;\n\nconst TabsRoot: React.FC<TabsProps> = ({\n activeTab,\n children,\n className,\n color = 'white',\n sticky = true,\n testId,\n type = 'normal',\n touchBehaviour = 'swipe',\n}) => {\n const isControlled = activeTab !== undefined;\n const [uncontrolledValue, setUncontrolledValue] = useState(0);\n const [touchStartX, setTouchStartX] = useState(0);\n const [touchEndX, setTouchEndX] = useState(0);\n const [translateX, setTranslateX] = useState(0);\n const [panelAnimation, setPanelAnimation] = useState<'left' | 'right' | null>(null);\n const mobile = isMobileUA();\n const tabsRef = useRef<HTMLDivElement>(null);\n const tabPanelRef = useRef<HTMLDivElement>(null);\n const tabListRef = useRef<HTMLDivElement>(null);\n\n const onValueChange = (newValue: number, oldValue: number): void => {\n if (!isControlled) {\n setUncontrolledValue(newValue);\n if (newValue > oldValue) {\n // make sure that the translateX is reset so the animation does not go outside the screen\n setTranslateX(0);\n onLeftSwipe();\n } else if (newValue < oldValue) {\n // make sure that the translateX is reset so the animation does not go outside the screen\n setTranslateX(0);\n onRightSwipe();\n }\n }\n };\n\n const onRightSwipe = (): void => {\n mobile && setPanelAnimation('right');\n };\n\n const onLeftSwipe = (): void => {\n mobile && setPanelAnimation('left');\n };\n\n const resetAnimation = (): void => {\n setPanelAnimation(null);\n };\n\n const activeTabIndex = isControlled ? activeTab : uncontrolledValue;\n\n useEffect(() => {\n const handleTouchStart = (event: TouchEvent): void => {\n setTouchStartX(event.touches[0].clientX);\n };\n\n const handleTouchMove = (event: TouchEvent): void => {\n setTouchEndX(event.touches[0].clientX);\n const newTranslateX = event.touches[0].clientX - touchStartX;\n\n if (activeTabIndex === 0 && newTranslateX > 0) {\n setTranslateX(0);\n } else if (activeTabIndex === React.Children.count(children) - 1 && newTranslateX < 0) {\n setTranslateX(0);\n } else {\n setTranslateX(newTranslateX);\n }\n };\n\n const handleTouchEnd = (): void => {\n const swipeDistance = Math.abs(touchEndX - touchStartX);\n if (swipeDistance >= swipeDistanceThreshold) {\n if (touchEndX > touchStartX) {\n // User swiped right\n onValueChange(Math.max(0, activeTabIndex - 1), activeTabIndex);\n } else {\n // User swiped left\n onValueChange(Math.min(React.Children.count(children) - 1, activeTabIndex + 1), activeTabIndex);\n }\n }\n setTranslateX(0);\n };\n\n if (touchBehaviour === 'swipe' && tabsRef.current) {\n tabsRef.current.addEventListener('touchstart', handleTouchStart);\n tabsRef.current.addEventListener('touchmove', handleTouchMove);\n tabsRef.current.addEventListener('touchend', handleTouchEnd);\n }\n return () => {\n if (tabsRef.current) {\n tabsRef.current.removeEventListener('touchstart', handleTouchStart);\n tabsRef.current.removeEventListener('touchmove', handleTouchMove);\n tabsRef.current.removeEventListener('touchend', handleTouchEnd);\n }\n };\n }, [touchBehaviour, touchStartX, touchEndX, activeTabIndex]);\n\n useEffect(() => {\n const handleAnimationEnd = (): void => {\n resetAnimation();\n };\n\n if (tabPanelRef.current) {\n tabPanelRef.current.addEventListener('animationend', handleAnimationEnd);\n }\n\n return () => {\n if (tabPanelRef.current) {\n tabPanelRef.current.removeEventListener('animationend', handleAnimationEnd);\n }\n };\n }, []);\n\n return (\n <div className={className} 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, activeTabIndex)}\n selectedTab={activeTabIndex}\n color={color}\n type={type}\n >\n {children}\n </TabList>\n <div\n className={classNames(styles['panel-wrapper'], styles[`panel-wrapper--${color}`], {\n [styles['panel-wrapper--framed']]: type == 'framed',\n })}\n ></div>\n </div>\n <div ref={tabsRef} style={{ marginTop: type == 'framed' ? '-40px' : '' }}>\n <TabPanel\n ref={tabPanelRef}\n color={color}\n type={type}\n isFirst={activeTabIndex == 0}\n translateX={translateX}\n animate={panelAnimation}\n >\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":["swipeDistanceThreshold","TabsRoot","activeTab","children","className","color","sticky","testId","type","touchBehaviour","isControlled","uncontrolledValue","setUncontrolledValue","useState","touchStartX","setTouchStartX","touchEndX","setTouchEndX","translateX","setTranslateX","panelAnimation","setPanelAnimation","mobile","isMobileUA","tabsRef","useRef","tabPanelRef","tabListRef","onValueChange","newValue","oldValue","onLeftSwipe","onRightSwipe","resetAnimation","activeTabIndex","useEffect","handleTouchStart","event","handleTouchMove","newTranslateX","React","handleTouchEnd","handleAnimationEnd","classNames","styles","TabList","index","TabPanel","Tabs","Tab"],"mappings":"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"}
|
|
@@ -1,17 +1,25 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import { useUuid as
|
|
5
|
-
import { Title as
|
|
6
|
-
import
|
|
7
|
-
const
|
|
8
|
-
const { errorTitleHtmlMarkup:
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import e from "react";
|
|
2
|
+
import o from "classnames";
|
|
3
|
+
import n from "./ErrorList.js";
|
|
4
|
+
import { useUuid as s } from "../../hooks/useUuid.js";
|
|
5
|
+
import { Title as c } from "../Title/Title.js";
|
|
6
|
+
import l from "../Validation/styles.module.scss";
|
|
7
|
+
const T = (r) => {
|
|
8
|
+
const { errorTitleHtmlMarkup: i = "h2" } = r, a = s(), t = !!r.errors && Object.entries(r.errors).length > 0, m = o(l.validation__summary, t && l["validation__summary--visible"]);
|
|
9
|
+
return /* @__PURE__ */ e.createElement(
|
|
10
|
+
"div",
|
|
11
|
+
{
|
|
12
|
+
role: "alert",
|
|
13
|
+
"aria-live": "polite",
|
|
14
|
+
"aria-relevant": "all",
|
|
15
|
+
"aria-labelledby": t && r.errorTitle ? a : void 0,
|
|
16
|
+
className: m
|
|
17
|
+
},
|
|
18
|
+
t && /* @__PURE__ */ e.createElement(e.Fragment, null, r.errorTitle && /* @__PURE__ */ e.createElement(c, { appearance: "title4", id: a, htmlMarkup: i, margin: { marginTop: 0, marginBottom: 1 } }, r.errorTitle), /* @__PURE__ */ e.createElement(n, { errors: r.errors })),
|
|
19
|
+
r.children
|
|
11
20
|
);
|
|
12
|
-
return /* @__PURE__ */ r.createElement("div", { role: "alert", "aria-live": "polite", "aria-relevant": "all", "aria-labelledby": t, className: i }, !!e.errors && Object.entries(e.errors).length > 0 && /* @__PURE__ */ r.createElement(r.Fragment, null, /* @__PURE__ */ r.createElement(s, { appearance: "title4", id: t, htmlMarkup: l, margin: { marginTop: 0, marginBottom: 1 } }, e.errorTitle), /* @__PURE__ */ r.createElement(o, { errors: e.errors })), e.children);
|
|
13
21
|
};
|
|
14
22
|
export {
|
|
15
|
-
|
|
23
|
+
T as default
|
|
16
24
|
};
|
|
17
25
|
//# sourceMappingURL=ValidationSummary.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ValidationSummary.js","sources":["../../../src/components/Validation/ValidationSummary.tsx"],"sourcesContent":["import React from 'react';\n\nimport classNames from 'classnames';\n\nimport ErrorList from './ErrorList';\nimport { ValidationErrors } from './types';\nimport { useUuid } from '../../hooks/useUuid';\nimport Title, { TitleTags } from '../Title';\n\nimport styles from './styles.module.scss';\n\ninterface ValidationSummaryProps {\n /** Error summary title */\n errorTitle?: string;\n /** Error list */\n errors?: ValidationErrors;\n /** Markup props for error summary title. Default: h2 */\n errorTitleHtmlMarkup?: TitleTags;\n /** Will be shown last */\n children?: React.ReactNode;\n}\n\nconst ValidationSummary: React.FC<ValidationSummaryProps> = props => {\n const { errorTitleHtmlMarkup = 'h2' } = props;\n const titleId = useUuid();\n\n const
|
|
1
|
+
{"version":3,"file":"ValidationSummary.js","sources":["../../../src/components/Validation/ValidationSummary.tsx"],"sourcesContent":["import React from 'react';\n\nimport classNames from 'classnames';\n\nimport ErrorList from './ErrorList';\nimport { ValidationErrors } from './types';\nimport { useUuid } from '../../hooks/useUuid';\nimport Title, { TitleTags } from '../Title';\n\nimport styles from './styles.module.scss';\n\ninterface ValidationSummaryProps {\n /** Error summary title */\n errorTitle?: string;\n /** Error list */\n errors?: ValidationErrors;\n /** Markup props for error summary title. Default: h2 */\n errorTitleHtmlMarkup?: TitleTags;\n /** Will be shown last */\n children?: React.ReactNode;\n}\n\nconst ValidationSummary: React.FC<ValidationSummaryProps> = props => {\n const { errorTitleHtmlMarkup = 'h2' } = props;\n const titleId = useUuid();\n\n const hasErrors = !!props.errors && Object.entries(props.errors).length > 0;\n\n const summaryClasses = classNames(styles['validation__summary'], hasErrors && styles['validation__summary--visible']);\n\n return (\n <div\n role={'alert'}\n aria-live={'polite'}\n aria-relevant={'all'}\n aria-labelledby={hasErrors && props.errorTitle ? titleId : undefined}\n className={summaryClasses}\n >\n {hasErrors && (\n <>\n {props.errorTitle && (\n <Title appearance=\"title4\" id={titleId} htmlMarkup={errorTitleHtmlMarkup} margin={{ marginTop: 0, marginBottom: 1 }}>\n {props.errorTitle}\n </Title>\n )}\n <ErrorList errors={props.errors!} />\n </>\n )}\n {props.children}\n </div>\n );\n};\n\nexport default ValidationSummary;\n"],"names":["ValidationSummary","props","errorTitleHtmlMarkup","titleId","useUuid","hasErrors","summaryClasses","classNames","styles","React","Title","ErrorList"],"mappings":";;;;;;AAsBA,MAAMA,IAAsD,CAASC,MAAA;AAC7D,QAAA,EAAE,sBAAAC,IAAuB,KAAS,IAAAD,GAClCE,IAAUC,KAEVC,IAAY,CAAC,CAACJ,EAAM,UAAU,OAAO,QAAQA,EAAM,MAAM,EAAE,SAAS,GAEpEK,IAAiBC,EAAWC,EAAO,qBAAwBH,KAAaG,EAAO,8BAA8B,CAAC;AAGlH,SAAAC,gBAAAA,EAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAM;AAAA,MACN,aAAW;AAAA,MACX,iBAAe;AAAA,MACf,mBAAiBJ,KAAaJ,EAAM,aAAaE,IAAU;AAAA,MAC3D,WAAWG;AAAA,IAAA;AAAA,IAEVD,KAEII,gBAAAA,EAAA,cAAAA,EAAA,UAAA,MAAAR,EAAM,cACLQ,gBAAAA,EAAA,cAACC,GAAM,EAAA,YAAW,UAAS,IAAIP,GAAS,YAAYD,GAAsB,QAAQ,EAAE,WAAW,GAAG,cAAc,EAAE,EAAA,GAC/GD,EAAM,UACT,GAEFQ,gBAAAA,EAAA,cAACE,GAAU,EAAA,QAAQV,EAAM,OAAA,CAAS,CACpC;AAAA,IAEDA,EAAM;AAAA,EAAA;AAGb;"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useEffect as a } from "react";
|
|
2
|
+
const p = (t, r) => {
|
|
3
|
+
const e = (o) => o.stopPropagation();
|
|
4
|
+
a(() => (r.forEach((o) => {
|
|
5
|
+
var n;
|
|
6
|
+
return (n = t == null ? void 0 : t.current) == null ? void 0 : n.addEventListener(o, e);
|
|
7
|
+
}), () => r.forEach((o) => {
|
|
8
|
+
var n;
|
|
9
|
+
return (n = t.current) == null ? void 0 : n.removeEventListener(o, e);
|
|
10
|
+
})), [t]);
|
|
11
|
+
};
|
|
12
|
+
export {
|
|
13
|
+
p as useStopPropagation
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=usestopPropagation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usestopPropagation.js","sources":["../../src/hooks/usestopPropagation.ts"],"sourcesContent":["import { useEffect } from 'react';\n\n/**\n * Stopp eventer fra å boble opp videre i DOMen\n * @param ref Element som skal overvåkes\n * @param events Navn på eventer som ikke skal boble opp\n */\nexport const useStopPropagation = (ref: React.RefObject<HTMLElement>, events: string[]) => {\n const handleEvent = (e: Event): void => e.stopPropagation();\n\n useEffect(() => {\n events.forEach(name => ref?.current?.addEventListener(name, handleEvent));\n\n return (): void => events.forEach(name => ref.current?.removeEventListener(name, handleEvent));\n }, [ref]);\n};\n"],"names":["useStopPropagation","ref","events","handleEvent","e","useEffect","name","_a"],"mappings":";AAOa,MAAAA,IAAqB,CAACC,GAAmCC,MAAqB;AACzF,QAAMC,IAAc,CAACC,MAAmBA,EAAE,gBAAgB;AAE1D,EAAAC,EAAU,OACRH,EAAO,QAAQ,CAAQI;;AAAA,YAAAC,IAAAN,KAAA,gBAAAA,EAAK,YAAL,gBAAAM,EAAc,iBAAiBD,GAAMH;AAAA,GAAY,GAEjE,MAAYD,EAAO,QAAQ,CAAAI,MAAQ;;AAAA,YAAAC,IAAAN,EAAI,YAAJ,gBAAAM,EAAa,oBAAoBD,GAAMH;AAAA,GAAY,IAC5F,CAACF,CAAG,CAAC;AACV;"}
|
package/package.json
CHANGED
|
@@ -159,7 +159,7 @@
|
|
|
159
159
|
--color-action-background-transparent-ondark-hover: #00000026;
|
|
160
160
|
|
|
161
161
|
/* Hoverfarge for bakgrunn på interaktive elementer - onDark selected */
|
|
162
|
-
--color-action-background-transparent-ondark-hoverselected: #
|
|
162
|
+
--color-action-background-transparent-ondark-hoverselected: #000000bf;
|
|
163
163
|
--color-base-background-dark-neutral: #2b2c2b;
|
|
164
164
|
|
|
165
165
|
/* Placeholdertext in input- and textarea-controls */
|
|
@@ -170,4 +170,12 @@
|
|
|
170
170
|
/* Subtle border for Blueberry 50 background */
|
|
171
171
|
--color-base-border-blueberry: #afdae3;
|
|
172
172
|
--color-base-border-cherry: #eec0a5;
|
|
173
|
+
|
|
174
|
+
/* In a few cases where coloured text is required to stress the semantics of an information notification text */
|
|
175
|
+
--color-notification-text-info: #08667c;
|
|
176
|
+
--color-notification-text-warning: #916500;
|
|
177
|
+
|
|
178
|
+
/* In a few cases where coloured text is required to stress the semantics of an error notification text */
|
|
179
|
+
--color-notification-text-error: #a31f0e;
|
|
180
|
+
--color-notification-text-success: #078141;
|
|
173
181
|
}
|