@telia/teddy 0.0.73 → 0.0.75

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.
@@ -6,8 +6,19 @@ const clsx = require("clsx");
6
6
  const components_card_card = require("./card.cjs");
7
7
  const components_carousel_carouselRoot = require("../carousel/carousel-root.cjs");
8
8
  const components_colorDot_index = require("../color-dot/index.cjs");
9
+ const utils_breakpointToNumber = require("../../utils/breakpointToNumber.cjs");
10
+ const tokens_breakpoint_variables = require("../../tokens/breakpoint/variables.cjs");
9
11
  const ImageSlider = React.forwardRef(
10
- ({ variants, className, children, onClickNext, onClickPrev, onChangeVariant = () => void 0 }, forwardRef) => {
12
+ ({
13
+ settings,
14
+ variants,
15
+ className,
16
+ children,
17
+ onClick = () => void 0,
18
+ onClickNext,
19
+ onClickPrev,
20
+ onChangeVariant = () => void 0
21
+ }, forwardRef) => {
11
22
  const [selectedSlide, setSelectedSlide] = React.useState(0);
12
23
  const rootCarouselClass = `${components_card_card.rootClassName}__carousel`;
13
24
  const classes = clsx([components_card_card.styles[rootCarouselClass]], className);
@@ -17,6 +28,7 @@ const ImageSlider = React.forwardRef(
17
28
  size: "sm",
18
29
  onClickNext,
19
30
  onClickPrev,
31
+ onClick,
20
32
  settings: {
21
33
  beforeChange: (_currentSlide, nextSlide) => {
22
34
  setSelectedSlide(nextSlide);
@@ -25,7 +37,17 @@ const ImageSlider = React.forwardRef(
25
37
  customPaging: (index) => {
26
38
  const variant = variants[index];
27
39
  return /* @__PURE__ */ jsxRuntime.jsx(components_colorDot_index.ColorDot, { color: variant.color, size: "xs", bordered: true, wide: index === selectedSlide });
28
- }
40
+ },
41
+ swipe: false,
42
+ responsive: [
43
+ {
44
+ breakpoint: utils_breakpointToNumber.breakpointToNumber(tokens_breakpoint_variables.teddyBreakpointMd),
45
+ settings: {
46
+ swipe: true
47
+ }
48
+ }
49
+ ],
50
+ ...settings
29
51
  },
30
52
  children
31
53
  }
@@ -1,4 +1,5 @@
1
1
  import { default as React } from 'react';
2
+ import { Settings } from 'react-slick';
2
3
 
3
4
  export type ImageSliderVariant = {
4
5
  color: string;
@@ -8,6 +9,8 @@ export interface ImageSliderProps {
8
9
  variants: ImageSliderVariant[];
9
10
  children: React.ReactNode;
10
11
  className?: string;
12
+ settings?: Settings;
13
+ onClick?: () => void;
11
14
  onClickNext?: () => void;
12
15
  onClickPrev?: () => void;
13
16
  onChangeVariant?: (variant: ImageSliderVariant) => void;
@@ -4,8 +4,19 @@ import clsx from "clsx";
4
4
  import { s as styles, rootClassName } from "./card.js";
5
5
  import { Carousel } from "../carousel/carousel-root.js";
6
6
  import { ColorDot } from "../color-dot/index.js";
7
+ import { breakpointToNumber } from "../../utils/breakpointToNumber.js";
8
+ import { teddyBreakpointMd } from "../../tokens/breakpoint/variables.js";
7
9
  const ImageSlider = React__default.forwardRef(
8
- ({ variants, className, children, onClickNext, onClickPrev, onChangeVariant = () => void 0 }, forwardRef) => {
10
+ ({
11
+ settings,
12
+ variants,
13
+ className,
14
+ children,
15
+ onClick = () => void 0,
16
+ onClickNext,
17
+ onClickPrev,
18
+ onChangeVariant = () => void 0
19
+ }, forwardRef) => {
9
20
  const [selectedSlide, setSelectedSlide] = useState(0);
10
21
  const rootCarouselClass = `${rootClassName}__carousel`;
11
22
  const classes = clsx([styles[rootCarouselClass]], className);
@@ -15,6 +26,7 @@ const ImageSlider = React__default.forwardRef(
15
26
  size: "sm",
16
27
  onClickNext,
17
28
  onClickPrev,
29
+ onClick,
18
30
  settings: {
19
31
  beforeChange: (_currentSlide, nextSlide) => {
20
32
  setSelectedSlide(nextSlide);
@@ -23,7 +35,17 @@ const ImageSlider = React__default.forwardRef(
23
35
  customPaging: (index) => {
24
36
  const variant = variants[index];
25
37
  return /* @__PURE__ */ jsx(ColorDot, { color: variant.color, size: "xs", bordered: true, wide: index === selectedSlide });
26
- }
38
+ },
39
+ swipe: false,
40
+ responsive: [
41
+ {
42
+ breakpoint: breakpointToNumber(teddyBreakpointMd),
43
+ settings: {
44
+ swipe: true
45
+ }
46
+ }
47
+ ],
48
+ ...settings
27
49
  },
28
50
  children
29
51
  }
@@ -39,6 +39,7 @@ const Carousel = ({
39
39
  className = "",
40
40
  onClickNext,
41
41
  onClickPrev,
42
+ onClick = () => void 0,
42
43
  navigationIcon,
43
44
  settings,
44
45
  size = "lg"
@@ -55,20 +56,6 @@ const Carousel = ({
55
56
  lazyLoad: "ondemand",
56
57
  ...settings
57
58
  };
58
- const [swiped, setSwiped] = React.useState(false);
59
- const handleSwiped = React.useCallback(() => {
60
- setSwiped(true);
61
- }, [setSwiped]);
62
- const handleOnItemClick = React.useCallback(
63
- (e) => {
64
- if (swiped) {
65
- e.stopPropagation();
66
- e.preventDefault();
67
- setSwiped(false);
68
- }
69
- },
70
- [swiped]
71
- );
72
59
  const filteredChildren = React.Children.toArray(children).filter((child) => !!child);
73
60
  const SliderComponent = Slider.default ? Slider.default : Slider;
74
61
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -78,19 +65,8 @@ const Carousel = ({
78
65
  [styles[`${rootClassName}--${size}`]]: size,
79
66
  [className]: className
80
67
  }),
81
- children: /* @__PURE__ */ jsxRuntime.jsx(SliderComponent, { ...computedSettings, onSwipe: handleSwiped, children: React.Children.map(filteredChildren, (child) => {
82
- return /* @__PURE__ */ jsxRuntime.jsx(
83
- "div",
84
- {
85
- onClick: (e) => {
86
- e.stopPropagation();
87
- e.preventDefault();
88
- },
89
- onClickCapture: handleOnItemClick,
90
- className: clsx(styles[`${rootClassName}__item`]),
91
- children: child
92
- }
93
- );
68
+ children: /* @__PURE__ */ jsxRuntime.jsx(SliderComponent, { ...computedSettings, children: React.Children.map(filteredChildren, (child) => {
69
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { onClick, className: clsx(styles[`${rootClassName}__item`]), children: child });
94
70
  }) })
95
71
  }
96
72
  );
@@ -10,6 +10,7 @@ export type CarouselProps = {
10
10
  size?: 'sm' | 'lg';
11
11
  onClickNext?: () => void;
12
12
  onClickPrev?: () => void;
13
+ onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
13
14
  };
14
15
  /** Carousel to show images in. Can be fully customized by utlizing underlying 'settings' props mapped with react-slick */
15
16
  export declare const Carousel: React.FC<CarouselProps>;
@@ -1,5 +1,5 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
- import React__default, { useState, useCallback } from "react";
2
+ import React__default from "react";
3
3
  import clsx from "clsx";
4
4
  import Slider from "react-slick";
5
5
  import "../../assets/sprite.269ba410-teddy.svg";
@@ -37,6 +37,7 @@ const Carousel = ({
37
37
  className = "",
38
38
  onClickNext,
39
39
  onClickPrev,
40
+ onClick = () => void 0,
40
41
  navigationIcon,
41
42
  settings,
42
43
  size = "lg"
@@ -53,20 +54,6 @@ const Carousel = ({
53
54
  lazyLoad: "ondemand",
54
55
  ...settings
55
56
  };
56
- const [swiped, setSwiped] = useState(false);
57
- const handleSwiped = useCallback(() => {
58
- setSwiped(true);
59
- }, [setSwiped]);
60
- const handleOnItemClick = useCallback(
61
- (e) => {
62
- if (swiped) {
63
- e.stopPropagation();
64
- e.preventDefault();
65
- setSwiped(false);
66
- }
67
- },
68
- [swiped]
69
- );
70
57
  const filteredChildren = React__default.Children.toArray(children).filter((child) => !!child);
71
58
  const SliderComponent = Slider.default ? Slider.default : Slider;
72
59
  return /* @__PURE__ */ jsx(
@@ -76,19 +63,8 @@ const Carousel = ({
76
63
  [styles[`${rootClassName}--${size}`]]: size,
77
64
  [className]: className
78
65
  }),
79
- children: /* @__PURE__ */ jsx(SliderComponent, { ...computedSettings, onSwipe: handleSwiped, children: React__default.Children.map(filteredChildren, (child) => {
80
- return /* @__PURE__ */ jsx(
81
- "div",
82
- {
83
- onClick: (e) => {
84
- e.stopPropagation();
85
- e.preventDefault();
86
- },
87
- onClickCapture: handleOnItemClick,
88
- className: clsx(styles[`${rootClassName}__item`]),
89
- children: child
90
- }
91
- );
66
+ children: /* @__PURE__ */ jsx(SliderComponent, { ...computedSettings, children: React__default.Children.map(filteredChildren, (child) => {
67
+ return /* @__PURE__ */ jsx("div", { onClick, className: clsx(styles[`${rootClassName}__item`]), children: child });
92
68
  }) })
93
69
  }
94
70
  );
@@ -209,6 +209,33 @@ const PRIVATE_LINKS = {
209
209
  }
210
210
  ]
211
211
  },
212
+ {
213
+ name: "Trygghet",
214
+ link: "/trygghet/",
215
+ appKey: APP_KEYS["open-pages"],
216
+ links: [
217
+ {
218
+ name: "Tjenester",
219
+ link: "/trygghet/tjenester/",
220
+ appKey: APP_KEYS["open-pages"]
221
+ },
222
+ {
223
+ name: "Svindel",
224
+ link: "/trygghet/svindel/",
225
+ appKey: APP_KEYS["open-pages"]
226
+ },
227
+ {
228
+ name: "Aktuelt",
229
+ link: "/trygghet/aktuelt/",
230
+ appKey: APP_KEYS["open-pages"]
231
+ },
232
+ {
233
+ name: "Hjelp Trygghet",
234
+ link: "/trygghet/hjelp/",
235
+ appKey: APP_KEYS["open-pages"]
236
+ }
237
+ ]
238
+ },
212
239
  {
213
240
  name: "Hjelp",
214
241
  link: "/hjelp/",
@@ -229,6 +256,11 @@ const PRIVATE_LINKS = {
229
256
  link: "/internett/hjelp/",
230
257
  appKey: APP_KEYS["open-pages"]
231
258
  },
259
+ {
260
+ name: "Hjelp Trygghet",
261
+ link: "/trygghet/hjelp/",
262
+ appKey: APP_KEYS["open-pages"]
263
+ },
232
264
  {
233
265
  name: "Faktura",
234
266
  link: "/hjelp/faktura/",
@@ -285,12 +317,12 @@ const BUSINESS_LINKS = {
285
317
  {
286
318
  name: "Nettbutikk",
287
319
  link: "/bedrift/mobilabonnement/",
288
- appKey: APP_KEYS["web-shop"],
320
+ appKey: APP_KEYS["open-pages"],
289
321
  links: [
290
322
  {
291
323
  name: "Mobilabonnement",
292
324
  link: "/bedrift/mobilabonnement/",
293
- appKey: APP_KEYS["web-shop"]
325
+ appKey: APP_KEYS["open-pages"]
294
326
  },
295
327
  {
296
328
  name: "Mobiltelefoner",
@@ -231,6 +231,27 @@ export declare const PRIVATE_LINKS: {
231
231
  readonly link: "/internett/hjelp/";
232
232
  readonly appKey: "open-pages";
233
233
  }];
234
+ }, {
235
+ readonly name: "Trygghet";
236
+ readonly link: "/trygghet/";
237
+ readonly appKey: "open-pages";
238
+ readonly links: [{
239
+ readonly name: "Tjenester";
240
+ readonly link: "/trygghet/tjenester/";
241
+ readonly appKey: "open-pages";
242
+ }, {
243
+ readonly name: "Svindel";
244
+ readonly link: "/trygghet/svindel/";
245
+ readonly appKey: "open-pages";
246
+ }, {
247
+ readonly name: "Aktuelt";
248
+ readonly link: "/trygghet/aktuelt/";
249
+ readonly appKey: "open-pages";
250
+ }, {
251
+ readonly name: "Hjelp Trygghet";
252
+ readonly link: "/trygghet/hjelp/";
253
+ readonly appKey: "open-pages";
254
+ }];
234
255
  }, {
235
256
  readonly name: "Hjelp";
236
257
  readonly link: "/hjelp/";
@@ -247,6 +268,10 @@ export declare const PRIVATE_LINKS: {
247
268
  readonly name: "Hjelp Internett";
248
269
  readonly link: "/internett/hjelp/";
249
270
  readonly appKey: "open-pages";
271
+ }, {
272
+ readonly name: "Hjelp Trygghet";
273
+ readonly link: "/trygghet/hjelp/";
274
+ readonly appKey: "open-pages";
250
275
  }, {
251
276
  readonly name: "Faktura";
252
277
  readonly link: "/hjelp/faktura/";
@@ -289,11 +314,11 @@ export declare const BUSINESS_LINKS: {
289
314
  }, {
290
315
  readonly name: "Nettbutikk";
291
316
  readonly link: "/bedrift/mobilabonnement/";
292
- readonly appKey: "web-shop";
317
+ readonly appKey: "open-pages";
293
318
  readonly links: [{
294
319
  readonly name: "Mobilabonnement";
295
320
  readonly link: "/bedrift/mobilabonnement/";
296
- readonly appKey: "web-shop";
321
+ readonly appKey: "open-pages";
297
322
  }, {
298
323
  readonly name: "Mobiltelefoner";
299
324
  readonly link: "/bedrift/mobiltelefoner/";
@@ -440,6 +465,27 @@ export declare const LINKS: [{
440
465
  readonly link: "/internett/hjelp/";
441
466
  readonly appKey: "open-pages";
442
467
  }];
468
+ }, {
469
+ readonly name: "Trygghet";
470
+ readonly link: "/trygghet/";
471
+ readonly appKey: "open-pages";
472
+ readonly links: [{
473
+ readonly name: "Tjenester";
474
+ readonly link: "/trygghet/tjenester/";
475
+ readonly appKey: "open-pages";
476
+ }, {
477
+ readonly name: "Svindel";
478
+ readonly link: "/trygghet/svindel/";
479
+ readonly appKey: "open-pages";
480
+ }, {
481
+ readonly name: "Aktuelt";
482
+ readonly link: "/trygghet/aktuelt/";
483
+ readonly appKey: "open-pages";
484
+ }, {
485
+ readonly name: "Hjelp Trygghet";
486
+ readonly link: "/trygghet/hjelp/";
487
+ readonly appKey: "open-pages";
488
+ }];
443
489
  }, {
444
490
  readonly name: "Hjelp";
445
491
  readonly link: "/hjelp/";
@@ -456,6 +502,10 @@ export declare const LINKS: [{
456
502
  readonly name: "Hjelp Internett";
457
503
  readonly link: "/internett/hjelp/";
458
504
  readonly appKey: "open-pages";
505
+ }, {
506
+ readonly name: "Hjelp Trygghet";
507
+ readonly link: "/trygghet/hjelp/";
508
+ readonly appKey: "open-pages";
459
509
  }, {
460
510
  readonly name: "Faktura";
461
511
  readonly link: "/hjelp/faktura/";
@@ -497,11 +547,11 @@ export declare const LINKS: [{
497
547
  }, {
498
548
  readonly name: "Nettbutikk";
499
549
  readonly link: "/bedrift/mobilabonnement/";
500
- readonly appKey: "web-shop";
550
+ readonly appKey: "open-pages";
501
551
  readonly links: [{
502
552
  readonly name: "Mobilabonnement";
503
553
  readonly link: "/bedrift/mobilabonnement/";
504
- readonly appKey: "web-shop";
554
+ readonly appKey: "open-pages";
505
555
  }, {
506
556
  readonly name: "Mobiltelefoner";
507
557
  readonly link: "/bedrift/mobiltelefoner/";
@@ -207,6 +207,33 @@ const PRIVATE_LINKS = {
207
207
  }
208
208
  ]
209
209
  },
210
+ {
211
+ name: "Trygghet",
212
+ link: "/trygghet/",
213
+ appKey: APP_KEYS["open-pages"],
214
+ links: [
215
+ {
216
+ name: "Tjenester",
217
+ link: "/trygghet/tjenester/",
218
+ appKey: APP_KEYS["open-pages"]
219
+ },
220
+ {
221
+ name: "Svindel",
222
+ link: "/trygghet/svindel/",
223
+ appKey: APP_KEYS["open-pages"]
224
+ },
225
+ {
226
+ name: "Aktuelt",
227
+ link: "/trygghet/aktuelt/",
228
+ appKey: APP_KEYS["open-pages"]
229
+ },
230
+ {
231
+ name: "Hjelp Trygghet",
232
+ link: "/trygghet/hjelp/",
233
+ appKey: APP_KEYS["open-pages"]
234
+ }
235
+ ]
236
+ },
210
237
  {
211
238
  name: "Hjelp",
212
239
  link: "/hjelp/",
@@ -227,6 +254,11 @@ const PRIVATE_LINKS = {
227
254
  link: "/internett/hjelp/",
228
255
  appKey: APP_KEYS["open-pages"]
229
256
  },
257
+ {
258
+ name: "Hjelp Trygghet",
259
+ link: "/trygghet/hjelp/",
260
+ appKey: APP_KEYS["open-pages"]
261
+ },
230
262
  {
231
263
  name: "Faktura",
232
264
  link: "/hjelp/faktura/",
@@ -283,12 +315,12 @@ const BUSINESS_LINKS = {
283
315
  {
284
316
  name: "Nettbutikk",
285
317
  link: "/bedrift/mobilabonnement/",
286
- appKey: APP_KEYS["web-shop"],
318
+ appKey: APP_KEYS["open-pages"],
287
319
  links: [
288
320
  {
289
321
  name: "Mobilabonnement",
290
322
  link: "/bedrift/mobilabonnement/",
291
- appKey: APP_KEYS["web-shop"]
323
+ appKey: APP_KEYS["open-pages"]
292
324
  },
293
325
  {
294
326
  name: "Mobiltelefoner",
@@ -64,76 +64,77 @@ const Corner = React.forwardRef(
64
64
  }
65
65
  );
66
66
  Corner.displayName = "Corner";
67
+ const directionToAriaLabel = {
68
+ up: "Scroll opp",
69
+ down: "Scroll ned",
70
+ left: "Scroll til venstre",
71
+ right: "Scroll til høyre"
72
+ };
73
+ const directionToIconName = {
74
+ up: "chevron-up",
75
+ down: "chevron-down",
76
+ left: "chevron-left",
77
+ right: "chevron-right"
78
+ };
67
79
  const Button = React.forwardRef(
68
80
  ({ className, hidden, direction = "right", children, ...props }, forwardRef) => {
69
- const context = React.useContext(RootContext);
70
- const isHidden = hidden ?? (direction === "up" && !(context == null ? void 0 : context.hasScrollTop) || direction === "down" && !(context == null ? void 0 : context.hasScrollBottom) || direction === "left" && !(context == null ? void 0 : context.hasScrollLeft) || direction === "right" && !(context == null ? void 0 : context.hasScrollRight));
71
- const classes = clsx(
81
+ const scrollAreaContext = React.useContext(RootContext);
82
+ const shouldBeHidden = hidden ?? (direction === "up" && !(scrollAreaContext == null ? void 0 : scrollAreaContext.hasScrollTop) || direction === "down" && !(scrollAreaContext == null ? void 0 : scrollAreaContext.hasScrollBottom) || direction === "left" && !(scrollAreaContext == null ? void 0 : scrollAreaContext.hasScrollLeft) || direction === "right" && !(scrollAreaContext == null ? void 0 : scrollAreaContext.hasScrollRight));
83
+ const buttonClasses = clsx(
72
84
  styles[`${rootClassName}__button`],
73
85
  {
74
- [styles[`${rootClassName}__button--hidden`]]: isHidden
86
+ [styles[`${rootClassName}__button--hidden`]]: shouldBeHidden
75
87
  },
76
88
  className
77
89
  );
78
- const directionLabels = {
79
- up: "Scroll opp",
80
- down: "Scroll ned",
81
- left: "Scroll til venstre",
82
- right: "Scroll til høyre"
83
- };
84
- const directionIcons = {
85
- up: "chevron-up",
86
- down: "chevron-down",
87
- left: "chevron-left",
88
- right: "chevron-right"
89
- };
90
- const handleClick = utils_composeEventHandlers.composeEventHandlers(props.onClick, (e) => {
91
- if (e.defaultPrevented)
90
+ const handleButtonClick = utils_composeEventHandlers.composeEventHandlers(props.onClick, (event) => {
91
+ if (event.defaultPrevented)
92
92
  return;
93
- const scrollArea = context == null ? void 0 : context.scrollRef;
94
- if (!scrollArea)
93
+ const scrollAreaElement = scrollAreaContext == null ? void 0 : scrollAreaContext.scrollRef;
94
+ if (!scrollAreaElement)
95
95
  return;
96
- const itemNodes = Array.from(scrollArea.querySelectorAll("[data-in-view]"));
97
- const isHorizontal = direction === "left" || direction === "right";
98
- const scrollAxis = isHorizontal ? "left" : "top";
99
- const isBackward = direction === "left" || direction === "up";
100
- const scrollPos = isHorizontal ? scrollArea.scrollLeft : scrollArea.scrollTop;
101
- const scrollAreaSize = isHorizontal ? scrollArea.clientWidth : scrollArea.clientHeight;
102
- const maxScrollPos = isHorizontal ? scrollArea.scrollWidth - scrollAreaSize : scrollArea.scrollHeight - scrollAreaSize;
103
- const buttonSize = isHorizontal ? e.currentTarget.offsetWidth : e.currentTarget.offsetHeight;
104
- const visibleStart = scrollPos + (isBackward ? buttonSize : 0);
105
- const visibleEnd = scrollPos + scrollAreaSize - (!isBackward ? buttonSize : 0);
106
- const getElementBounds = (element) => {
107
- const elementStart = isHorizontal ? element.offsetLeft : element.offsetTop;
108
- const elementEnd = elementStart + (isHorizontal ? element.offsetWidth : element.offsetHeight);
109
- return { elementStart, elementEnd };
96
+ const scrollableItems = Array.from(scrollAreaElement.querySelectorAll("[data-in-view]"));
97
+ const isHorizontalScroll = direction === "left" || direction === "right";
98
+ const scrollProperty = isHorizontalScroll ? "left" : "top";
99
+ const isScrollingBackward = direction === "left" || direction === "up";
100
+ const currentScrollPosition = isHorizontalScroll ? scrollAreaElement.scrollLeft : scrollAreaElement.scrollTop;
101
+ const viewportSize = isHorizontalScroll ? scrollAreaElement.clientWidth : scrollAreaElement.clientHeight;
102
+ const scrollButtonSize = isHorizontalScroll ? event.currentTarget.offsetWidth : event.currentTarget.offsetHeight;
103
+ const visibleAreaStart = currentScrollPosition + (isScrollingBackward ? scrollButtonSize : 0);
104
+ const visibleAreaEnd = currentScrollPosition + viewportSize - (!isScrollingBackward ? scrollButtonSize : 0);
105
+ const getItemBounds = (item) => {
106
+ const itemStart = isHorizontalScroll ? item.offsetLeft : item.offsetTop;
107
+ const itemEnd = itemStart + (isHorizontalScroll ? item.offsetWidth : item.offsetHeight);
108
+ return { itemStart, itemEnd };
110
109
  };
111
- const isElementFullyVisible = (element) => {
112
- const { elementStart, elementEnd } = getElementBounds(element);
113
- return elementStart >= visibleStart && elementEnd <= visibleEnd;
110
+ const isItemFullyVisible = (item) => {
111
+ const { itemStart, itemEnd } = getItemBounds(item);
112
+ return itemStart >= visibleAreaStart && itemEnd <= visibleAreaEnd;
114
113
  };
115
- const inViewIndices = itemNodes.map((node, index) => {
116
- const dataInView = node.getAttribute("data-in-view") === "true";
117
- const fullyVisible = isElementFullyVisible(node);
118
- return dataInView && fullyVisible ? index : -1;
114
+ const fullyVisibleItemIndices = scrollableItems.map((item, index) => {
115
+ const isInView = item.getAttribute("data-in-view") === "true";
116
+ const isFullyVisible = isItemFullyVisible(item);
117
+ return isInView && isFullyVisible ? index : -1;
119
118
  }).filter((index) => index !== -1);
120
- const hasReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
121
- const scrollBehavior = hasReducedMotion ? "auto" : (context == null ? void 0 : context.scrollBehavior) ?? "smooth";
122
- let scrollAmount = scrollPos;
123
- if (inViewIndices.length > 0) {
124
- const currentIndex = isBackward ? inViewIndices[0] : inViewIndices[inViewIndices.length - 1];
125
- const targetIndex = isBackward ? currentIndex > 0 ? currentIndex - 1 : currentIndex : currentIndex < itemNodes.length - 1 ? currentIndex + 1 : currentIndex;
126
- const targetItem = itemNodes[targetIndex];
127
- const { elementStart, elementEnd } = getElementBounds(targetItem);
128
- const targetSize = elementEnd - elementStart;
129
- scrollAmount = isBackward ? elementStart + targetSize - scrollAreaSize + buttonSize : elementStart - buttonSize;
130
- } else {
131
- const scrollBy = scrollAreaSize - buttonSize * 2;
132
- scrollAmount = isBackward ? scrollPos - scrollBy : scrollPos + scrollBy;
119
+ const userPrefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
120
+ const scrollBehavior = userPrefersReducedMotion ? "auto" : (scrollAreaContext == null ? void 0 : scrollAreaContext.scrollBehavior) ?? "smooth";
121
+ function calculateScrollAmount() {
122
+ if (fullyVisibleItemIndices.length <= 0) {
123
+ const defaultScrollAmount = viewportSize - scrollButtonSize * 2;
124
+ return isScrollingBackward ? currentScrollPosition - defaultScrollAmount : currentScrollPosition + defaultScrollAmount;
125
+ }
126
+ const isRightToLeft = scrollAreaContext == null ? void 0 : scrollAreaContext.isRtl;
127
+ const effectiveBackwardDirection = isRightToLeft ? !isScrollingBackward : isScrollingBackward;
128
+ const referenceItemIndex = effectiveBackwardDirection ? fullyVisibleItemIndices[0] : fullyVisibleItemIndices[fullyVisibleItemIndices.length - 1];
129
+ const targetItemIndex = effectiveBackwardDirection ? referenceItemIndex > 0 ? referenceItemIndex - 1 : referenceItemIndex : referenceItemIndex < scrollableItems.length - 1 ? referenceItemIndex + 1 : referenceItemIndex;
130
+ const targetItem = scrollableItems[targetItemIndex];
131
+ const { itemStart, itemEnd } = getItemBounds(targetItem);
132
+ const targetItemSize = itemEnd - itemStart;
133
+ return isScrollingBackward ? itemStart + targetItemSize - viewportSize + scrollButtonSize : itemStart - scrollButtonSize;
133
134
  }
134
- scrollAmount = Math.max(0, Math.min(scrollAmount, maxScrollPos));
135
- scrollArea.scrollTo({
136
- [scrollAxis]: scrollAmount,
135
+ const newScrollPosition = calculateScrollAmount();
136
+ scrollAreaElement.scrollTo({
137
+ [scrollProperty]: newScrollPosition,
137
138
  behavior: scrollBehavior
138
139
  });
139
140
  });
@@ -142,14 +143,14 @@ const Button = React.forwardRef(
142
143
  {
143
144
  iconOnly: true,
144
145
  variant: "primary",
145
- "aria-label": directionLabels[direction],
146
+ "aria-label": directionToAriaLabel[direction],
146
147
  "data-direction": direction,
147
- tabIndex: isHidden ? -1 : void 0,
148
+ tabIndex: shouldBeHidden ? -1 : void 0,
148
149
  ...props,
149
- onClick: handleClick,
150
+ onClick: handleButtonClick,
150
151
  ref: forwardRef,
151
- className: classes,
152
- children: children || /* @__PURE__ */ jsxRuntime.jsx(components_icon_icon.Icon, { name: directionIcons[direction] })
152
+ className: buttonClasses,
153
+ children: children || /* @__PURE__ */ jsxRuntime.jsx(components_icon_icon.Icon, { name: directionToIconName[direction] })
153
154
  }
154
155
  );
155
156
  }
@@ -206,7 +207,16 @@ const Root = React.forwardRef(
206
207
  return /* @__PURE__ */ jsxRuntime.jsx(
207
208
  RootContext.Provider,
208
209
  {
209
- value: { scrollRef, variant, hasScrollTop, hasScrollBottom, hasScrollLeft, hasScrollRight, scrollBehavior },
210
+ value: {
211
+ scrollRef,
212
+ variant,
213
+ hasScrollTop,
214
+ hasScrollBottom,
215
+ hasScrollLeft,
216
+ hasScrollRight,
217
+ scrollBehavior,
218
+ isRtl: props.dir === "rtl"
219
+ },
210
220
  children: /* @__PURE__ */ jsxRuntime.jsxs(ScrollAreaPrimitive__namespace.Root, { ...props, ref: forwardRef, className: classes, children: [
211
221
  /* @__PURE__ */ jsxRuntime.jsx(
212
222
  ScrollAreaPrimitive__namespace.Viewport,
@@ -45,76 +45,77 @@ const Corner = React__default.forwardRef(
45
45
  }
46
46
  );
47
47
  Corner.displayName = "Corner";
48
+ const directionToAriaLabel = {
49
+ up: "Scroll opp",
50
+ down: "Scroll ned",
51
+ left: "Scroll til venstre",
52
+ right: "Scroll til høyre"
53
+ };
54
+ const directionToIconName = {
55
+ up: "chevron-up",
56
+ down: "chevron-down",
57
+ left: "chevron-left",
58
+ right: "chevron-right"
59
+ };
48
60
  const Button = React__default.forwardRef(
49
61
  ({ className, hidden, direction = "right", children, ...props }, forwardRef) => {
50
- const context = React__default.useContext(RootContext);
51
- const isHidden = hidden ?? (direction === "up" && !(context == null ? void 0 : context.hasScrollTop) || direction === "down" && !(context == null ? void 0 : context.hasScrollBottom) || direction === "left" && !(context == null ? void 0 : context.hasScrollLeft) || direction === "right" && !(context == null ? void 0 : context.hasScrollRight));
52
- const classes = clsx(
62
+ const scrollAreaContext = React__default.useContext(RootContext);
63
+ const shouldBeHidden = hidden ?? (direction === "up" && !(scrollAreaContext == null ? void 0 : scrollAreaContext.hasScrollTop) || direction === "down" && !(scrollAreaContext == null ? void 0 : scrollAreaContext.hasScrollBottom) || direction === "left" && !(scrollAreaContext == null ? void 0 : scrollAreaContext.hasScrollLeft) || direction === "right" && !(scrollAreaContext == null ? void 0 : scrollAreaContext.hasScrollRight));
64
+ const buttonClasses = clsx(
53
65
  styles[`${rootClassName}__button`],
54
66
  {
55
- [styles[`${rootClassName}__button--hidden`]]: isHidden
67
+ [styles[`${rootClassName}__button--hidden`]]: shouldBeHidden
56
68
  },
57
69
  className
58
70
  );
59
- const directionLabels = {
60
- up: "Scroll opp",
61
- down: "Scroll ned",
62
- left: "Scroll til venstre",
63
- right: "Scroll til høyre"
64
- };
65
- const directionIcons = {
66
- up: "chevron-up",
67
- down: "chevron-down",
68
- left: "chevron-left",
69
- right: "chevron-right"
70
- };
71
- const handleClick = composeEventHandlers(props.onClick, (e) => {
72
- if (e.defaultPrevented)
71
+ const handleButtonClick = composeEventHandlers(props.onClick, (event) => {
72
+ if (event.defaultPrevented)
73
73
  return;
74
- const scrollArea = context == null ? void 0 : context.scrollRef;
75
- if (!scrollArea)
74
+ const scrollAreaElement = scrollAreaContext == null ? void 0 : scrollAreaContext.scrollRef;
75
+ if (!scrollAreaElement)
76
76
  return;
77
- const itemNodes = Array.from(scrollArea.querySelectorAll("[data-in-view]"));
78
- const isHorizontal = direction === "left" || direction === "right";
79
- const scrollAxis = isHorizontal ? "left" : "top";
80
- const isBackward = direction === "left" || direction === "up";
81
- const scrollPos = isHorizontal ? scrollArea.scrollLeft : scrollArea.scrollTop;
82
- const scrollAreaSize = isHorizontal ? scrollArea.clientWidth : scrollArea.clientHeight;
83
- const maxScrollPos = isHorizontal ? scrollArea.scrollWidth - scrollAreaSize : scrollArea.scrollHeight - scrollAreaSize;
84
- const buttonSize = isHorizontal ? e.currentTarget.offsetWidth : e.currentTarget.offsetHeight;
85
- const visibleStart = scrollPos + (isBackward ? buttonSize : 0);
86
- const visibleEnd = scrollPos + scrollAreaSize - (!isBackward ? buttonSize : 0);
87
- const getElementBounds = (element) => {
88
- const elementStart = isHorizontal ? element.offsetLeft : element.offsetTop;
89
- const elementEnd = elementStart + (isHorizontal ? element.offsetWidth : element.offsetHeight);
90
- return { elementStart, elementEnd };
77
+ const scrollableItems = Array.from(scrollAreaElement.querySelectorAll("[data-in-view]"));
78
+ const isHorizontalScroll = direction === "left" || direction === "right";
79
+ const scrollProperty = isHorizontalScroll ? "left" : "top";
80
+ const isScrollingBackward = direction === "left" || direction === "up";
81
+ const currentScrollPosition = isHorizontalScroll ? scrollAreaElement.scrollLeft : scrollAreaElement.scrollTop;
82
+ const viewportSize = isHorizontalScroll ? scrollAreaElement.clientWidth : scrollAreaElement.clientHeight;
83
+ const scrollButtonSize = isHorizontalScroll ? event.currentTarget.offsetWidth : event.currentTarget.offsetHeight;
84
+ const visibleAreaStart = currentScrollPosition + (isScrollingBackward ? scrollButtonSize : 0);
85
+ const visibleAreaEnd = currentScrollPosition + viewportSize - (!isScrollingBackward ? scrollButtonSize : 0);
86
+ const getItemBounds = (item) => {
87
+ const itemStart = isHorizontalScroll ? item.offsetLeft : item.offsetTop;
88
+ const itemEnd = itemStart + (isHorizontalScroll ? item.offsetWidth : item.offsetHeight);
89
+ return { itemStart, itemEnd };
91
90
  };
92
- const isElementFullyVisible = (element) => {
93
- const { elementStart, elementEnd } = getElementBounds(element);
94
- return elementStart >= visibleStart && elementEnd <= visibleEnd;
91
+ const isItemFullyVisible = (item) => {
92
+ const { itemStart, itemEnd } = getItemBounds(item);
93
+ return itemStart >= visibleAreaStart && itemEnd <= visibleAreaEnd;
95
94
  };
96
- const inViewIndices = itemNodes.map((node, index) => {
97
- const dataInView = node.getAttribute("data-in-view") === "true";
98
- const fullyVisible = isElementFullyVisible(node);
99
- return dataInView && fullyVisible ? index : -1;
95
+ const fullyVisibleItemIndices = scrollableItems.map((item, index) => {
96
+ const isInView = item.getAttribute("data-in-view") === "true";
97
+ const isFullyVisible = isItemFullyVisible(item);
98
+ return isInView && isFullyVisible ? index : -1;
100
99
  }).filter((index) => index !== -1);
101
- const hasReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
102
- const scrollBehavior = hasReducedMotion ? "auto" : (context == null ? void 0 : context.scrollBehavior) ?? "smooth";
103
- let scrollAmount = scrollPos;
104
- if (inViewIndices.length > 0) {
105
- const currentIndex = isBackward ? inViewIndices[0] : inViewIndices[inViewIndices.length - 1];
106
- const targetIndex = isBackward ? currentIndex > 0 ? currentIndex - 1 : currentIndex : currentIndex < itemNodes.length - 1 ? currentIndex + 1 : currentIndex;
107
- const targetItem = itemNodes[targetIndex];
108
- const { elementStart, elementEnd } = getElementBounds(targetItem);
109
- const targetSize = elementEnd - elementStart;
110
- scrollAmount = isBackward ? elementStart + targetSize - scrollAreaSize + buttonSize : elementStart - buttonSize;
111
- } else {
112
- const scrollBy = scrollAreaSize - buttonSize * 2;
113
- scrollAmount = isBackward ? scrollPos - scrollBy : scrollPos + scrollBy;
100
+ const userPrefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
101
+ const scrollBehavior = userPrefersReducedMotion ? "auto" : (scrollAreaContext == null ? void 0 : scrollAreaContext.scrollBehavior) ?? "smooth";
102
+ function calculateScrollAmount() {
103
+ if (fullyVisibleItemIndices.length <= 0) {
104
+ const defaultScrollAmount = viewportSize - scrollButtonSize * 2;
105
+ return isScrollingBackward ? currentScrollPosition - defaultScrollAmount : currentScrollPosition + defaultScrollAmount;
106
+ }
107
+ const isRightToLeft = scrollAreaContext == null ? void 0 : scrollAreaContext.isRtl;
108
+ const effectiveBackwardDirection = isRightToLeft ? !isScrollingBackward : isScrollingBackward;
109
+ const referenceItemIndex = effectiveBackwardDirection ? fullyVisibleItemIndices[0] : fullyVisibleItemIndices[fullyVisibleItemIndices.length - 1];
110
+ const targetItemIndex = effectiveBackwardDirection ? referenceItemIndex > 0 ? referenceItemIndex - 1 : referenceItemIndex : referenceItemIndex < scrollableItems.length - 1 ? referenceItemIndex + 1 : referenceItemIndex;
111
+ const targetItem = scrollableItems[targetItemIndex];
112
+ const { itemStart, itemEnd } = getItemBounds(targetItem);
113
+ const targetItemSize = itemEnd - itemStart;
114
+ return isScrollingBackward ? itemStart + targetItemSize - viewportSize + scrollButtonSize : itemStart - scrollButtonSize;
114
115
  }
115
- scrollAmount = Math.max(0, Math.min(scrollAmount, maxScrollPos));
116
- scrollArea.scrollTo({
117
- [scrollAxis]: scrollAmount,
116
+ const newScrollPosition = calculateScrollAmount();
117
+ scrollAreaElement.scrollTo({
118
+ [scrollProperty]: newScrollPosition,
118
119
  behavior: scrollBehavior
119
120
  });
120
121
  });
@@ -123,14 +124,14 @@ const Button = React__default.forwardRef(
123
124
  {
124
125
  iconOnly: true,
125
126
  variant: "primary",
126
- "aria-label": directionLabels[direction],
127
+ "aria-label": directionToAriaLabel[direction],
127
128
  "data-direction": direction,
128
- tabIndex: isHidden ? -1 : void 0,
129
+ tabIndex: shouldBeHidden ? -1 : void 0,
129
130
  ...props,
130
- onClick: handleClick,
131
+ onClick: handleButtonClick,
131
132
  ref: forwardRef,
132
- className: classes,
133
- children: children || /* @__PURE__ */ jsx(Icon, { name: directionIcons[direction] })
133
+ className: buttonClasses,
134
+ children: children || /* @__PURE__ */ jsx(Icon, { name: directionToIconName[direction] })
134
135
  }
135
136
  );
136
137
  }
@@ -187,7 +188,16 @@ const Root = React__default.forwardRef(
187
188
  return /* @__PURE__ */ jsx(
188
189
  RootContext.Provider,
189
190
  {
190
- value: { scrollRef, variant, hasScrollTop, hasScrollBottom, hasScrollLeft, hasScrollRight, scrollBehavior },
191
+ value: {
192
+ scrollRef,
193
+ variant,
194
+ hasScrollTop,
195
+ hasScrollBottom,
196
+ hasScrollLeft,
197
+ hasScrollRight,
198
+ scrollBehavior,
199
+ isRtl: props.dir === "rtl"
200
+ },
191
201
  children: /* @__PURE__ */ jsxs(ScrollAreaPrimitive.Root, { ...props, ref: forwardRef, className: classes, children: [
192
202
  /* @__PURE__ */ jsx(
193
203
  ScrollAreaPrimitive.Viewport,
@@ -15,7 +15,7 @@ export declare const Button: React.ForwardRefExoticComponent<Omit<Omit<Omit<Reac
15
15
  } & {
16
16
  asChild?: boolean | undefined;
17
17
  loading?: boolean | undefined;
18
- fullWidth?: boolean | undefined;
18
+ fullWidth?: boolean | undefined; /** Hidden will fade the button out. Used when the scrollbar is at the end */
19
19
  size?: "sm" | "md" | "lg" | undefined;
20
20
  variant?: "text" | "text-negative" | "primary" | "list-item" | "secondary" | "destructive" | "tertiary-purple" | "expressive" | "primary-negative" | "secondary-negative" | "destructive-negative" | "tertiary-purple-negative" | "expressive-negative" | undefined;
21
21
  } & {
@@ -26,7 +26,7 @@ export declare const Button: React.ForwardRefExoticComponent<Omit<Omit<Omit<Reac
26
26
  } & {
27
27
  asChild?: boolean | undefined;
28
28
  loading?: boolean | undefined;
29
- fullWidth?: boolean | undefined;
29
+ fullWidth?: boolean | undefined; /** Hidden will fade the button out. Used when the scrollbar is at the end */
30
30
  size?: "sm" | "md" | "lg" | undefined;
31
31
  variant?: "text" | "text-negative" | "primary" | "list-item" | "secondary" | "destructive" | "tertiary-purple" | "expressive" | "primary-negative" | "secondary-negative" | "destructive-negative" | "tertiary-purple-negative" | "expressive-negative" | undefined;
32
32
  } & {
@@ -20,6 +20,7 @@ type RootContextType = {
20
20
  hasScrollLeft: boolean | undefined;
21
21
  hasScrollRight: boolean | undefined;
22
22
  scrollBehavior: 'smooth' | 'auto';
23
+ isRtl: boolean;
23
24
  };
24
25
  export declare const RootContext: React.Context<RootContextType | undefined>;
25
26
  export declare const Root: React.ForwardRefExoticComponent<Omit<ScrollAreaPrimitive.ScrollAreaProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const breakpointToNumber = (breakpoint) => {
4
+ return parseInt((breakpoint || "").replace("px", ""));
5
+ };
6
+ exports.breakpointToNumber = breakpointToNumber;
@@ -0,0 +1 @@
1
+ export declare const breakpointToNumber: (breakpoint: string) => number;
@@ -0,0 +1,6 @@
1
+ const breakpointToNumber = (breakpoint) => {
2
+ return parseInt((breakpoint || "").replace("px", ""));
3
+ };
4
+ export {
5
+ breakpointToNumber
6
+ };
package/package.json CHANGED
@@ -20,7 +20,7 @@
20
20
  "pnpm": ">=8"
21
21
  },
22
22
  "private": false,
23
- "version": "0.0.73",
23
+ "version": "0.0.75",
24
24
  "sideEffects": [
25
25
  "**/*.css"
26
26
  ],