@obosbbl/grunnmuren-react 3.3.5 → 3.4.1
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/dist/__stories__/form-validation.stories.cjs +71 -57
- package/dist/__stories__/form-validation.stories.js +72 -58
- package/dist/__stories__/layout.stories.cjs +7 -0
- package/dist/__stories__/layout.stories.js +7 -0
- package/dist/index.d.mts +101 -25
- package/dist/index.mjs +541 -342
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { useContextProps, DisclosureContext, DisclosureGroupStateContext, Provider, ButtonContext as ButtonContext$1, DEFAULT_SLOT, Button as Button$1, useLocale, Link as Link$1, Breadcrumb as Breadcrumb$1, Breadcrumbs as Breadcrumbs$1, Text, CheckboxContext, Checkbox as Checkbox$1, FieldError, Label as Label$1, CheckboxGroup as CheckboxGroup$1, Header, ListBoxItem as ListBoxItem$1, ListBoxSection as ListBoxSection$1, ListBox as ListBox$1, ComboBox, Group, Input, Popover, useSlottedContext, FormContext, FieldErrorContext, LabelContext, InputContext, I18nProvider, RouterProvider,
|
|
2
|
+
import { useContextProps, DisclosureContext, DisclosureGroupStateContext, Provider, ButtonContext as ButtonContext$1, DEFAULT_SLOT, Button as Button$1, useLocale, Link as Link$1, Breadcrumb as Breadcrumb$1, Breadcrumbs as Breadcrumbs$1, GroupContext, Text, CheckboxContext, Checkbox as Checkbox$1, FieldError, Label as Label$1, CheckboxGroup as CheckboxGroup$1, Header, ListBoxItem as ListBoxItem$1, ListBoxSection as ListBoxSection$1, ListBox as ListBox$1, ComboBox, Group, Input, Popover, useSlottedContext, FormContext, FieldErrorContext, LabelContext, InputContext, I18nProvider, RouterProvider, Dialog as Dialog$1, DialogTrigger as DialogTrigger$1, Modal as Modal$1, ModalOverlay, NumberField as NumberField$1, Radio as Radio$1, RadioGroup as RadioGroup$1, Select as Select$1, SelectValue, ProgressBar as ProgressBar$1, LinkContext, ColumnResizer, Table as Table$1, TableBody as TableBody$1, Cell, Column, ResizableTableContainer, TableHeader as TableHeader$1, Row, Tab as Tab$1, TabListStateContext, TabList as TabList$1, TabPanel as TabPanel$1, Tabs as Tabs$1, TagGroup as TagGroup$1, TagList as TagList$1, Tag as Tag$1, TextField as TextField$1, TextArea as TextArea$1 } from 'react-aria-components';
|
|
3
3
|
export { DisclosureGroup, Form, Group } from 'react-aria-components';
|
|
4
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
import { cva, cx, compose } from 'cva';
|
|
6
|
-
import { createContext, useContext, useId, useRef, Children, useState, useEffect, useMemo, useCallback, isValidElement, cloneElement } from 'react';
|
|
7
|
-
import { ChevronDown, Error, Warning, CheckCircle, InfoCircle, Close, User, ChevronLeft, ChevronRight, LoadingSpinner, Check, Trash,
|
|
6
|
+
import { createContext, useContext, useId, useRef, Children, useState, useEffect, useMemo, useCallback, isValidElement, cloneElement, use } from 'react';
|
|
7
|
+
import { ChevronDown, Error, Warning, CheckCircle, InfoCircle, Close, User, ChevronLeft, ChevronRight, LoadingSpinner, Check, Trash, Download, LinkExternal, ArrowRight, Edit, PlayerPause, PlayerPlay } from '@obosbbl/grunnmuren-icons-react';
|
|
8
8
|
import { filterDOMProps, mergeProps, mergeRefs, useObjectRef, useFormReset, useUpdateEffect } from '@react-aria/utils';
|
|
9
9
|
import { useFocusRing, useDisclosure, useProgressBar, useDateFormatter, useField } from 'react-aria';
|
|
10
10
|
import { useDisclosureState } from 'react-stately';
|
|
@@ -357,15 +357,20 @@ const translations$1 = {
|
|
|
357
357
|
sv: 'Nästa',
|
|
358
358
|
en: 'Next'
|
|
359
359
|
},
|
|
360
|
-
carousel: {
|
|
361
|
-
nb: 'Karusell',
|
|
362
|
-
sv: 'Karusell',
|
|
363
|
-
en: 'Carousel'
|
|
364
|
-
},
|
|
365
360
|
externalLink: {
|
|
366
361
|
nb: '(ekstern lenke)',
|
|
367
362
|
sv: '(extern länk)',
|
|
368
363
|
en: '(external link)'
|
|
364
|
+
},
|
|
365
|
+
stepper: {
|
|
366
|
+
nb: 'Steg',
|
|
367
|
+
sv: 'Steg',
|
|
368
|
+
en: 'Steps'
|
|
369
|
+
},
|
|
370
|
+
completed: {
|
|
371
|
+
nb: 'Fullført',
|
|
372
|
+
sv: 'Slutförd',
|
|
373
|
+
en: 'Completed'
|
|
369
374
|
}
|
|
370
375
|
};
|
|
371
376
|
|
|
@@ -495,44 +500,73 @@ const Avatar = ({ src, alt = '', className, onError, loading = 'lazy', ...rest }
|
|
|
495
500
|
});
|
|
496
501
|
};
|
|
497
502
|
|
|
498
|
-
const
|
|
499
|
-
const
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
503
|
+
const formField = cx('group flex flex-col gap-2');
|
|
504
|
+
const formFieldError = cx('w-fit bg-red-light px-2 py-1 text-red text-sm leading-6', 'group-data-[slot=file-upload]:rounded-lg');
|
|
505
|
+
const input = cva({
|
|
506
|
+
base: [
|
|
507
|
+
// All inputs should always have a white background (this also ensures that type="search" on Safri doesn't get a gray background)
|
|
508
|
+
'bg-white',
|
|
509
|
+
// Use box-content to enable auto width based on number of characters (size)
|
|
510
|
+
// Setting min-height to prevent the input from collapsing in Safari
|
|
511
|
+
// Combining these with a padding-y as base classes makes it easier to standardize the height (44px) of all inputs
|
|
512
|
+
'box-content min-h-6 py-2.5',
|
|
513
|
+
'rounded-md font-normal text-base leading-6 placeholder-[#727070] outline-hidden ring-1 ring-black',
|
|
514
|
+
// invalid styles
|
|
515
|
+
'group-data-invalid:ring-focus group-data-invalid:ring-red',
|
|
516
|
+
// Fix invisible ring on safari: https://github.com/tailwindlabs/tailwindcss.com/issues/1135
|
|
517
|
+
'appearance-none'
|
|
518
|
+
],
|
|
519
|
+
variants: {
|
|
520
|
+
// Focus rings. Can either be :focus or :focus-visible based on the needs of the particular component.
|
|
521
|
+
focusModifier: {
|
|
522
|
+
focus: 'focus:ring-focus group-data-invalid:focus:ring-3 group-data-invalid:focus:ring-red',
|
|
523
|
+
visible: 'data-focus-visible:ring-focus group-data-invalid:data-focus-visible:ring-3 group-data-invalid:data-focus-visible:ring-red'
|
|
524
|
+
},
|
|
525
|
+
isGrouped: {
|
|
526
|
+
false: 'px-3',
|
|
527
|
+
true: '!ring-0 flex-1'
|
|
528
|
+
}
|
|
529
|
+
},
|
|
530
|
+
defaultVariants: {
|
|
531
|
+
focusModifier: 'focus',
|
|
532
|
+
isGrouped: false
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
const inputGroup = cx([
|
|
536
|
+
'inline-flex items-center gap-3 overflow-hidden rounded-md bg-white px-3 text-base ring-1 ring-black focus-within:ring-focus',
|
|
537
|
+
'group-data-invalid:ring-focus group-data-invalid:ring-red group-data-invalid:focus-within:ring-3 group-data-invalid:focus-within:ring-red'
|
|
538
|
+
]);
|
|
539
|
+
const dropdown = {
|
|
540
|
+
popover: cx('data-entering:fade-in data-exiting:fade-out min-w-(--trigger-width) overflow-y-auto rounded-md border border-black bg-white shadow-sm data-entering:animate-in data-exiting:animate-out'),
|
|
541
|
+
// overflow-x-hidden is needed to prevent visible vertical scrollbars from overflowing the border radius of the popover
|
|
542
|
+
listbox: cx('max-h-100 overflow-x-hidden text-sm outline-hidden'),
|
|
543
|
+
chevronIcon: cx('text-base transition-transform duration-150 group-data-open:rotate-180 motion-reduce:transition-none')
|
|
524
544
|
};
|
|
545
|
+
const animateIconVariants = cva({
|
|
546
|
+
base: '*:[svg]:shrink-0 *:[svg]:transition-transform',
|
|
547
|
+
variants: {
|
|
548
|
+
animateIcon: {
|
|
549
|
+
right: 'hover:*:[svg]:motion-safe:translate-x-1',
|
|
550
|
+
left: 'hover:*:[svg]:motion-safe:-translate-x-1',
|
|
551
|
+
down: 'hover:*:[svg]:motion-safe:translate-y-1',
|
|
552
|
+
up: 'hover:*:[svg]:motion-safe:-translate-y-1',
|
|
553
|
+
'up-right': 'hover:*:[svg]:motion-safe:-translate-y-0.5 hover:*:[svg]:motion-safe:translate-x-0.5'
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
});
|
|
525
557
|
|
|
526
558
|
function isLinkProps$1(props) {
|
|
527
559
|
return !!props.href;
|
|
528
560
|
}
|
|
529
561
|
function Backlink(props) {
|
|
530
|
-
const { className,
|
|
531
|
-
const _className = cx(className,
|
|
562
|
+
const { className, children, withUnderline, ref, ...restProps } = props;
|
|
563
|
+
const _className = cx(className, animateIconVariants({
|
|
564
|
+
animateIcon: 'left'
|
|
565
|
+
}), 'group flex max-w-fit cursor-pointer items-center gap-3 rounded-md p-2.5 font-normal no-underline focus-visible:outline-focus');
|
|
532
566
|
const content = /*#__PURE__*/ jsxs(Fragment, {
|
|
533
567
|
children: [
|
|
534
568
|
/*#__PURE__*/ jsx(ChevronLeft, {
|
|
535
|
-
className: cx('-ml-[0.5em]
|
|
569
|
+
className: cx('-ml-[0.5em] duration-300')
|
|
536
570
|
}),
|
|
537
571
|
/*#__PURE__*/ jsx("span", {
|
|
538
572
|
children: /*#__PURE__*/ jsx("span", {
|
|
@@ -543,10 +577,9 @@ function Backlink(props) {
|
|
|
543
577
|
]
|
|
544
578
|
});
|
|
545
579
|
if (isLinkProps$1(props)) {
|
|
546
|
-
return /*#__PURE__*/ jsx(Link, {
|
|
580
|
+
return /*#__PURE__*/ jsx(Link$1, {
|
|
547
581
|
...restProps,
|
|
548
582
|
className: _className,
|
|
549
|
-
style: style,
|
|
550
583
|
ref: ref,
|
|
551
584
|
children: content
|
|
552
585
|
});
|
|
@@ -554,7 +587,6 @@ function Backlink(props) {
|
|
|
554
587
|
return /*#__PURE__*/ jsx(Button$1, {
|
|
555
588
|
...restProps,
|
|
556
589
|
className: _className,
|
|
557
|
-
style: style,
|
|
558
590
|
ref: ref,
|
|
559
591
|
children: content
|
|
560
592
|
});
|
|
@@ -597,6 +629,30 @@ function Badge(props) {
|
|
|
597
629
|
});
|
|
598
630
|
}
|
|
599
631
|
|
|
632
|
+
const linkVariants = compose(animateIconVariants, cva({
|
|
633
|
+
base: 'inline-flex cursor-pointer items-center gap-1 font-medium hover:no-underline focus-visible:outline-current focus-visible:outline-focus-offset data-disabled:cursor-default data-disabled:font-normal data-disabled:no-underline'
|
|
634
|
+
}));
|
|
635
|
+
const Link = ({ animateIcon, children, className, '~iconRight': iconRight, ...props })=>{
|
|
636
|
+
const locale = _useLocale();
|
|
637
|
+
const externalLinkText = translations$1.externalLink[locale];
|
|
638
|
+
return /*#__PURE__*/ jsxs(Link$1, {
|
|
639
|
+
...props,
|
|
640
|
+
"data-slot": "link",
|
|
641
|
+
className: linkVariants({
|
|
642
|
+
className,
|
|
643
|
+
animateIcon
|
|
644
|
+
}),
|
|
645
|
+
children: [
|
|
646
|
+
children,
|
|
647
|
+
props.rel?.includes('external') && /*#__PURE__*/ jsx("span", {
|
|
648
|
+
className: "sr-only",
|
|
649
|
+
children: externalLinkText
|
|
650
|
+
}),
|
|
651
|
+
iconRight
|
|
652
|
+
]
|
|
653
|
+
});
|
|
654
|
+
};
|
|
655
|
+
|
|
600
656
|
function Breadcrumb(props) {
|
|
601
657
|
const { className, children, href, ...restProps } = props;
|
|
602
658
|
return /*#__PURE__*/ jsxs(Breadcrumb$1, {
|
|
@@ -627,38 +683,38 @@ function Breadcrumbs(props) {
|
|
|
627
683
|
|
|
628
684
|
/**
|
|
629
685
|
* Figma: https://www.figma.com/file/9OvSg0ZXI5E1eQYi7AWiWn/Grunnmuren-2.0-%E2%94%82-Designsystem?node-id=30%3A2574&mode=dev
|
|
630
|
-
*/ const buttonVariants = cva({
|
|
686
|
+
*/ const buttonVariants = compose(animateIconVariants, cva({
|
|
631
687
|
base: [
|
|
632
688
|
'inline-flex min-h-[44px] cursor-pointer items-center justify-center whitespace-nowrap rounded-lg font-medium transition-colors duration-200 focus-visible:outline-focus-offset'
|
|
633
689
|
],
|
|
634
690
|
variants: {
|
|
635
691
|
/**
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
692
|
+
* The variant of the button
|
|
693
|
+
* @default primary
|
|
694
|
+
*/ variant: {
|
|
639
695
|
primary: 'no-underline',
|
|
640
696
|
// by using an inset box-shadow to emulate a border instead of an actual border, the button size will be equal regardless of the variant
|
|
641
697
|
secondary: 'border-2 border-current no-underline hover:border-transparent',
|
|
642
698
|
tertiary: 'underline hover:no-underline'
|
|
643
699
|
},
|
|
644
700
|
/**
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
701
|
+
* Adjusts the color of the button for usage on different backgrounds.
|
|
702
|
+
* @default blue
|
|
703
|
+
*/ color: {
|
|
648
704
|
blue: 'focus-visible:outline-focus',
|
|
649
705
|
mint: 'focus-visible:outline-focus focus-visible:outline-mint',
|
|
650
706
|
white: 'focus-visible:outline-focus focus-visible:outline-white'
|
|
651
707
|
},
|
|
652
708
|
/**
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
709
|
+
* When the button is without text, but with a single icon.
|
|
710
|
+
* @default false
|
|
711
|
+
*/ isIconOnly: {
|
|
656
712
|
true: 'p-2 [&>svg]:h-7 [&>svg]:w-7',
|
|
657
713
|
false: 'gap-2.5 px-4 py-2'
|
|
658
714
|
},
|
|
659
715
|
// Make the content of the button transparent to hide it's content, but keep the button width
|
|
660
716
|
isPending: {
|
|
661
|
-
true: '
|
|
717
|
+
true: 'relative text-transparent!',
|
|
662
718
|
false: null
|
|
663
719
|
}
|
|
664
720
|
},
|
|
@@ -717,15 +773,17 @@ function Breadcrumbs(props) {
|
|
|
717
773
|
isIconOnly: false,
|
|
718
774
|
isPending: false
|
|
719
775
|
}
|
|
720
|
-
});
|
|
776
|
+
}));
|
|
721
777
|
const ButtonContext = /*#__PURE__*/ createContext({});
|
|
722
778
|
function isLinkProps(props) {
|
|
723
779
|
return !!props.href;
|
|
724
780
|
}
|
|
725
781
|
function Button({ ref = null, ...props }) {
|
|
726
782
|
[props, ref] = useContextProps(props, ref, ButtonContext);
|
|
727
|
-
const { children: _children, color, isIconOnly, variant, isPending, ...restProps } = props;
|
|
783
|
+
const { animateIcon, children: _children, color, isIconOnly, variant, isPending, ...restProps } = props;
|
|
728
784
|
const className = buttonVariants({
|
|
785
|
+
// Don't animate the icon when we're pending, as it affects the loading spinner
|
|
786
|
+
animateIcon: isPending ? undefined : animateIcon,
|
|
729
787
|
className: props.className,
|
|
730
788
|
color,
|
|
731
789
|
isIconOnly,
|
|
@@ -985,6 +1043,137 @@ const cardLinkVariants = cva({
|
|
|
985
1043
|
});
|
|
986
1044
|
};
|
|
987
1045
|
|
|
1046
|
+
const HeroContext = /*#__PURE__*/ createContext(null);
|
|
1047
|
+
// Common variant for "standard" and "full-bleed" Hero variants
|
|
1048
|
+
const oneColumnLayout = [
|
|
1049
|
+
// Vertical spacing in the <Content>
|
|
1050
|
+
'lg:*:data-[slot="content"]:gap-y-4',
|
|
1051
|
+
// Main text content takes up 9 columns on medium screens and above
|
|
1052
|
+
'lg:*:data-[slot="content"]:col-span-9',
|
|
1053
|
+
// Make sure other elements than <Content> and <Media> (i.e CTA) does not span the full width on small screens
|
|
1054
|
+
'*:not-data-[slot="content"]:not-data-[slot="media"]:w-fit',
|
|
1055
|
+
// Other elements than <Content> and <Media> (e.g. CTA, SVG logo or Badge) take up 3 columns on medium screens and above, and are right aligned
|
|
1056
|
+
'lg:*:not-data-[slot="content"]:not-data-[slot="media"]:not-data-[slot="carousel"]:col-span-3 lg:*:not-data-[slot="content"]:not-data-[slot="media"]:justify-self-end',
|
|
1057
|
+
// <Media> and <Carousel> content takes up the full width on medium screens and above
|
|
1058
|
+
'lg:*:data-[slot="media"]:col-span-full *:data-[slot="media"]:*:w-full',
|
|
1059
|
+
'lg:*:data-[slot="carousel"]:col-span-full',
|
|
1060
|
+
// Aligns <Content> and any element beside it (e.g. <Media>, <Badge>, <CTA> etc.) to the bottom of the <Content> container
|
|
1061
|
+
'lg:items-end'
|
|
1062
|
+
];
|
|
1063
|
+
const nonFullBleedAspectRatiosForSmallScreens = '*:data-[slot="media"]:*:aspect-[1/1] sm:*:data-[slot="media"]:*:aspect-4/3 md:*:data-[slot="media"]:*:aspect-3/2';
|
|
1064
|
+
const variants = cva({
|
|
1065
|
+
base: [
|
|
1066
|
+
'container px-0',
|
|
1067
|
+
// Grid variant to position the Hero's content
|
|
1068
|
+
'grid lg:grid-cols-12 lg:gap-x-12 xl:gap-x-16',
|
|
1069
|
+
'gap-y-10 lg:gap-y-12',
|
|
1070
|
+
// Enable vertical gap within <Content>
|
|
1071
|
+
'*:data-[slot="content"]:grid',
|
|
1072
|
+
// Vertical spacing in the <Content>
|
|
1073
|
+
'*:data-[slot="content"]:gap-y-3',
|
|
1074
|
+
// Make sure <Media> content fills any available vertical and horizontal space
|
|
1075
|
+
'*:data-[slot="media"]:*:object-cover',
|
|
1076
|
+
'*:data-[slot="carousel"]:overflow-hidden *:data-[slot="carousel"]:rounded-3xl',
|
|
1077
|
+
// Make the carousel items full width, so we scroll one at a time
|
|
1078
|
+
'**:data-[slot="carousel-item"]:basis-full'
|
|
1079
|
+
],
|
|
1080
|
+
variants: {
|
|
1081
|
+
/**
|
|
1082
|
+
* Defines the variant of the Hero
|
|
1083
|
+
* @default standard
|
|
1084
|
+
* */ variant: {
|
|
1085
|
+
standard: [
|
|
1086
|
+
oneColumnLayout,
|
|
1087
|
+
nonFullBleedAspectRatiosForSmallScreens,
|
|
1088
|
+
'lg:*:data-[slot="media"]:*:aspect-2/1'
|
|
1089
|
+
],
|
|
1090
|
+
'full-bleed': [
|
|
1091
|
+
oneColumnLayout,
|
|
1092
|
+
// Position the media and carousel content to fill the entire viewport width
|
|
1093
|
+
'*:data-[slot="media"]:*:absolute *:data-[slot="media"]:*:left-0',
|
|
1094
|
+
// Special case for Carousel, where the Media is nested inside a CarouselItem
|
|
1095
|
+
'*:data-[slot="carousel"]:**:data-[slot="media"]:w-full',
|
|
1096
|
+
// Match the heights of the <Media> or <Carousel> wrapper for the Media content (e.g. image, VideoLoop, video etc.)
|
|
1097
|
+
// This is necessary due to the absolute positioning of the media and carousel containers in this variant
|
|
1098
|
+
// biome-ignore lint/nursery/useSortedClasses: biome is unable to sort the custom classes for 3xl and 4xl breakpoints
|
|
1099
|
+
'**:data-[slot="media"]:h-80 sm:**:data-[slot="media"]:h-[25rem] md:**:data-[slot="media"]:h-[30rem] lg:**:data-[slot="media"]:h-[35rem] xl:**:data-[slot="media"]:h-[40rem] 2xl:**:data-[slot="media"]:h-[42rem] 3xl:**:data-[slot="media"]:h-[48rem] 4xl:**:data-[slot="media"]:h-[53rem]',
|
|
1100
|
+
'**:data-[slot="media"]:*:h-[inherit]',
|
|
1101
|
+
// biome-ignore lint/nursery/useSortedClasses: biome is unable to sort the custom classes for 3xl and 4xl breakpoints
|
|
1102
|
+
'*:data-[slot="carousel"]:h-80 sm:*:data-[slot="carousel"]:h-[25rem] md:*:data-[slot="carousel"]:h-[30rem] lg:*:data-[slot="carousel"]:h-[35rem] xl:*:data-[slot="carousel"]:h-[40rem] 2xl:*:data-[slot="carousel"]:h-[42rem] 3xl:*:data-[slot="carousel"]:h-[48rem] 4xl:*:data-[slot="carousel"]:h-[53rem]',
|
|
1103
|
+
'*:data-[slot="carousel"]:w-full!',
|
|
1104
|
+
// Override aspect ratio of the media and carousel-item slots (since we can not use aspect for full-bleed layout)
|
|
1105
|
+
'**:data-[slot="carousel-item"]:data-[slot="media"]:*:aspect-none',
|
|
1106
|
+
// break out the carousel out of the container
|
|
1107
|
+
'**:data-[slot="carousel-items-container"]:absolute **:data-[slot="carousel-items-container"]:right-0 **:data-[slot="carousel-items-container"]:left-0 **:data-[slot="carousel-items-container"]:h-[inherit]',
|
|
1108
|
+
// Positions the carousel controls inside the carousel
|
|
1109
|
+
'**:data-[slot="carousel-controls"]:z-10 **:data-[slot="carousel-controls"]:mb-4 *:data-[slot="carousel"]:flex *:data-[slot="carousel"]:items-end *:data-[slot="carousel"]:justify-end'
|
|
1110
|
+
],
|
|
1111
|
+
'two-column': [
|
|
1112
|
+
'lg:items-center lg:*:col-span-6',
|
|
1113
|
+
// Vertical spacing in the <Content>
|
|
1114
|
+
'lg:*:data-[slot="content"]:gap-y-7',
|
|
1115
|
+
nonFullBleedAspectRatiosForSmallScreens,
|
|
1116
|
+
// Set media aspect ratio to 1:1 (square)
|
|
1117
|
+
'lg:*:data-[slot="media"]:*:aspect-square'
|
|
1118
|
+
]
|
|
1119
|
+
}
|
|
1120
|
+
},
|
|
1121
|
+
compoundVariants: [
|
|
1122
|
+
{
|
|
1123
|
+
variant: [
|
|
1124
|
+
'standard',
|
|
1125
|
+
'two-column'
|
|
1126
|
+
],
|
|
1127
|
+
className: [
|
|
1128
|
+
'*:data-[slot="media"]:*:rounded-3xl',
|
|
1129
|
+
'**:data-[slot="carousel-controls"]:absolute *:data-[slot="carousel"]:relative **:data-[slot="carousel-controls"]:right-4 **:data-[slot="carousel-controls"]:bottom-4 **:data-[slot="carousel-container"]:rounded-3xl'
|
|
1130
|
+
]
|
|
1131
|
+
}
|
|
1132
|
+
],
|
|
1133
|
+
defaultVariants: {
|
|
1134
|
+
variant: 'standard'
|
|
1135
|
+
}
|
|
1136
|
+
});
|
|
1137
|
+
const Hero = ({ variant, className, children, ...rest })=>{
|
|
1138
|
+
const variantsClassName = variants({
|
|
1139
|
+
variant,
|
|
1140
|
+
className
|
|
1141
|
+
});
|
|
1142
|
+
return /*#__PURE__*/ jsx(Provider, {
|
|
1143
|
+
values: [
|
|
1144
|
+
[
|
|
1145
|
+
HeroContext,
|
|
1146
|
+
{
|
|
1147
|
+
variant
|
|
1148
|
+
}
|
|
1149
|
+
],
|
|
1150
|
+
[
|
|
1151
|
+
HeadingContext,
|
|
1152
|
+
{
|
|
1153
|
+
// Sets the default heading size for the Hero based on the variant
|
|
1154
|
+
size: variant === 'two-column' ? 'xl' : 'l',
|
|
1155
|
+
className: // word-break:break-word to allow long words to break (this is necessary to make hyphens work in grid containers in Safari)
|
|
1156
|
+
'hyphens-auto text-pretty [word-break:break-word]'
|
|
1157
|
+
}
|
|
1158
|
+
],
|
|
1159
|
+
[
|
|
1160
|
+
GroupContext,
|
|
1161
|
+
{
|
|
1162
|
+
// Prevents the group from being announced as a group by screen readers
|
|
1163
|
+
// The Group component is used to group the Hero's CTA buttons together visually, and has no semantic meaning
|
|
1164
|
+
role: 'presentation',
|
|
1165
|
+
className: 'flex flex-wrap gap-3 *:w-fit'
|
|
1166
|
+
}
|
|
1167
|
+
]
|
|
1168
|
+
],
|
|
1169
|
+
children: /*#__PURE__*/ jsx("div", {
|
|
1170
|
+
className: cx(variantsClassName, className),
|
|
1171
|
+
...rest,
|
|
1172
|
+
children: children
|
|
1173
|
+
})
|
|
1174
|
+
});
|
|
1175
|
+
};
|
|
1176
|
+
|
|
988
1177
|
/**
|
|
989
1178
|
* Hook that detects the user's preference for reduced motion.
|
|
990
1179
|
*
|
|
@@ -1008,6 +1197,32 @@ const cardLinkVariants = cva({
|
|
|
1008
1197
|
return prefersReducedMotion;
|
|
1009
1198
|
}
|
|
1010
1199
|
|
|
1200
|
+
/**
|
|
1201
|
+
* A helper to get the prev/next button from the carousel DOM
|
|
1202
|
+
* @param ref The carousel ref
|
|
1203
|
+
* @param slot The slot of the button to get ('prev' or 'next')
|
|
1204
|
+
* @returns The button element, or undefined if not found
|
|
1205
|
+
*/ const getCarouselButton = (ref, slot)=>ref.current?.querySelector(`button[slot="${slot}"]`);
|
|
1206
|
+
/**
|
|
1207
|
+
* Focus the first focusable element in the currently snapped slide
|
|
1208
|
+
* @param emblaApi The embla carousel API instance
|
|
1209
|
+
*/ const focusElementInSnappedSlide = (emblaApi)=>{
|
|
1210
|
+
if (!emblaApi) {
|
|
1211
|
+
return;
|
|
1212
|
+
}
|
|
1213
|
+
const index = emblaApi.selectedScrollSnap();
|
|
1214
|
+
const targetSlide = emblaApi.slideNodes()[index];
|
|
1215
|
+
if (!targetSlide) {
|
|
1216
|
+
return;
|
|
1217
|
+
}
|
|
1218
|
+
// Find first focusable element in the slide
|
|
1219
|
+
const focusableElement = targetSlide.querySelector('a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])');
|
|
1220
|
+
// Use preventScroll to avoid the browser's default scroll-into-view behavior
|
|
1221
|
+
// which would conflict with embla's scroll animation
|
|
1222
|
+
focusableElement?.focus({
|
|
1223
|
+
preventScroll: true
|
|
1224
|
+
});
|
|
1225
|
+
};
|
|
1011
1226
|
const Carousel = ({ autoPlayDelay, align = 'center', children, initialIndex = 0, orientation = 'horizontal', onSelect, onSettled, loop = false, scrollGestures = false, ref, ...rest })=>{
|
|
1012
1227
|
const carouselRef = useRef(null);
|
|
1013
1228
|
const prefersReducedMotion = usePrefersReducedMotion() ?? false;
|
|
@@ -1040,6 +1255,10 @@ const Carousel = ({ autoPlayDelay, align = 'center', children, initialIndex = 0,
|
|
|
1040
1255
|
const [slidesInView, setSlidesInView] = useState([
|
|
1041
1256
|
initialIndex
|
|
1042
1257
|
]);
|
|
1258
|
+
// We need some default values here. The proper initial values will be set by the embla init handler later
|
|
1259
|
+
// for the default values, assume that we can scroll next, but for prev only if looping is enabled
|
|
1260
|
+
const [canScrollNext, setCanScrollNext] = useState(true);
|
|
1261
|
+
const [canScrollPrev, setCanScrollPrev] = useState(loop);
|
|
1043
1262
|
const previousSettledScrollIndex = useRef(initialIndex);
|
|
1044
1263
|
useEffect(()=>{
|
|
1045
1264
|
if (!emblaApi) {
|
|
@@ -1050,6 +1269,8 @@ const Carousel = ({ autoPlayDelay, align = 'center', children, initialIndex = 0,
|
|
|
1050
1269
|
switch(type){
|
|
1051
1270
|
case 'select':
|
|
1052
1271
|
onSelect?.(scrollSnapIndex);
|
|
1272
|
+
setCanScrollNext(emblaApi.canScrollNext());
|
|
1273
|
+
setCanScrollPrev(emblaApi.canScrollPrev());
|
|
1053
1274
|
break;
|
|
1054
1275
|
case 'settle':
|
|
1055
1276
|
{
|
|
@@ -1066,15 +1287,23 @@ const Carousel = ({ autoPlayDelay, align = 'center', children, initialIndex = 0,
|
|
|
1066
1287
|
setSlidesInView(emblaApi.slidesInView());
|
|
1067
1288
|
break;
|
|
1068
1289
|
}
|
|
1290
|
+
case 'init':
|
|
1291
|
+
{
|
|
1292
|
+
setCanScrollNext(emblaApi.canScrollNext());
|
|
1293
|
+
setCanScrollPrev(emblaApi.canScrollPrev());
|
|
1294
|
+
break;
|
|
1295
|
+
}
|
|
1069
1296
|
}
|
|
1070
1297
|
};
|
|
1071
1298
|
emblaApi.on('select', emblaHandler);
|
|
1072
1299
|
emblaApi.on('slidesInView', emblaHandler);
|
|
1073
1300
|
emblaApi.on('settle', emblaHandler);
|
|
1301
|
+
emblaApi.on('init', emblaHandler);
|
|
1074
1302
|
return ()=>{
|
|
1075
1303
|
emblaApi.off('select', emblaHandler);
|
|
1076
1304
|
emblaApi.off('settle', emblaHandler);
|
|
1077
1305
|
emblaApi.off('slidesInView', emblaHandler);
|
|
1306
|
+
emblaApi.off('init', emblaHandler);
|
|
1078
1307
|
};
|
|
1079
1308
|
}, [
|
|
1080
1309
|
emblaApi,
|
|
@@ -1088,8 +1317,8 @@ const Carousel = ({ autoPlayDelay, align = 'center', children, initialIndex = 0,
|
|
|
1088
1317
|
emblaApi.plugins().autoplay?.stop();
|
|
1089
1318
|
emblaApi.scrollNext(prefersReducedMotion);
|
|
1090
1319
|
// we need to move focus if we are about to disable this button due to start/end of carousel
|
|
1091
|
-
if (!loop && !emblaApi.canScrollNext() && carouselRef
|
|
1092
|
-
carouselRef
|
|
1320
|
+
if (!loop && !emblaApi.canScrollNext() && getCarouselButton(carouselRef, 'next')?.matches(':focus-visible')) {
|
|
1321
|
+
getCarouselButton(carouselRef, 'prev')?.focus();
|
|
1093
1322
|
}
|
|
1094
1323
|
}, [
|
|
1095
1324
|
emblaApi,
|
|
@@ -1103,8 +1332,8 @@ const Carousel = ({ autoPlayDelay, align = 'center', children, initialIndex = 0,
|
|
|
1103
1332
|
emblaApi.plugins().autoplay?.stop();
|
|
1104
1333
|
emblaApi.scrollPrev(prefersReducedMotion);
|
|
1105
1334
|
// we need to move focus if we are about to disable this button due to start/end of carousel
|
|
1106
|
-
if (!loop && !emblaApi.canScrollPrev() && carouselRef
|
|
1107
|
-
carouselRef
|
|
1335
|
+
if (!loop && !emblaApi.canScrollPrev() && getCarouselButton(carouselRef, 'prev')?.matches(':focus-visible')) {
|
|
1336
|
+
getCarouselButton(carouselRef, 'next')?.focus();
|
|
1108
1337
|
}
|
|
1109
1338
|
}, [
|
|
1110
1339
|
emblaApi,
|
|
@@ -1113,24 +1342,40 @@ const Carousel = ({ autoPlayDelay, align = 'center', children, initialIndex = 0,
|
|
|
1113
1342
|
]);
|
|
1114
1343
|
const locale = _useLocale();
|
|
1115
1344
|
const handleKeyDown = useCallback((e)=>{
|
|
1345
|
+
// Check if either prev or next button has focus - if so, don't override their focus management
|
|
1346
|
+
const carouselButtonHasFocus = getCarouselButton(carouselRef, 'prev')?.matches(':focus-visible') || getCarouselButton(carouselRef, 'next')?.matches(':focus-visible');
|
|
1116
1347
|
if (e.key === 'ArrowRight' && !e.repeat) {
|
|
1117
1348
|
handleNextPress();
|
|
1349
|
+
// Focus first focusable element in the next slide, unless a carousel button has focus
|
|
1350
|
+
if (!carouselButtonHasFocus) {
|
|
1351
|
+
focusElementInSnappedSlide(emblaApi);
|
|
1352
|
+
}
|
|
1118
1353
|
} else if (e.key === 'ArrowLeft' && !e.repeat) {
|
|
1119
1354
|
handlePrevPress();
|
|
1355
|
+
// Focus first focusable element in the previous slide, unless a carousel button has focus
|
|
1356
|
+
if (!carouselButtonHasFocus) {
|
|
1357
|
+
focusElementInSnappedSlide(emblaApi);
|
|
1358
|
+
}
|
|
1120
1359
|
}
|
|
1121
1360
|
}, [
|
|
1122
1361
|
handleNextPress,
|
|
1123
|
-
handlePrevPress
|
|
1362
|
+
handlePrevPress,
|
|
1363
|
+
emblaApi
|
|
1124
1364
|
]);
|
|
1125
|
-
|
|
1365
|
+
const hasHeroContext = !!useContext(HeroContext);
|
|
1366
|
+
const nextPrevStyles = hasHeroContext ? {
|
|
1367
|
+
color: 'white',
|
|
1368
|
+
variant: 'primary'
|
|
1369
|
+
} : {
|
|
1370
|
+
variant: 'tertiary'
|
|
1371
|
+
};
|
|
1372
|
+
return(// biome-ignore lint/a11y/noStaticElementInteractions: This is just to enhance keyboard navigation, this is not a replacement for proper focusable elements inside the carousel
|
|
1126
1373
|
/*#__PURE__*/ jsx("div", {
|
|
1127
1374
|
...rest,
|
|
1128
1375
|
"data-orientation": orientation,
|
|
1129
1376
|
"data-slot": "carousel",
|
|
1130
1377
|
ref: mergeRefs(ref, carouselRef),
|
|
1131
1378
|
onKeyDown: handleKeyDown,
|
|
1132
|
-
role: "region",
|
|
1133
|
-
"aria-label": translations$1.carousel[locale],
|
|
1134
1379
|
children: /*#__PURE__*/ jsx(Provider, {
|
|
1135
1380
|
values: [
|
|
1136
1381
|
[
|
|
@@ -1148,13 +1393,15 @@ const Carousel = ({ autoPlayDelay, align = 'center', children, initialIndex = 0,
|
|
|
1148
1393
|
[DEFAULT_SLOT]: {},
|
|
1149
1394
|
prev: {
|
|
1150
1395
|
'aria-label': translations$1.previous[locale],
|
|
1151
|
-
isDisabled: !
|
|
1152
|
-
onPress: handlePrevPress
|
|
1396
|
+
isDisabled: !canScrollPrev,
|
|
1397
|
+
onPress: handlePrevPress,
|
|
1398
|
+
...nextPrevStyles
|
|
1153
1399
|
},
|
|
1154
1400
|
next: {
|
|
1155
1401
|
'aria-label': translations$1.next[locale],
|
|
1156
|
-
isDisabled: !
|
|
1157
|
-
onPress: handleNextPress
|
|
1402
|
+
isDisabled: !canScrollNext,
|
|
1403
|
+
onPress: handleNextPress,
|
|
1404
|
+
...nextPrevStyles
|
|
1158
1405
|
}
|
|
1159
1406
|
}
|
|
1160
1407
|
}
|
|
@@ -1180,17 +1427,11 @@ const CarouselItemsContainer = ({ children, className, ...rest })=>{
|
|
|
1180
1427
|
});
|
|
1181
1428
|
};
|
|
1182
1429
|
const CarouselItems = ({ className, children })=>{
|
|
1183
|
-
const {
|
|
1430
|
+
const { orientation } = useContext(CarouselContext);
|
|
1184
1431
|
return /*#__PURE__*/ jsx("div", {
|
|
1185
1432
|
className: cx(className, 'flex', orientation === 'vertical' && 'flex-col'),
|
|
1186
1433
|
"data-slot": "carousel-items",
|
|
1187
|
-
children:
|
|
1188
|
-
if (/*#__PURE__*/ isValidElement(child)) {
|
|
1189
|
-
return /*#__PURE__*/ cloneElement(child, {
|
|
1190
|
-
inert: slidesInView.includes(index) ? undefined : true
|
|
1191
|
-
});
|
|
1192
|
-
}
|
|
1193
|
-
})
|
|
1434
|
+
children: children
|
|
1194
1435
|
});
|
|
1195
1436
|
};
|
|
1196
1437
|
/**
|
|
@@ -1200,6 +1441,8 @@ const CarouselItems = ({ className, children })=>{
|
|
|
1200
1441
|
className: cx(className, 'flex justify-end gap-x-2'),
|
|
1201
1442
|
"data-slot": "carousel-controls",
|
|
1202
1443
|
...rest,
|
|
1444
|
+
// All items of the carousel are accessible to the screen reader at all times, so these controls will only confuse screen reader users
|
|
1445
|
+
"aria-hidden": "true",
|
|
1203
1446
|
children: children
|
|
1204
1447
|
});
|
|
1205
1448
|
const carouselButtonVariants = cva({
|
|
@@ -1242,7 +1485,7 @@ const carouselButtonIconSlotVariants = cva({
|
|
|
1242
1485
|
}
|
|
1243
1486
|
]
|
|
1244
1487
|
});
|
|
1245
|
-
const CarouselButton = ({ className, isIconOnly = true,
|
|
1488
|
+
const CarouselButton = ({ className, isIconOnly = true, slot, ...rest })=>{
|
|
1246
1489
|
const { orientation } = useContext(CarouselContext);
|
|
1247
1490
|
return /*#__PURE__*/ jsx(Button, {
|
|
1248
1491
|
className: carouselButtonVariants({
|
|
@@ -1250,8 +1493,6 @@ const CarouselButton = ({ className, isIconOnly = true, color = 'white', variant
|
|
|
1250
1493
|
}),
|
|
1251
1494
|
isIconOnly: isIconOnly,
|
|
1252
1495
|
slot: slot,
|
|
1253
|
-
variant: variant,
|
|
1254
|
-
color: color,
|
|
1255
1496
|
...rest,
|
|
1256
1497
|
children: /*#__PURE__*/ jsx(ChevronRight, {
|
|
1257
1498
|
className: carouselButtonIconSlotVariants({
|
|
@@ -1281,49 +1522,6 @@ const CarouselItem = ({ className, children, ...rest })=>{
|
|
|
1281
1522
|
});
|
|
1282
1523
|
};
|
|
1283
1524
|
|
|
1284
|
-
const formField = cx('group flex flex-col gap-2');
|
|
1285
|
-
const formFieldError = cx('w-fit bg-red-light px-2 py-1 text-red text-sm leading-6', 'group-data-[slot=file-upload]:rounded-lg');
|
|
1286
|
-
const input = cva({
|
|
1287
|
-
base: [
|
|
1288
|
-
// All inputs should always have a white background (this also ensures that type="search" on Safri doesn't get a gray background)
|
|
1289
|
-
'bg-white',
|
|
1290
|
-
// Use box-content to enable auto width based on number of characters (size)
|
|
1291
|
-
// Setting min-height to prevent the input from collapsing in Safari
|
|
1292
|
-
// Combining these with a padding-y as base classes makes it easier to standardize the height (44px) of all inputs
|
|
1293
|
-
'box-content min-h-6 py-2.5',
|
|
1294
|
-
'rounded-md font-normal text-base leading-6 placeholder-[#727070] outline-hidden ring-1 ring-black',
|
|
1295
|
-
// invalid styles
|
|
1296
|
-
'group-data-invalid:ring-focus group-data-invalid:ring-red',
|
|
1297
|
-
// Fix invisible ring on safari: https://github.com/tailwindlabs/tailwindcss.com/issues/1135
|
|
1298
|
-
'appearance-none'
|
|
1299
|
-
],
|
|
1300
|
-
variants: {
|
|
1301
|
-
// Focus rings. Can either be :focus or :focus-visible based on the needs of the particular component.
|
|
1302
|
-
focusModifier: {
|
|
1303
|
-
focus: 'focus:ring-focus group-data-invalid:focus:ring-3 group-data-invalid:focus:ring-red',
|
|
1304
|
-
visible: 'data-focus-visible:ring-focus group-data-invalid:data-focus-visible:ring-3 group-data-invalid:data-focus-visible:ring-red'
|
|
1305
|
-
},
|
|
1306
|
-
isGrouped: {
|
|
1307
|
-
false: 'px-3',
|
|
1308
|
-
true: '!ring-0 flex-1'
|
|
1309
|
-
}
|
|
1310
|
-
},
|
|
1311
|
-
defaultVariants: {
|
|
1312
|
-
focusModifier: 'focus',
|
|
1313
|
-
isGrouped: false
|
|
1314
|
-
}
|
|
1315
|
-
});
|
|
1316
|
-
const inputGroup = cx([
|
|
1317
|
-
'inline-flex items-center gap-3 overflow-hidden rounded-md bg-white px-3 text-base ring-1 ring-black focus-within:ring-focus',
|
|
1318
|
-
'group-data-invalid:ring-focus group-data-invalid:ring-red group-data-invalid:focus-within:ring-3 group-data-invalid:focus-within:ring-red'
|
|
1319
|
-
]);
|
|
1320
|
-
const dropdown = {
|
|
1321
|
-
popover: cx('data-entering:fade-in data-exiting:fade-out min-w-(--trigger-width) overflow-y-auto rounded-md border border-black bg-white shadow-sm data-entering:animate-in data-exiting:animate-out'),
|
|
1322
|
-
// overflow-x-hidden is needed to prevent visible vertical scrollbars from overflowing the border radius of the popover
|
|
1323
|
-
listbox: cx('max-h-100 overflow-x-hidden text-sm outline-hidden'),
|
|
1324
|
-
chevronIcon: cx('text-base transition-transform duration-150 group-data-open:rotate-180 motion-reduce:transition-none')
|
|
1325
|
-
};
|
|
1326
|
-
|
|
1327
1525
|
function ErrorMessage(props) {
|
|
1328
1526
|
const { children, className, ...restProps } = props;
|
|
1329
1527
|
return /*#__PURE__*/ jsx(Text, {
|
|
@@ -1430,7 +1628,7 @@ function Description(props) {
|
|
|
1430
1628
|
function Label(props) {
|
|
1431
1629
|
const { children, className, ...restProps } = props;
|
|
1432
1630
|
return /*#__PURE__*/ jsx(Label$1, {
|
|
1433
|
-
className: cx(className, 'font-
|
|
1631
|
+
className: cx(className, 'font-medium leading-7'),
|
|
1434
1632
|
...restProps,
|
|
1435
1633
|
children: children
|
|
1436
1634
|
});
|
|
@@ -1913,185 +2111,77 @@ function GrunnmurenProvider({ children, locale = 'nb', navigate, useHref }) {
|
|
|
1913
2111
|
});
|
|
1914
2112
|
}
|
|
1915
2113
|
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
'
|
|
1920
|
-
|
|
1921
|
-
'
|
|
1922
|
-
|
|
1923
|
-
'*:
|
|
1924
|
-
// Other elements than <Content> and <Media> (e.g. CTA, SVG logo or Badge) take up 3 columns on medium screens and above, and are right aligned
|
|
1925
|
-
'lg:*:not-data-[slot="content"]:not-data-[slot="media"]:not-data-[slot="carousel"]:col-span-3 lg:*:not-data-[slot="content"]:not-data-[slot="media"]:justify-self-end',
|
|
1926
|
-
// <Media> and <Carousel> content takes up the full width on medium screens and above
|
|
1927
|
-
'lg:*:data-[slot="media"]:col-span-full *:data-[slot="media"]:*:w-full',
|
|
1928
|
-
'lg:*:data-[slot="carousel"]:col-span-full',
|
|
1929
|
-
// Aligns <Content> and any element beside it (e.g. <Media>, <Badge>, <CTA> etc.) to the bottom of the <Content> container
|
|
1930
|
-
'lg:items-end'
|
|
2114
|
+
const linkStyles = [
|
|
2115
|
+
'*:data-[slot=link]:flex',
|
|
2116
|
+
'*:data-[slot=link]:w-full',
|
|
2117
|
+
'*:data-[slot=link]:justify-between',
|
|
2118
|
+
'*:data-[slot=link]:gap-x-2',
|
|
2119
|
+
'*:data-[slot=link]:py-3.5',
|
|
2120
|
+
'*:data-[slot=link]:no-underline',
|
|
2121
|
+
'*:data-[slot=link]:focus-visible:outline-focus'
|
|
1931
2122
|
];
|
|
1932
|
-
const
|
|
1933
|
-
const variants = cva({
|
|
2123
|
+
const linkListContainerVariants = cva({
|
|
1934
2124
|
base: [
|
|
1935
|
-
'
|
|
1936
|
-
|
|
1937
|
-
'
|
|
1938
|
-
'
|
|
1939
|
-
|
|
1940
|
-
'*:data-[slot=
|
|
1941
|
-
// Vertical spacing in the <Content>
|
|
1942
|
-
'*:data-[slot="content"]:gap-y-3',
|
|
1943
|
-
// Make sure <Media> content fills any available vertical and horizontal space
|
|
1944
|
-
'*:data-[slot="media"]:*:object-cover',
|
|
1945
|
-
'*:data-[slot="carousel"]:overflow-hidden *:data-[slot="carousel"]:rounded-3xl',
|
|
1946
|
-
// Make the carousel items full width, so we scroll one at a time
|
|
1947
|
-
'**:data-[slot="carousel-item"]:basis-full'
|
|
2125
|
+
'*:data-[slot=link-list]:overflow-visible',
|
|
2126
|
+
'*:data-[slot=heading]:p-1.25',
|
|
2127
|
+
'*:data-[slot=heading]:*:data-[slot=link]:py-2.25',
|
|
2128
|
+
'**:[svg]:text-base',
|
|
2129
|
+
'has-data-[slot=heading]:*:data-[slot=link-list]:overflow-visible',
|
|
2130
|
+
'*:data-[slot=heading]:has-not:*:data-[slot=link]:my-2.25'
|
|
1948
2131
|
],
|
|
1949
2132
|
variants: {
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
* */ variant: {
|
|
1954
|
-
standard: [
|
|
1955
|
-
oneColumnLayout,
|
|
1956
|
-
nonFullBleedAspectRatiosForSmallScreens,
|
|
1957
|
-
'lg:*:data-[slot="media"]:*:aspect-2/1'
|
|
1958
|
-
],
|
|
1959
|
-
'full-bleed': [
|
|
1960
|
-
oneColumnLayout,
|
|
1961
|
-
// Position the media and carousel content to fill the entire viewport width
|
|
1962
|
-
'*:data-[slot="media"]:*:absolute *:data-[slot="media"]:*:left-0',
|
|
1963
|
-
// Special case for Carousel, where the Media is nested inside a CarouselItem
|
|
1964
|
-
'*:data-[slot="carousel"]:**:data-[slot="media"]:w-full',
|
|
1965
|
-
// Match the heights of the <Media> or <Carousel> wrapper for the Media content (e.g. image, VideoLoop, video etc.)
|
|
1966
|
-
// This is necessary due to the absolute positioning of the media and carousel containers in this variant
|
|
1967
|
-
// biome-ignore lint/nursery/useSortedClasses: biome is unable to sort the custom classes for 3xl and 4xl breakpoints
|
|
1968
|
-
'**:data-[slot="media"]:h-80 sm:**:data-[slot="media"]:h-[25rem] md:**:data-[slot="media"]:h-[30rem] lg:**:data-[slot="media"]:h-[35rem] xl:**:data-[slot="media"]:h-[40rem] 2xl:**:data-[slot="media"]:h-[42rem] 3xl:**:data-[slot="media"]:h-[48rem] 4xl:**:data-[slot="media"]:h-[53rem]',
|
|
1969
|
-
'**:data-[slot="media"]:*:h-[inherit]',
|
|
1970
|
-
// biome-ignore lint/nursery/useSortedClasses: biome is unable to sort the custom classes for 3xl and 4xl breakpoints
|
|
1971
|
-
'*:data-[slot="carousel"]:h-80 sm:*:data-[slot="carousel"]:h-[25rem] md:*:data-[slot="carousel"]:h-[30rem] lg:*:data-[slot="carousel"]:h-[35rem] xl:*:data-[slot="carousel"]:h-[40rem] 2xl:*:data-[slot="carousel"]:h-[42rem] 3xl:*:data-[slot="carousel"]:h-[48rem] 4xl:*:data-[slot="carousel"]:h-[53rem]',
|
|
1972
|
-
'*:data-[slot="carousel"]:w-full!',
|
|
1973
|
-
// Override aspect ratio of the media and carousel-item slots (since we can not use aspect for full-bleed layout)
|
|
1974
|
-
'**:data-[slot="carousel-item"]:data-[slot="media"]:*:aspect-none',
|
|
1975
|
-
// break out the carousel out of the container
|
|
1976
|
-
'**:data-[slot="carousel-items-container"]:absolute **:data-[slot="carousel-items-container"]:right-0 **:data-[slot="carousel-items-container"]:left-0 **:data-[slot="carousel-items-container"]:h-[inherit]',
|
|
1977
|
-
// Positions the carousel controls inside the carousel
|
|
1978
|
-
'**:data-[slot="carousel-controls"]:z-10 **:data-[slot="carousel-controls"]:mb-4 *:data-[slot="carousel"]:flex *:data-[slot="carousel"]:items-end *:data-[slot="carousel"]:justify-end'
|
|
1979
|
-
],
|
|
1980
|
-
'two-column': [
|
|
1981
|
-
'lg:items-center lg:*:col-span-6',
|
|
1982
|
-
// Vertical spacing in the <Content>
|
|
1983
|
-
'lg:*:data-[slot="content"]:gap-y-7',
|
|
1984
|
-
nonFullBleedAspectRatiosForSmallScreens,
|
|
1985
|
-
// Set media aspect ratio to 1:1 (square)
|
|
1986
|
-
'lg:*:data-[slot="media"]:*:aspect-square'
|
|
1987
|
-
]
|
|
2133
|
+
layout: {
|
|
2134
|
+
stack: null,
|
|
2135
|
+
grid: '@container'
|
|
1988
2136
|
}
|
|
1989
2137
|
},
|
|
1990
|
-
compoundVariants: [
|
|
1991
|
-
{
|
|
1992
|
-
variant: [
|
|
1993
|
-
'standard',
|
|
1994
|
-
'two-column'
|
|
1995
|
-
],
|
|
1996
|
-
className: [
|
|
1997
|
-
'*:data-[slot="media"]:*:rounded-3xl',
|
|
1998
|
-
'**:data-[slot="carousel-controls"]:absolute *:data-[slot="carousel"]:relative **:data-[slot="carousel-controls"]:right-4 **:data-[slot="carousel-controls"]:bottom-4 **:data-[slot="carousel-container"]:rounded-3xl'
|
|
1999
|
-
]
|
|
2000
|
-
}
|
|
2001
|
-
],
|
|
2002
2138
|
defaultVariants: {
|
|
2003
|
-
|
|
2139
|
+
layout: 'stack'
|
|
2004
2140
|
}
|
|
2005
2141
|
});
|
|
2006
|
-
const
|
|
2007
|
-
const variantsClassName = variants({
|
|
2008
|
-
variant,
|
|
2009
|
-
className
|
|
2010
|
-
});
|
|
2011
|
-
return /*#__PURE__*/ jsx(Provider, {
|
|
2142
|
+
const LinkListContainer = ({ className, layout = 'stack', ...props })=>/*#__PURE__*/ jsx(Provider, {
|
|
2012
2143
|
values: [
|
|
2013
2144
|
[
|
|
2014
2145
|
HeadingContext,
|
|
2015
2146
|
{
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
className: // word-break:break-word to allow long words to break (this is necessary to make hyphens work in grid containers in Safari)
|
|
2019
|
-
'hyphens-auto text-pretty [word-break:break-word]'
|
|
2020
|
-
}
|
|
2021
|
-
],
|
|
2022
|
-
[
|
|
2023
|
-
GroupContext,
|
|
2024
|
-
{
|
|
2025
|
-
// Prevents the group from being announced as a group by screen readers
|
|
2026
|
-
// The Group component is used to group the Hero's CTA buttons together visually, and has no semantic meaning
|
|
2027
|
-
role: 'presentation',
|
|
2028
|
-
className: 'flex flex-wrap gap-3 *:w-fit'
|
|
2147
|
+
size: 'm',
|
|
2148
|
+
className: cx(linkStyles)
|
|
2029
2149
|
}
|
|
2030
2150
|
]
|
|
2031
2151
|
],
|
|
2032
2152
|
children: /*#__PURE__*/ jsx("div", {
|
|
2033
|
-
className: cx(variantsClassName, className),
|
|
2034
|
-
...rest,
|
|
2035
|
-
children: children
|
|
2036
|
-
})
|
|
2037
|
-
});
|
|
2038
|
-
};
|
|
2039
|
-
|
|
2040
|
-
// Sets the correct icons for each link in the link list
|
|
2041
|
-
const _LinkProvider = ({ children })=>/*#__PURE__*/ jsx(Provider, {
|
|
2042
|
-
values: [
|
|
2043
|
-
[
|
|
2044
|
-
_LinkContext,
|
|
2045
|
-
{
|
|
2046
|
-
_innerWrapper: ({ children, download, rel })=>(values)=>{
|
|
2047
|
-
let Icon = ArrowRight;
|
|
2048
|
-
if (download) {
|
|
2049
|
-
Icon = Download;
|
|
2050
|
-
} else if (rel?.includes('external')) {
|
|
2051
|
-
Icon = LinkExternal;
|
|
2052
|
-
}
|
|
2053
|
-
return /*#__PURE__*/ jsxs(Fragment, {
|
|
2054
|
-
children: [
|
|
2055
|
-
typeof children === 'function' ? children({
|
|
2056
|
-
...values,
|
|
2057
|
-
defaultChildren: null
|
|
2058
|
-
}) : children,
|
|
2059
|
-
/*#__PURE__*/ jsx(Icon, {})
|
|
2060
|
-
]
|
|
2061
|
-
});
|
|
2062
|
-
}
|
|
2063
|
-
}
|
|
2064
|
-
]
|
|
2065
|
-
],
|
|
2066
|
-
children: children
|
|
2067
|
-
});
|
|
2068
|
-
const LinkListContainer = ({ className, ...restProps })=>// Dual providers makes for easier typing and more readable code
|
|
2069
|
-
/*#__PURE__*/ jsx(Provider, {
|
|
2070
|
-
values: [
|
|
2071
|
-
[
|
|
2072
|
-
HeadingContext,
|
|
2073
|
-
{
|
|
2074
|
-
size: 'm'
|
|
2075
|
-
}
|
|
2076
|
-
]
|
|
2077
|
-
],
|
|
2078
|
-
children: /*#__PURE__*/ jsx(_LinkProvider, {
|
|
2079
|
-
children: /*#__PURE__*/ jsx("div", {
|
|
2080
|
-
className: cx(className, 'link-list-container'),
|
|
2081
|
-
...restProps
|
|
2082
|
-
})
|
|
2083
|
-
})
|
|
2084
|
-
});
|
|
2085
|
-
const LinkList = (props)=>/*#__PURE__*/ jsx(_LinkProvider, {
|
|
2086
|
-
children: /*#__PURE__*/ jsx("ul", {
|
|
2087
2153
|
...props,
|
|
2088
|
-
|
|
2154
|
+
className: linkListContainerVariants({
|
|
2155
|
+
className,
|
|
2156
|
+
layout
|
|
2157
|
+
}),
|
|
2158
|
+
"data-layout": layout,
|
|
2159
|
+
"data-slot": "link-list-container"
|
|
2089
2160
|
})
|
|
2090
2161
|
});
|
|
2091
|
-
const
|
|
2162
|
+
const LinkList = ({ className, ...restProps })=>/*#__PURE__*/ jsx("ul", {
|
|
2163
|
+
...restProps,
|
|
2164
|
+
"data-slot": "link-list",
|
|
2165
|
+
className: cx(/**
|
|
2166
|
+
* Hides dividers at the top of the list (overflow-y)
|
|
2167
|
+
* while preventing arrow icons from overflowing container when animated to the right (overflow-x)
|
|
2168
|
+
*/ 'grid min-w-fit auto-rows-max gap-y-px overflow-hidden', className)
|
|
2169
|
+
});
|
|
2170
|
+
const LinkListItem = ({ children, className, ...props })=>{
|
|
2171
|
+
const child = Children.only(children);
|
|
2172
|
+
const childProps = /*#__PURE__*/ isValidElement(child) ? child.props : {};
|
|
2173
|
+
const animateIcon = childProps.animateIcon || childProps.download ? 'down' : childProps.rel?.includes('external') ? 'up-right' : 'right';
|
|
2174
|
+
const iconRight = childProps['~iconRight'] || childProps.download ? /*#__PURE__*/ jsx(Download, {}) : childProps.rel?.includes('external') ? /*#__PURE__*/ jsx(LinkExternal, {}) : /*#__PURE__*/ jsx(ArrowRight, {});
|
|
2175
|
+
return /*#__PURE__*/ jsx("li", {
|
|
2092
2176
|
...props,
|
|
2093
|
-
|
|
2177
|
+
className: cx(className, 'after:-top-px relative p-1.25 after:absolute after:right-0 after:left-0 after:h-px after:w-full after:bg-gray-light', '*:data-[slot=link]:paragraph', ...linkStyles),
|
|
2178
|
+
"data-slot": "link-list-item",
|
|
2179
|
+
children: /*#__PURE__*/ isValidElement(child) && /*#__PURE__*/ cloneElement(child, {
|
|
2180
|
+
animateIcon,
|
|
2181
|
+
'~iconRight': iconRight
|
|
2182
|
+
})
|
|
2094
2183
|
});
|
|
2184
|
+
};
|
|
2095
2185
|
|
|
2096
2186
|
const DialogTrigger = (props)=>/*#__PURE__*/ jsx(DialogTrigger$1, {
|
|
2097
2187
|
...props
|
|
@@ -2240,44 +2330,6 @@ function NumberField(props) {
|
|
|
2240
2330
|
});
|
|
2241
2331
|
}
|
|
2242
2332
|
|
|
2243
|
-
const _ProgressBarValueTextContext = /*#__PURE__*/ createContext(undefined);
|
|
2244
|
-
const _ProgressBarValueTextProvider = _ProgressBarValueTextContext.Provider;
|
|
2245
|
-
const ProgressBarValueText = ({ className, ...restProps })=>{
|
|
2246
|
-
const value = useContext(_ProgressBarValueTextContext);
|
|
2247
|
-
return /*#__PURE__*/ jsx("span", {
|
|
2248
|
-
...restProps,
|
|
2249
|
-
className: cx(className, 'px-2 leading-7'),
|
|
2250
|
-
"data-slot": "progress-bar-value-text",
|
|
2251
|
-
children: value
|
|
2252
|
-
});
|
|
2253
|
-
};
|
|
2254
|
-
const ProgressBar = ({ children, className, ...restProps })=>{
|
|
2255
|
-
return /*#__PURE__*/ jsx(ProgressBar$1, {
|
|
2256
|
-
"data-slot": "progress-bar",
|
|
2257
|
-
...restProps,
|
|
2258
|
-
className: cx(className, 'max-w-full'),
|
|
2259
|
-
children: ({ percentage, valueText, ...restArgs })=>/*#__PURE__*/ jsxs(_ProgressBarValueTextProvider, {
|
|
2260
|
-
value: valueText,
|
|
2261
|
-
children: [
|
|
2262
|
-
typeof children === 'function' ? children({
|
|
2263
|
-
percentage,
|
|
2264
|
-
valueText,
|
|
2265
|
-
...restArgs
|
|
2266
|
-
}) : children,
|
|
2267
|
-
/*#__PURE__*/ jsx("div", {
|
|
2268
|
-
className: "relative h-0.75 rounded bg-gray-light",
|
|
2269
|
-
children: /*#__PURE__*/ jsx("div", {
|
|
2270
|
-
className: "h-0.75 rounded bg-blue-dark transition-all duration-300 ease-in-out",
|
|
2271
|
-
style: {
|
|
2272
|
-
width: `${percentage}%`
|
|
2273
|
-
}
|
|
2274
|
-
})
|
|
2275
|
-
})
|
|
2276
|
-
]
|
|
2277
|
-
})
|
|
2278
|
-
});
|
|
2279
|
-
};
|
|
2280
|
-
|
|
2281
2333
|
const defaultClasses = cx([
|
|
2282
2334
|
'-ml-2.5 relative inline-flex max-w-fit cursor-pointer items-start gap-4 py-2.5 pl-2.5 leading-7',
|
|
2283
2335
|
// the radio button itself
|
|
@@ -2387,18 +2439,47 @@ function Select(props) {
|
|
|
2387
2439
|
});
|
|
2388
2440
|
}
|
|
2389
2441
|
|
|
2390
|
-
|
|
2442
|
+
const _ProgressBarValueTextContext = /*#__PURE__*/ createContext(undefined);
|
|
2443
|
+
const _ProgressBarValueTextProvider = _ProgressBarValueTextContext.Provider;
|
|
2444
|
+
const ProgressBar = ({ children, className, ...restProps })=>{
|
|
2445
|
+
return /*#__PURE__*/ jsx(ProgressBar$1, {
|
|
2446
|
+
"data-slot": "progress-bar",
|
|
2447
|
+
...restProps,
|
|
2448
|
+
className: cx(className, 'max-w-full'),
|
|
2449
|
+
children: ({ percentage, valueText, ...restArgs })=>/*#__PURE__*/ jsxs(_ProgressBarValueTextProvider, {
|
|
2450
|
+
value: valueText,
|
|
2451
|
+
children: [
|
|
2452
|
+
typeof children === 'function' ? children({
|
|
2453
|
+
percentage,
|
|
2454
|
+
valueText,
|
|
2455
|
+
...restArgs
|
|
2456
|
+
}) : children,
|
|
2457
|
+
/*#__PURE__*/ jsx("div", {
|
|
2458
|
+
className: "relative rounded border border-blue-dark bg-gray-light",
|
|
2459
|
+
children: /*#__PURE__*/ jsx("div", {
|
|
2460
|
+
className: "h-1 rounded bg-blue-dark transition-all duration-300 ease-in-out",
|
|
2461
|
+
style: {
|
|
2462
|
+
width: `${percentage}%`
|
|
2463
|
+
}
|
|
2464
|
+
})
|
|
2465
|
+
})
|
|
2466
|
+
]
|
|
2467
|
+
})
|
|
2468
|
+
});
|
|
2469
|
+
};
|
|
2470
|
+
|
|
2471
|
+
function ScrollButton({ direction, onClick, isVisible, hasScrollingOccurred, className }) {
|
|
2391
2472
|
const Icon = direction === 'left' ? ChevronLeft : ChevronRight;
|
|
2392
2473
|
return(// biome-ignore lint/a11y/useKeyWithClickEvents: This button is only for mouse interaction to help users scroll. Keyboard and screen reader users can navigate the content directly without needing these scroll helpers.
|
|
2393
2474
|
// biome-ignore lint/a11y/noStaticElementInteractions: This button is only for mouse interaction to help users scroll. Keyboard and screen reader users can navigate the content directly without needing these scroll helpers.
|
|
2394
2475
|
/*#__PURE__*/ jsx("div", {
|
|
2395
2476
|
onClick: onClick,
|
|
2396
2477
|
className: cx(// Base scroll button styling
|
|
2397
|
-
'flex cursor-pointer items-center justify-center', '
|
|
2478
|
+
'flex cursor-pointer items-center justify-center', 'absolute top-0 size-11', 'group/scroll-button text-black', direction === 'left' ? 'bg-[linear-gradient(90deg,white,white_calc(100%-10px),transparent)]' : 'bg-[linear-gradient(90deg,transparent,white_calc(10px),white)]', // Animation
|
|
2398
2479
|
hasScrollingOccurred && 'duration-100 ease-in motion-safe:transition-transform', // Hide/show animation
|
|
2399
2480
|
direction === 'left' ? !isVisible && '-translate-x-full pointer-events-none' : !isVisible && 'pointer-events-none translate-x-full', direction === 'left' ? '-left-3' : '-right-3', className),
|
|
2400
2481
|
children: /*#__PURE__*/ jsx(Icon, {
|
|
2401
|
-
className:
|
|
2482
|
+
className: cx('motion-safe:transition-all', direction === 'left' ? 'group-hover/scroll-button:-translate-x-1' : 'group-hover/scroll-button:translate-x-1')
|
|
2402
2483
|
})
|
|
2403
2484
|
}));
|
|
2404
2485
|
}
|
|
@@ -2455,6 +2536,132 @@ function ScrollButton({ direction, onClick, isVisible, hasScrollingOccurred, cla
|
|
|
2455
2536
|
};
|
|
2456
2537
|
}
|
|
2457
2538
|
|
|
2539
|
+
const StepperContext = /*#__PURE__*/ createContext({
|
|
2540
|
+
activeStep: 0,
|
|
2541
|
+
stepsCount: 0
|
|
2542
|
+
});
|
|
2543
|
+
const Stepper = ({ children, activeStep, onStepChange, ...restProps })=>{
|
|
2544
|
+
const locale = _useLocale();
|
|
2545
|
+
const stepsCount = Children.count(children);
|
|
2546
|
+
const [emblaRef, emblaApi] = useEmblaCarousel({
|
|
2547
|
+
startIndex: activeStep,
|
|
2548
|
+
dragFree: true,
|
|
2549
|
+
breakpoints: {
|
|
2550
|
+
// disable the carousel on large screens
|
|
2551
|
+
'(width >= 64rem)': {
|
|
2552
|
+
active: false
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
});
|
|
2556
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
2557
|
+
...restProps,
|
|
2558
|
+
"data-slot": "stepper-container",
|
|
2559
|
+
ref: emblaRef,
|
|
2560
|
+
children: [
|
|
2561
|
+
/*#__PURE__*/ jsx("ol", {
|
|
2562
|
+
"aria-label": translations$1.stepper[locale],
|
|
2563
|
+
"data-slot": "stepper",
|
|
2564
|
+
children: /*#__PURE__*/ jsx(StepperContext.Provider, {
|
|
2565
|
+
value: {
|
|
2566
|
+
onStepChange,
|
|
2567
|
+
activeStep,
|
|
2568
|
+
stepsCount
|
|
2569
|
+
},
|
|
2570
|
+
children: Children.map(children, (child, index)=>{
|
|
2571
|
+
return /*#__PURE__*/ isValidElement(child) && /*#__PURE__*/ cloneElement(child, {
|
|
2572
|
+
'~stepIndex': index
|
|
2573
|
+
});
|
|
2574
|
+
})
|
|
2575
|
+
})
|
|
2576
|
+
}),
|
|
2577
|
+
/*#__PURE__*/ jsx(MobileScrollButtons, {
|
|
2578
|
+
emblaApi: emblaApi
|
|
2579
|
+
})
|
|
2580
|
+
]
|
|
2581
|
+
});
|
|
2582
|
+
};
|
|
2583
|
+
const MobileScrollButtons = ({ emblaApi })=>{
|
|
2584
|
+
const [canScrollLeft, setCanScrollLeft] = useState(false);
|
|
2585
|
+
const [canScrollRight, setCanScrollRight] = useState(false);
|
|
2586
|
+
useEffect(()=>{
|
|
2587
|
+
if (!emblaApi) {
|
|
2588
|
+
return;
|
|
2589
|
+
}
|
|
2590
|
+
const handleSlidesInView = ()=>{
|
|
2591
|
+
setCanScrollLeft(emblaApi.canScrollPrev());
|
|
2592
|
+
setCanScrollRight(emblaApi.canScrollNext());
|
|
2593
|
+
};
|
|
2594
|
+
emblaApi.on('slidesInView', handleSlidesInView);
|
|
2595
|
+
return ()=>{
|
|
2596
|
+
emblaApi.off('slidesInView', handleSlidesInView);
|
|
2597
|
+
};
|
|
2598
|
+
}, [
|
|
2599
|
+
emblaApi
|
|
2600
|
+
]);
|
|
2601
|
+
return /*#__PURE__*/ jsxs(Fragment, {
|
|
2602
|
+
children: [
|
|
2603
|
+
/*#__PURE__*/ jsx(ScrollButton, {
|
|
2604
|
+
className: "lg:hidden",
|
|
2605
|
+
direction: "left",
|
|
2606
|
+
onClick: ()=>emblaApi?.scrollPrev(),
|
|
2607
|
+
isVisible: canScrollLeft,
|
|
2608
|
+
hasScrollingOccurred: false
|
|
2609
|
+
}),
|
|
2610
|
+
/*#__PURE__*/ jsx(ScrollButton, {
|
|
2611
|
+
className: "lg:hidden",
|
|
2612
|
+
direction: "right",
|
|
2613
|
+
isVisible: canScrollRight,
|
|
2614
|
+
onClick: ()=>emblaApi?.scrollNext(),
|
|
2615
|
+
hasScrollingOccurred: false
|
|
2616
|
+
})
|
|
2617
|
+
]
|
|
2618
|
+
});
|
|
2619
|
+
};
|
|
2620
|
+
const Step = ({ isDisabled = false, state, children, '~stepIndex': stepIndex, progress, ...restProps })=>{
|
|
2621
|
+
const locale = _useLocale();
|
|
2622
|
+
const id = useId();
|
|
2623
|
+
const { onStepChange, activeStep, stepsCount } = use(StepperContext);
|
|
2624
|
+
const isLastStep = stepIndex === stepsCount - 1;
|
|
2625
|
+
const isCurrent = stepIndex === activeStep;
|
|
2626
|
+
const iconText = state === 'completed' ? translations$1.completed[locale] : undefined;
|
|
2627
|
+
const icon = isCurrent ? /*#__PURE__*/ jsx(Edit, {
|
|
2628
|
+
"aria-label": iconText
|
|
2629
|
+
}) : state === 'completed' && /*#__PURE__*/ jsx(Check, {
|
|
2630
|
+
"aria-label": iconText
|
|
2631
|
+
});
|
|
2632
|
+
return /*#__PURE__*/ jsx("li", {
|
|
2633
|
+
...restProps,
|
|
2634
|
+
"data-slot": "step",
|
|
2635
|
+
"data-state": state,
|
|
2636
|
+
"data-current": isCurrent ? true : undefined,
|
|
2637
|
+
"data-disabled": isDisabled ? true : undefined,
|
|
2638
|
+
id: id,
|
|
2639
|
+
children: /*#__PURE__*/ jsxs(Provider, {
|
|
2640
|
+
values: [
|
|
2641
|
+
[
|
|
2642
|
+
LinkContext,
|
|
2643
|
+
{
|
|
2644
|
+
// @ts-expect-error this works even though it's a type error
|
|
2645
|
+
'aria-current': isCurrent ? 'step' : undefined,
|
|
2646
|
+
isDisabled,
|
|
2647
|
+
className: 'underline',
|
|
2648
|
+
onPress: ()=>onStepChange?.(stepIndex)
|
|
2649
|
+
}
|
|
2650
|
+
]
|
|
2651
|
+
],
|
|
2652
|
+
children: [
|
|
2653
|
+
icon,
|
|
2654
|
+
children,
|
|
2655
|
+
!isLastStep && /*#__PURE__*/ jsx(ProgressBar, {
|
|
2656
|
+
"aria-labelledby": id,
|
|
2657
|
+
// Make sure that if the step is completed, the progress value is 100%
|
|
2658
|
+
value: state === 'completed' ? 100 : progress
|
|
2659
|
+
})
|
|
2660
|
+
]
|
|
2661
|
+
})
|
|
2662
|
+
});
|
|
2663
|
+
};
|
|
2664
|
+
|
|
2458
2665
|
const tableVariants = cva({
|
|
2459
2666
|
base: [
|
|
2460
2667
|
'relative'
|
|
@@ -2504,22 +2711,6 @@ const TableScrollContainerContext = /*#__PURE__*/ createContext({
|
|
|
2504
2711
|
children: /*#__PURE__*/ jsxs("div", {
|
|
2505
2712
|
className: "relative overflow-hidden",
|
|
2506
2713
|
children: [
|
|
2507
|
-
/*#__PURE__*/ jsx(ScrollButton, {
|
|
2508
|
-
direction: "left",
|
|
2509
|
-
onClick: ()=>handleScroll('left'),
|
|
2510
|
-
isVisible: canScrollLeft,
|
|
2511
|
-
hasScrollingOccurred: hasScrollingOccurred,
|
|
2512
|
-
className: "-translate-y-1/2 absolute top-5 z-10 h-11 w-11",
|
|
2513
|
-
iconClassName: "h-5 w-5"
|
|
2514
|
-
}),
|
|
2515
|
-
/*#__PURE__*/ jsx(ScrollButton, {
|
|
2516
|
-
direction: "right",
|
|
2517
|
-
onClick: ()=>handleScroll('right'),
|
|
2518
|
-
isVisible: canScrollRight,
|
|
2519
|
-
hasScrollingOccurred: hasScrollingOccurred,
|
|
2520
|
-
className: "-translate-y-1/2 absolute top-5 z-10 h-11 w-11",
|
|
2521
|
-
iconClassName: "h-5 w-5"
|
|
2522
|
-
}),
|
|
2523
2714
|
/*#__PURE__*/ jsx("div", {
|
|
2524
2715
|
ref: scrollContainerRef,
|
|
2525
2716
|
className: "scrollbar-hidden overflow-x-auto",
|
|
@@ -2532,6 +2723,18 @@ const TableScrollContainerContext = /*#__PURE__*/ createContext({
|
|
|
2532
2723
|
"data-variant": variant,
|
|
2533
2724
|
children: children
|
|
2534
2725
|
})
|
|
2726
|
+
}),
|
|
2727
|
+
/*#__PURE__*/ jsx(ScrollButton, {
|
|
2728
|
+
direction: "left",
|
|
2729
|
+
onClick: ()=>handleScroll('left'),
|
|
2730
|
+
isVisible: canScrollLeft,
|
|
2731
|
+
hasScrollingOccurred: hasScrollingOccurred
|
|
2732
|
+
}),
|
|
2733
|
+
/*#__PURE__*/ jsx(ScrollButton, {
|
|
2734
|
+
direction: "right",
|
|
2735
|
+
onClick: ()=>handleScroll('right'),
|
|
2736
|
+
isVisible: canScrollRight,
|
|
2737
|
+
hasScrollingOccurred: hasScrollingOccurred
|
|
2535
2738
|
})
|
|
2536
2739
|
]
|
|
2537
2740
|
})
|
|
@@ -2719,17 +2922,13 @@ const tabsVariants = cva({
|
|
|
2719
2922
|
direction: "left",
|
|
2720
2923
|
onClick: onPrev,
|
|
2721
2924
|
isVisible: canScrollLeft,
|
|
2722
|
-
hasScrollingOccurred: hasScrollingOccurred
|
|
2723
|
-
className: "absolute bottom-0.25 size-11",
|
|
2724
|
-
iconClassName: "mt-0.25 h-6 w-full text-black"
|
|
2925
|
+
hasScrollingOccurred: hasScrollingOccurred
|
|
2725
2926
|
}),
|
|
2726
2927
|
/*#__PURE__*/ jsx(ScrollButton, {
|
|
2727
2928
|
direction: "right",
|
|
2728
2929
|
onClick: onNext,
|
|
2729
2930
|
isVisible: canScrollRight,
|
|
2730
|
-
hasScrollingOccurred: hasScrollingOccurred
|
|
2731
|
-
className: "absolute bottom-0.25 size-11",
|
|
2732
|
-
iconClassName: "mt-0.25 h-6 w-full text-black"
|
|
2931
|
+
hasScrollingOccurred: hasScrollingOccurred
|
|
2733
2932
|
})
|
|
2734
2933
|
]
|
|
2735
2934
|
});
|
|
@@ -2740,7 +2939,7 @@ const tabsVariants = cva({
|
|
|
2740
2939
|
const { className, children, ...restProps } = props;
|
|
2741
2940
|
return /*#__PURE__*/ jsx(Tab$1, {
|
|
2742
2941
|
...restProps,
|
|
2743
|
-
className: cx(className, 'data-focus-visible:-outline-offset-10 data-focus-visible:outline-2 data-focus-visible:outline-black', 'description cursor-pointer border-transparent px-4 py-
|
|
2942
|
+
className: cx(className, 'data-focus-visible:-outline-offset-10 data-focus-visible:outline-2 data-focus-visible:outline-black', 'description h-11 cursor-pointer border-transparent px-4 py-[0.71875rem] font-light', // Transition
|
|
2744
2943
|
'transition-colors duration-150 ease-out', // TODO: Should disabled tabs just be hidden?
|
|
2745
2944
|
'data-disabled:cursor-not-allowed data-disabled:opacity-50', // Selection
|
|
2746
2945
|
'data-selected:font-medium data-selected:text-blue-dark', // Hover with layout shift prevention using pseudo-element
|
|
@@ -3001,4 +3200,4 @@ const VideoLoop = ({ src, format, alt, className })=>{
|
|
|
3001
3200
|
});
|
|
3002
3201
|
};
|
|
3003
3202
|
|
|
3004
|
-
export { Accordion, AccordionItem, Alertbox, Avatar, Backlink, Badge, Breadcrumb, Breadcrumbs, Button, ButtonContext, Caption, Card, CardLink, Checkbox, CheckboxGroup, Combobox, ListBoxHeader as ComboboxHeader, ListBoxItem as ComboboxItem, ListBoxSection as ComboboxSection, Content, ContentContext, DateFormatter, Description, Disclosure, DisclosureButton, DisclosurePanel, DisclosureStateContext, ErrorMessage, Footer, GrunnmurenProvider, Heading, HeadingContext, Label, LinkList, LinkListContainer, LinkListItem, Media, MediaContext, NumberField, Radio, RadioGroup, Select, ListBoxHeader as SelectHeader, ListBoxItem as SelectItem, ListBoxSection as SelectSection, Tag, TagGroup, TagList, TextArea, TextField, Carousel as UNSAFE_Carousel, CarouselButton as UNSAFE_CarouselButton, CarouselControls as UNSAFE_CarouselControls, CarouselItem as UNSAFE_CarouselItem, CarouselItems as UNSAFE_CarouselItems, CarouselItemsContainer as UNSAFE_CarouselItemsContainer, Dialog as UNSAFE_Dialog, DialogTrigger as UNSAFE_DialogTrigger, FileUpload as UNSAFE_FileUpload, Hero as UNSAFE_Hero, Link as UNSAFE_Link, Modal as UNSAFE_Modal,
|
|
3203
|
+
export { Accordion, AccordionItem, Alertbox, Avatar, Backlink, Badge, Breadcrumb, Breadcrumbs, Button, ButtonContext, Caption, Card, CardLink, Checkbox, CheckboxGroup, Combobox, ListBoxHeader as ComboboxHeader, ListBoxItem as ComboboxItem, ListBoxSection as ComboboxSection, Content, ContentContext, DateFormatter, Description, Disclosure, DisclosureButton, DisclosurePanel, DisclosureStateContext, ErrorMessage, Footer, GrunnmurenProvider, Heading, HeadingContext, Label, LinkList, LinkListContainer, LinkListItem, Media, MediaContext, NumberField, Radio, RadioGroup, Select, ListBoxHeader as SelectHeader, ListBoxItem as SelectItem, ListBoxSection as SelectSection, Tag, TagGroup, TagList, TextArea, TextField, Carousel as UNSAFE_Carousel, CarouselButton as UNSAFE_CarouselButton, CarouselContext as UNSAFE_CarouselContext, CarouselControls as UNSAFE_CarouselControls, CarouselItem as UNSAFE_CarouselItem, CarouselItems as UNSAFE_CarouselItems, CarouselItemsContainer as UNSAFE_CarouselItemsContainer, Dialog as UNSAFE_Dialog, DialogTrigger as UNSAFE_DialogTrigger, FileUpload as UNSAFE_FileUpload, Hero as UNSAFE_Hero, HeroContext as UNSAFE_HeroContext, Link as UNSAFE_Link, Modal as UNSAFE_Modal, Step as UNSAFE_Step, Stepper as UNSAFE_Stepper, Tab as UNSAFE_Tab, TabList as UNSAFE_TabList, TabPanel as UNSAFE_TabPanel, Table as UNSAFE_Table, TableBody as UNSAFE_TableBody, TableCell as UNSAFE_TableCell, TableColumn as UNSAFE_TableColumn, TableColumnResizer as UNSAFE_TableColumnResizer, TableContainer as UNSAFE_TableContainer, TableHeader as UNSAFE_TableHeader, TableRow as UNSAFE_TableRow, Tabs as UNSAFE_Tabs, VideoLoop, _useLocale as useLocale };
|