@obosbbl/grunnmuren-react 2.3.4 → 3.0.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/index.d.mts +50 -16
- package/dist/index.mjs +211 -19
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { RouterProvider, ButtonProps as ButtonProps$1, LinkProps, ContextValue, CheckboxProps as CheckboxProps$1, CheckboxGroupProps as CheckboxGroupProps$1, ListBoxItemProps, ListBoxSectionProps, HeadingProps as HeadingProps$1, ComboBoxProps, RadioGroupProps as RadioGroupProps$1, RadioProps as RadioProps$1, SelectProps as SelectProps$1, TextFieldProps as TextFieldProps$1, NumberFieldProps as NumberFieldProps$1, BreadcrumbProps as BreadcrumbProps$1, BreadcrumbsProps as BreadcrumbsProps$1, DisclosureProps as DisclosureProps$1, FileTriggerProps as FileTriggerProps$1, TextProps, LabelProps, DialogTriggerProps as DialogTriggerProps$1, ModalOverlayProps, DialogProps as DialogProps$1, TagGroupProps as TagGroupProps$1, TagListProps as TagListProps$1, TagProps as TagProps$1 } from 'react-aria-components';
|
|
1
|
+
import { RouterProvider, ButtonProps as ButtonProps$1, LinkProps, ContextValue, CheckboxProps as CheckboxProps$1, CheckboxGroupProps as CheckboxGroupProps$1, ListBoxItemProps, ListBoxSectionProps, HeadingProps as HeadingProps$1, ComboBoxProps, RadioGroupProps as RadioGroupProps$1, RadioProps as RadioProps$1, SelectProps as SelectProps$1, TextFieldProps as TextFieldProps$1, NumberFieldProps as NumberFieldProps$1, BreadcrumbProps as BreadcrumbProps$1, BreadcrumbsProps as BreadcrumbsProps$1, DisclosureProps as DisclosureProps$1, FileTriggerProps as FileTriggerProps$1, TextProps, LabelProps, DialogTriggerProps as DialogTriggerProps$1, ModalOverlayProps, DialogProps as DialogProps$1, TagGroupProps as TagGroupProps$1, TagListProps as TagListProps$1, TagProps as TagProps$1, TabsProps as TabsProps$1, TabListProps as TabListProps$1, TabProps as TabProps$1, TabPanelProps as TabPanelProps$1 } from 'react-aria-components';
|
|
2
2
|
export { ListBoxItemProps as ComboboxItemProps, Form, Group, LabelProps, ListBoxItemProps as SelectItemProps, DisclosureGroup as UNSAFE_DisclosureGroup, DisclosureGroupProps as UNSAFE_DisclosureGroupProps } from 'react-aria-components';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
import * as react from 'react';
|
|
5
|
-
import { Ref, HTMLProps, ReactNode, RefAttributes, HTMLAttributes, RefObject, Dispatch, SetStateAction, ComponentProps } from 'react';
|
|
5
|
+
import { Ref, HTMLProps, ReactNode, RefAttributes, HTMLAttributes, RefObject, Dispatch, SetStateAction, ComponentProps, JSX } from 'react';
|
|
6
6
|
import * as cva from 'cva';
|
|
7
7
|
import { VariantProps } from 'cva';
|
|
8
8
|
import { DateFormatterOptions } from 'react-aria';
|
|
@@ -80,7 +80,7 @@ declare function Badge(props: BadgeProps): react_jsx_runtime.JSX.Element;
|
|
|
80
80
|
*/
|
|
81
81
|
declare const buttonVariants: (props?: ({
|
|
82
82
|
variant?: "primary" | "secondary" | "tertiary" | undefined;
|
|
83
|
-
color?: "mint" | "white" | "
|
|
83
|
+
color?: "mint" | "white" | "blue" | undefined;
|
|
84
84
|
isIconOnly?: boolean | undefined;
|
|
85
85
|
isPending?: boolean | undefined;
|
|
86
86
|
} & ({
|
|
@@ -93,12 +93,6 @@ declare const buttonVariants: (props?: ({
|
|
|
93
93
|
type ButtonOrLinkProps$1 = VariantProps<typeof buttonVariants> & {
|
|
94
94
|
children?: React.ReactNode;
|
|
95
95
|
href?: LinkProps['href'];
|
|
96
|
-
/**
|
|
97
|
-
* Display the button in a loading state
|
|
98
|
-
* @deprecated Use isPending instead.
|
|
99
|
-
* @default false
|
|
100
|
-
*/
|
|
101
|
-
isLoading?: boolean;
|
|
102
96
|
/** Additional style properties for the element. */
|
|
103
97
|
style?: React.CSSProperties;
|
|
104
98
|
/** Ref to the element. */
|
|
@@ -158,11 +152,6 @@ type ComboboxProps<T extends object> = {
|
|
|
158
152
|
description?: React.ReactNode;
|
|
159
153
|
/** Error message for the form control. Automatically sets `isInvalid` to true */
|
|
160
154
|
errorMessage?: React.ReactNode;
|
|
161
|
-
/**
|
|
162
|
-
* Display the dropdown button trigger in a pending state
|
|
163
|
-
* @deprecated Use isPending instead.
|
|
164
|
-
*/
|
|
165
|
-
isLoading?: boolean;
|
|
166
155
|
/**
|
|
167
156
|
* Display the dropdown button trigger in a pending state
|
|
168
157
|
* @default false
|
|
@@ -653,7 +642,7 @@ type CarouselItemsProps = {
|
|
|
653
642
|
declare const CarouselItems: ({ className, children }: CarouselItemsProps) => react_jsx_runtime.JSX.Element;
|
|
654
643
|
type CarouselItemProps = {
|
|
655
644
|
/** The component/components to display as the <CarouselItem/>. */
|
|
656
|
-
children:
|
|
645
|
+
children: JSX.Element | JSX.Element[];
|
|
657
646
|
/** Additional CSS className for the element. */
|
|
658
647
|
className?: string;
|
|
659
648
|
id?: string;
|
|
@@ -668,4 +657,49 @@ type CarouselItem = Pick<CarouselItemProps, 'id'> & {
|
|
|
668
657
|
};
|
|
669
658
|
declare const CarouselItem: ({ className, children, id }: CarouselItemProps) => react_jsx_runtime.JSX.Element;
|
|
670
659
|
|
|
671
|
-
|
|
660
|
+
type TabsProps = Omit<TabsProps$1, 'className'> & RefAttributes<HTMLDivElement> & {
|
|
661
|
+
/**
|
|
662
|
+
* CSS classes to apply to the tabs container
|
|
663
|
+
*/
|
|
664
|
+
className?: string;
|
|
665
|
+
orientation?: 'horizontal' | 'vertical';
|
|
666
|
+
};
|
|
667
|
+
type TabListProps = Omit<TabListProps$1<object>, 'className'> & RefAttributes<HTMLDivElement> & {
|
|
668
|
+
/**
|
|
669
|
+
* CSS classes to apply to the tab list
|
|
670
|
+
*/
|
|
671
|
+
className?: string;
|
|
672
|
+
};
|
|
673
|
+
type TabProps = Omit<TabProps$1, 'className'> & RefAttributes<HTMLDivElement> & {
|
|
674
|
+
children: React.ReactNode;
|
|
675
|
+
/**
|
|
676
|
+
* CSS classes to apply to the tab
|
|
677
|
+
*/
|
|
678
|
+
className?: string;
|
|
679
|
+
};
|
|
680
|
+
type TabPanelProps = Omit<TabPanelProps$1, 'className'> & RefAttributes<HTMLDivElement> & {
|
|
681
|
+
children: React.ReactNode;
|
|
682
|
+
/**
|
|
683
|
+
* CSS classes to apply to the tab panel
|
|
684
|
+
*/
|
|
685
|
+
className?: string;
|
|
686
|
+
};
|
|
687
|
+
/**
|
|
688
|
+
* A container component that organizes content into multiple sections
|
|
689
|
+
* and allows users to navigate between them.
|
|
690
|
+
*/
|
|
691
|
+
declare function Tabs(props: TabsProps): react_jsx_runtime.JSX.Element;
|
|
692
|
+
/**
|
|
693
|
+
* A container component for Tab components within Tabs.
|
|
694
|
+
*/
|
|
695
|
+
declare function TabList({ className, children, ...restProps }: TabListProps): react_jsx_runtime.JSX.Element;
|
|
696
|
+
/**
|
|
697
|
+
* An individual tab that can be selected to display its associated content.
|
|
698
|
+
*/
|
|
699
|
+
declare function Tab(props: TabProps): react_jsx_runtime.JSX.Element;
|
|
700
|
+
/**
|
|
701
|
+
* The content area that displays the selected tab's content.
|
|
702
|
+
*/
|
|
703
|
+
declare function TabPanel(props: TabPanelProps): react_jsx_runtime.JSX.Element;
|
|
704
|
+
|
|
705
|
+
export { Accordion, AccordionItem, type AccordionItemProps, type AccordionProps, Alertbox, type Props as AlertboxProps, Avatar, type AvatarProps, Backlink, type BacklinkProps, Badge, type BadgeProps, Breadcrumb, type BreadcrumbProps, Breadcrumbs, type BreadcrumbsProps, Button, ButtonContext, type ButtonProps, Caption, type CaptionProps, Card, CardLink, type CardLinkProps, type CardProps, Checkbox, CheckboxGroup, type CheckboxGroupProps, type CheckboxProps, Combobox, ListBoxHeader as ComboboxHeader, ListBoxItem as ComboboxItem, type ComboboxProps, ListBoxSection as ComboboxSection, Content, ContentContext, type ContentProps, DateFormatter, type DateFormatterProps, Description, type DescriptionProps, DisclosureStateContext, ErrorMessage, type ErrorMessageProps, Footer, type FooterProps, GrunnmurenProvider, type GrunnmurenProviderProps, Heading, HeadingContext, type HeadingProps, Label, type Locale, Media, MediaContext, type MediaProps, NumberField, type NumberFieldProps, Radio, RadioGroup, type RadioGroupProps, type RadioProps, Select, ListBoxHeader as SelectHeader, ListBoxItem as SelectItem, type SelectProps, ListBoxSection as SelectSection, type TagGroupProps, type TagListProps, type TagProps, TextArea, type TextAreaProps, TextField, type TextFieldProps, Carousel as UNSAFE_Carousel, CarouselItem as UNSAFE_CarouselItem, type CarouselItemProps as UNSAFE_CarouselItemProps, CarouselItems as UNSAFE_CarouselItems, type CarouselItemsProps as UNSAFE_CarouselItemsProps, type CarouselProps as UNSAFE_CarouselProps, Dialog as UNSAFE_Dialog, type DialogProps as UNSAFE_DialogProps, DialogTrigger as UNSAFE_DialogTrigger, type DialogTriggerProps as UNSAFE_DialogTriggerProps, Disclosure as UNSAFE_Disclosure, DisclosureButton as UNSAFE_DisclosureButton, type DisclosureButtonProps as UNSAFE_DisclosureButtonProps, DisclosurePanel as UNSAFE_DisclosurePanel, type DisclosurePanelProps as UNSAFE_DisclosurePanelProps, type DisclosureProps as UNSAFE_DisclosureProps, FileUpload as UNSAFE_FileUpload, type FileUploadProps as UNSAFE_FileUploadProps, Hero as UNSAFE_Hero, type HeroProps as UNSAFE_HeroProps, Modal as UNSAFE_Modal, type ModalProps as UNSAFE_ModalProps, Tab as UNSAFE_Tab, TabList as UNSAFE_TabList, type TabListProps as UNSAFE_TabListProps, TabPanel as UNSAFE_TabPanel, type TabPanelProps as UNSAFE_TabPanelProps, type TabProps as UNSAFE_TabProps, Tabs as UNSAFE_Tabs, type TabsProps as UNSAFE_TabsProps, Tag as UNSAFE_Tag, TagGroup as UNSAFE_TagGroup, TagList as UNSAFE_TagList, VideoLoop, _useLocale as useLocale };
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { I18nProvider, RouterProvider, useLocale, useContextProps, Provider, Link, Button as Button$1, Text, CheckboxContext, Checkbox as Checkbox$1, FieldError, Label as Label$1, CheckboxGroup as CheckboxGroup$1, ListBoxItem as ListBoxItem$1, ListBoxSection as ListBoxSection$1, Header, ListBox as ListBox$1, ComboBox, Group, Input, Popover, RadioGroup as RadioGroup$1, Radio as Radio$1, Select as Select$1, SelectValue, TextField as TextField$1, TextArea as TextArea$1, NumberField as NumberField$1, Breadcrumbs as Breadcrumbs$1, Breadcrumb as Breadcrumb$1, ButtonContext as ButtonContext$1, DisclosureContext, DisclosureGroupStateContext, DEFAULT_SLOT, useSlottedContext, FormContext, FieldErrorContext, LabelContext, InputContext, DialogTrigger as DialogTrigger$1, Modal as Modal$1, Dialog as Dialog$1, ModalOverlay as ModalOverlay$1, TagGroup as TagGroup$1, TagList as TagList$1, Tag as Tag$1, GroupContext } from 'react-aria-components';
|
|
2
|
+
import { I18nProvider, RouterProvider, useLocale, useContextProps, Provider, Link, Button as Button$1, Text, CheckboxContext, Checkbox as Checkbox$1, FieldError, Label as Label$1, CheckboxGroup as CheckboxGroup$1, ListBoxItem as ListBoxItem$1, ListBoxSection as ListBoxSection$1, Header, ListBox as ListBox$1, ComboBox, Group, Input, Popover, RadioGroup as RadioGroup$1, Radio as Radio$1, Select as Select$1, SelectValue, TextField as TextField$1, TextArea as TextArea$1, NumberField as NumberField$1, Breadcrumbs as Breadcrumbs$1, Breadcrumb as Breadcrumb$1, ButtonContext as ButtonContext$1, DisclosureContext, DisclosureGroupStateContext, DEFAULT_SLOT, useSlottedContext, FormContext, FieldErrorContext, LabelContext, InputContext, DialogTrigger as DialogTrigger$1, Modal as Modal$1, Dialog as Dialog$1, ModalOverlay as ModalOverlay$1, TagGroup as TagGroup$1, TagList as TagList$1, Tag as Tag$1, GroupContext, Tabs as Tabs$1, TabListStateContext, TabList as TabList$1, Tab as Tab$1, TabPanel as TabPanel$1 } from 'react-aria-components';
|
|
3
3
|
export { Form, Group, DisclosureGroup as UNSAFE_DisclosureGroup } from 'react-aria-components';
|
|
4
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
import { ChevronDown, LoadingSpinner, Check, Close, InfoCircle, CheckCircle, Warning, Error, ChevronRight, ChevronLeft, PlayerPause, PlayerPlay, Trash, User } from '@obosbbl/grunnmuren-icons-react';
|
|
@@ -291,14 +291,14 @@ const translations$1 = {
|
|
|
291
291
|
*/ variant: {
|
|
292
292
|
primary: 'no-underline',
|
|
293
293
|
// 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
|
|
294
|
-
secondary: 'no-underline
|
|
294
|
+
secondary: 'border-2 border-current no-underline hover:border-transparent',
|
|
295
295
|
tertiary: 'underline hover:no-underline'
|
|
296
296
|
},
|
|
297
297
|
/**
|
|
298
298
|
* Adjusts the color of the button for usage on different backgrounds.
|
|
299
|
-
* @default
|
|
299
|
+
* @default blue
|
|
300
300
|
*/ color: {
|
|
301
|
-
|
|
301
|
+
blue: 'focus-visible:outline-focus',
|
|
302
302
|
mint: 'focus-visible:outline-focus focus-visible:outline-mint',
|
|
303
303
|
white: 'focus-visible:outline-focus focus-visible:outline-white'
|
|
304
304
|
},
|
|
@@ -317,18 +317,18 @@ const translations$1 = {
|
|
|
317
317
|
},
|
|
318
318
|
compoundVariants: [
|
|
319
319
|
{
|
|
320
|
-
color: '
|
|
320
|
+
color: 'blue',
|
|
321
321
|
variant: 'primary',
|
|
322
322
|
// Darken bg by 20% on hover. The color is manually crafted
|
|
323
|
-
className: 'bg-
|
|
323
|
+
className: 'bg-blue-dark text-white hover:bg-blue active:bg-[#0536A0] active:text-white [&_[role="progressbar"]]:text-white'
|
|
324
324
|
},
|
|
325
325
|
{
|
|
326
|
-
color: '
|
|
326
|
+
color: 'blue',
|
|
327
327
|
variant: 'secondary',
|
|
328
|
-
className: 'text-
|
|
328
|
+
className: 'text-blue-dark hover:border-transparent hover:bg-blue hover:text-blue-dark hover:text-white active:bg-[#0536A0] [&:hover_[role="progressbar"]]:text-white [&_[role="progressbar"]]:text-blue-dark'
|
|
329
329
|
},
|
|
330
330
|
{
|
|
331
|
-
color: '
|
|
331
|
+
color: 'blue',
|
|
332
332
|
variant: 'tertiary',
|
|
333
333
|
className: '[&_[role="progressbar"]]:text-black'
|
|
334
334
|
},
|
|
@@ -341,7 +341,7 @@ const translations$1 = {
|
|
|
341
341
|
{
|
|
342
342
|
color: 'mint',
|
|
343
343
|
variant: 'secondary',
|
|
344
|
-
className: 'text-mint
|
|
344
|
+
className: 'text-mint hover:bg-mint hover:text-black [&:hover_[role="progressbar"]]:text-black [&_[role="progressbar"]]:text-mint'
|
|
345
345
|
},
|
|
346
346
|
{
|
|
347
347
|
color: 'mint',
|
|
@@ -356,7 +356,7 @@ const translations$1 = {
|
|
|
356
356
|
{
|
|
357
357
|
color: 'white',
|
|
358
358
|
variant: 'secondary',
|
|
359
|
-
className: 'text-white
|
|
359
|
+
className: 'text-white hover:bg-white hover:text-black [&:hover_[role="progressbar"]]:text-black [&_[role="progressbar"]]:text-white'
|
|
360
360
|
},
|
|
361
361
|
{
|
|
362
362
|
color: 'white',
|
|
@@ -366,7 +366,7 @@ const translations$1 = {
|
|
|
366
366
|
],
|
|
367
367
|
defaultVariants: {
|
|
368
368
|
variant: 'primary',
|
|
369
|
-
color: '
|
|
369
|
+
color: 'blue',
|
|
370
370
|
isIconOnly: false,
|
|
371
371
|
isPending: false
|
|
372
372
|
}
|
|
@@ -377,8 +377,7 @@ function isLinkProps$1(props) {
|
|
|
377
377
|
}
|
|
378
378
|
function Button({ ref = null, ...props }) {
|
|
379
379
|
[props, ref] = useContextProps(props, ref, ButtonContext);
|
|
380
|
-
const { children: _children, color, isIconOnly,
|
|
381
|
-
const isPending = _isPending || isLoading;
|
|
380
|
+
const { children: _children, color, isIconOnly, variant, isPending, ...restProps } = props;
|
|
382
381
|
const className = buttonVariants({
|
|
383
382
|
className: props.className,
|
|
384
383
|
color,
|
|
@@ -402,7 +401,6 @@ function Button({ ref = null, ...props }) {
|
|
|
402
401
|
}) : _children;
|
|
403
402
|
return isLinkProps$1(restProps) ? /*#__PURE__*/ jsx(Link, {
|
|
404
403
|
...restProps,
|
|
405
|
-
routerOptions: restProps.routerOptions,
|
|
406
404
|
className: className,
|
|
407
405
|
ref: ref,
|
|
408
406
|
children: children
|
|
@@ -638,8 +636,7 @@ function InputAddonDivider() {
|
|
|
638
636
|
}
|
|
639
637
|
|
|
640
638
|
function Combobox(props) {
|
|
641
|
-
const { className, children, description, errorMessage,
|
|
642
|
-
const isPending = _isPending || isLoading;
|
|
639
|
+
const { className, children, description, errorMessage, isPending, label, isInvalid: _isInvalid, ref, ...restProps } = props;
|
|
643
640
|
// the order of the conditions matter here, because providing a value for isInvalid makes the validation state "controlled",
|
|
644
641
|
// which will override any built in validation
|
|
645
642
|
const isInvalid = !!errorMessage || _isInvalid;
|
|
@@ -1802,7 +1799,7 @@ const FileUpload = ({ children, files: _files, onChange, validate, isInvalid: _i
|
|
|
1802
1799
|
children: children
|
|
1803
1800
|
})
|
|
1804
1801
|
}),
|
|
1805
|
-
/*#__PURE__*/ jsx("ul", {
|
|
1802
|
+
controlledOrUncontrolledFiles.length > 0 && /*#__PURE__*/ jsx("ul", {
|
|
1806
1803
|
className: "mt-4 grid gap-y-2",
|
|
1807
1804
|
children: controlledOrUncontrolledFiles.map((file, fileIndex)=>{
|
|
1808
1805
|
let fileName = file.name;
|
|
@@ -2292,4 +2289,199 @@ const CarouselItem = ({ className, children, id })=>{
|
|
|
2292
2289
|
});
|
|
2293
2290
|
};
|
|
2294
2291
|
|
|
2295
|
-
|
|
2292
|
+
const tabsVariants = cva({
|
|
2293
|
+
base: [
|
|
2294
|
+
'grid gap-4'
|
|
2295
|
+
],
|
|
2296
|
+
variants: {
|
|
2297
|
+
orientation: {
|
|
2298
|
+
horizontal: '',
|
|
2299
|
+
vertical: 'grid-cols-[auto_1fr]'
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
});
|
|
2303
|
+
/**
|
|
2304
|
+
* A container component that organizes content into multiple sections
|
|
2305
|
+
* and allows users to navigate between them.
|
|
2306
|
+
*/ function Tabs(props) {
|
|
2307
|
+
const { className, children, orientation = 'horizontal', ...restProps } = props;
|
|
2308
|
+
return /*#__PURE__*/ jsx(Tabs$1, {
|
|
2309
|
+
...restProps,
|
|
2310
|
+
orientation: orientation,
|
|
2311
|
+
className: tabsVariants({
|
|
2312
|
+
className,
|
|
2313
|
+
orientation
|
|
2314
|
+
}),
|
|
2315
|
+
children: children
|
|
2316
|
+
});
|
|
2317
|
+
}
|
|
2318
|
+
/**
|
|
2319
|
+
* A container component for Tab components within Tabs.
|
|
2320
|
+
*/ function TabList({ className, children, ...restProps }) {
|
|
2321
|
+
const scrollContainerRef = useRef(null);
|
|
2322
|
+
const [canScrollLeft, setCanScrollLeft] = useState(false);
|
|
2323
|
+
const [canScrollRight, setCanScrollRight] = useState(false);
|
|
2324
|
+
const checkScrollOverflow = useCallback(()=>{
|
|
2325
|
+
const container = scrollContainerRef.current;
|
|
2326
|
+
if (!container) return;
|
|
2327
|
+
const { scrollLeft, scrollWidth, clientWidth } = container;
|
|
2328
|
+
setCanScrollLeft(scrollLeft > 0);
|
|
2329
|
+
setCanScrollRight(scrollLeft < scrollWidth - clientWidth - 1);
|
|
2330
|
+
}, []);
|
|
2331
|
+
const state = useContext(TabListStateContext);
|
|
2332
|
+
const prevKey = state?.selectedKey && state?.collection.getKeyBefore(state.selectedKey);
|
|
2333
|
+
const onPrev = prevKey ? ()=>state?.setSelectedKey(prevKey) : ()=>{
|
|
2334
|
+
if (canScrollLeft && state?.selectedKey === state?.collection.firstKey) {
|
|
2335
|
+
// Scroll to the start of the tab list if we are at the first tab but it is scrolled out of view
|
|
2336
|
+
scrollContainerRef.current?.scrollTo({
|
|
2337
|
+
left: 0,
|
|
2338
|
+
behavior: 'smooth'
|
|
2339
|
+
});
|
|
2340
|
+
}
|
|
2341
|
+
};
|
|
2342
|
+
const nextKey = state?.selectedKey && state?.collection.getKeyAfter(state.selectedKey);
|
|
2343
|
+
const onNext = nextKey ? ()=>state?.setSelectedKey(nextKey) : ()=>{
|
|
2344
|
+
if (canScrollRight && state?.selectedKey === state?.collection.lastKey) {
|
|
2345
|
+
// Scroll to the end of the tab list if we are at the last tab but it is scrolled out of view
|
|
2346
|
+
scrollContainerRef.current?.scrollTo({
|
|
2347
|
+
left: scrollContainerRef.current.scrollWidth,
|
|
2348
|
+
behavior: 'smooth'
|
|
2349
|
+
});
|
|
2350
|
+
}
|
|
2351
|
+
};
|
|
2352
|
+
// To controll if the animation for the scroll buttons and the scrolling behavior
|
|
2353
|
+
// This is used to prevent animations from running when the component mounts
|
|
2354
|
+
// We use a ref here to prevent redundant render cycles and potentially uninteded scrolling.
|
|
2355
|
+
const hasScrollingOccurredRef = useRef(false);
|
|
2356
|
+
// Debounce the scroll handler to avoid performance issues with frequent scroll events
|
|
2357
|
+
const scrollHandler = useDebouncedCallback(()=>{
|
|
2358
|
+
checkScrollOverflow();
|
|
2359
|
+
hasScrollingOccurredRef.current = true;
|
|
2360
|
+
}, 100);
|
|
2361
|
+
useEffect(()=>{
|
|
2362
|
+
const container = scrollContainerRef.current;
|
|
2363
|
+
if (!container) return;
|
|
2364
|
+
checkScrollOverflow();
|
|
2365
|
+
container.addEventListener('scroll', scrollHandler);
|
|
2366
|
+
const resizeObserver = new ResizeObserver(checkScrollOverflow);
|
|
2367
|
+
resizeObserver.observe(container);
|
|
2368
|
+
return ()=>{
|
|
2369
|
+
container.removeEventListener('scroll', scrollHandler);
|
|
2370
|
+
resizeObserver.disconnect();
|
|
2371
|
+
};
|
|
2372
|
+
}, [
|
|
2373
|
+
checkScrollOverflow,
|
|
2374
|
+
scrollHandler
|
|
2375
|
+
]);
|
|
2376
|
+
// Scroll to the selected tab when the selected key changes
|
|
2377
|
+
// We use the state.selectedItem here instead of just the state.selectedKey, since state.selectedItem is set when the tab list is mounted
|
|
2378
|
+
// This way we can make sure the default selected tab is scrolled into view.
|
|
2379
|
+
useEffect(()=>{
|
|
2380
|
+
const container = scrollContainerRef.current;
|
|
2381
|
+
if (!container) return;
|
|
2382
|
+
const selectedKey = state?.selectedItem?.key;
|
|
2383
|
+
if (!selectedKey) return;
|
|
2384
|
+
// Scroll to the selected tab when it changes
|
|
2385
|
+
const selectedTab = container.querySelector(`[data-key="${selectedKey}"]`);
|
|
2386
|
+
if (!selectedTab) return;
|
|
2387
|
+
const offsetLeft = selectedTab.offsetLeft;
|
|
2388
|
+
const containerWidth = container.clientWidth;
|
|
2389
|
+
// Set the scroll position to try and ish center the selected tab
|
|
2390
|
+
const scrollLeft = offsetLeft - (containerWidth - selectedTab.clientWidth) / 2;
|
|
2391
|
+
// When the scroll is initiated by the user we want a smooth scroll
|
|
2392
|
+
if (hasScrollingOccurredRef.current) {
|
|
2393
|
+
// The RAC TabList component prevents us from using scroll snapping, so by using requestAnimationFrame, we can ensure the scroll position is set correctly.
|
|
2394
|
+
// We want the active tab to be centered in the view when navigating with the scroll buttons, selecting a tab with the keyboard, or clicking on a tab.
|
|
2395
|
+
requestAnimationFrame(()=>{
|
|
2396
|
+
container.scrollTo({
|
|
2397
|
+
left: scrollLeft,
|
|
2398
|
+
behavior: 'smooth'
|
|
2399
|
+
});
|
|
2400
|
+
});
|
|
2401
|
+
} else {
|
|
2402
|
+
// When the scroll is done to ensure the default selected tab is in view, we want instant scrolling
|
|
2403
|
+
container.scrollTo({
|
|
2404
|
+
left: scrollLeft,
|
|
2405
|
+
behavior: 'instant'
|
|
2406
|
+
});
|
|
2407
|
+
}
|
|
2408
|
+
}, [
|
|
2409
|
+
state?.selectedItem
|
|
2410
|
+
]);
|
|
2411
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
2412
|
+
className: "relative overflow-hidden",
|
|
2413
|
+
children: [
|
|
2414
|
+
/*#__PURE__*/ jsx(TabList$1, {
|
|
2415
|
+
...restProps,
|
|
2416
|
+
ref: scrollContainerRef,
|
|
2417
|
+
"data-scroll-animation": false,
|
|
2418
|
+
className: cx(className, 'group/tablist', // Ensure the tab list is scrollable
|
|
2419
|
+
'scrollbar-hidden overflow-x-auto', 'flex w-fit max-w-full', // Ensure tabs don't shrink and maintain min-width
|
|
2420
|
+
'[&>*]:min-w-fit [&>*]:flex-shrink-0', // Divider line
|
|
2421
|
+
'border-gray-light', 'data-[orientation=horizontal]:border-b', 'data-[orientation=vertical]:border-r', // Selection highlight based on orientation
|
|
2422
|
+
'data-[orientation=horizontal]:*:border-y-2', 'data-[orientation=horizontal]:*:data-selected:border-b-blue-dark', 'data-[orientation=vertical]:*:border-r-2', 'data-[orientation=vertical]:*:data-selected:border-r-blue-dark', // Flex direction based on orientation
|
|
2423
|
+
'data-[orientation=vertical]:flex-col'),
|
|
2424
|
+
style: {
|
|
2425
|
+
WebkitOverflowScrolling: 'touch'
|
|
2426
|
+
},
|
|
2427
|
+
children: children
|
|
2428
|
+
}),
|
|
2429
|
+
// biome-ignore lint/a11y/useKeyWithClickEvents: These are just for scrolling, and not necessary for keyboard or screen reader users. They can use the tablist's keyboard navigation pattern to navigate the entire list the same way.
|
|
2430
|
+
/*#__PURE__*/ jsx("div", {
|
|
2431
|
+
onClick: onPrev,
|
|
2432
|
+
className: cx('cursor-pointer', 'flex items-center', // Ensure click are of 44px by 44px.
|
|
2433
|
+
'size-11', // Position the button at the left of the tab list, with a small (left) offset to avoid overlap with the tabs.
|
|
2434
|
+
// The bottom offset is to avoid overlap with the tab lists bottom border.
|
|
2435
|
+
'-left-3 absolute bottom-0.25', // Creates a gradient background that fades to transparent on the right side, which creates a smooth overlay effect over the tabs that are scrolled out of view.
|
|
2436
|
+
'bg-[linear-gradient(90deg,white,white_calc(100%-10px),transparent)]', // Slide in and out based on scroll position, match duration with the debounce delay of the scrollHandler function
|
|
2437
|
+
// Wait until user started scrolling until animation is applied, to prevent the animation from running on mount
|
|
2438
|
+
hasScrollingOccurredRef.current && 'duration-100 ease-in motion-safe:transition-transform', !canScrollLeft && '-translate-x-full pointer-events-none'),
|
|
2439
|
+
children: /*#__PURE__*/ jsx(ChevronLeft, {
|
|
2440
|
+
className: "mt-0.25 h-6 w-full text-black"
|
|
2441
|
+
})
|
|
2442
|
+
}),
|
|
2443
|
+
// biome-ignore lint/a11y/useKeyWithClickEvents: These are just for scrolling, and not necessary for keyboard or screen reader users. They can use the tablist's keyboard navigation pattern to navigate the entire list the same way.
|
|
2444
|
+
/*#__PURE__*/ jsx("div", {
|
|
2445
|
+
onClick: onNext,
|
|
2446
|
+
className: cx('cursor-pointer', 'flex items-center', // Ensure click are of 44px by 44px.
|
|
2447
|
+
'size-11', // Position the button at the right of the tab list, with a small (right) offset to avoid overlap with the tabs.
|
|
2448
|
+
// The bottom offset is to avoid overlap with the tab lists bottom border.
|
|
2449
|
+
'-right-3 absolute bottom-0.25', // Creates a gradient background that fades to transparent on the left side, which creates a smooth overlay effect over the tabs that are scrolled out of view.
|
|
2450
|
+
'bg-[linear-gradient(90deg,transparent,white_calc(10px),white)]', // Slide in and out based on scroll position, match duration with the debounce delay of the scrollHandler function
|
|
2451
|
+
// Wait until user started scrolling until animation is applied, to prevent the animation from running on mount
|
|
2452
|
+
hasScrollingOccurredRef.current && 'duration-100 ease-in motion-safe:transition-transform', !canScrollRight && 'pointer-events-none translate-x-full'),
|
|
2453
|
+
children: /*#__PURE__*/ jsx(ChevronRight, {
|
|
2454
|
+
className: "mt-0.25 h-6 w-full text-black "
|
|
2455
|
+
})
|
|
2456
|
+
})
|
|
2457
|
+
]
|
|
2458
|
+
});
|
|
2459
|
+
}
|
|
2460
|
+
/**
|
|
2461
|
+
* An individual tab that can be selected to display its associated content.
|
|
2462
|
+
*/ function Tab(props) {
|
|
2463
|
+
const { className, children, ...restProps } = props;
|
|
2464
|
+
return /*#__PURE__*/ jsx(Tab$1, {
|
|
2465
|
+
...restProps,
|
|
2466
|
+
className: cx(className, 'data-focus-visible:-outline-offset-10 data-focus-visible:outline-2 data-focus-visible:outline-black', 'cursor-pointer border-transparent px-4 py-2 font-light text-sm', // Transition
|
|
2467
|
+
'transition-colors duration-150 ease-out', // TODO: Should disabled tabs just be hidden?
|
|
2468
|
+
'data-disabled:cursor-not-allowed data-disabled:opacity-50', // Selection
|
|
2469
|
+
'data-selected:font-medium data-selected:text-blue-dark', // Hover with layout shift prevention using pseudo-element
|
|
2470
|
+
'after:invisible after:block after:h-0 after:overflow-hidden after:font-medium after:content-[attr(data-text)]', 'data-hovered:font-medium', // Pressed
|
|
2471
|
+
'data-pressed:font-medium data-pressed:text-blue-dark'),
|
|
2472
|
+
"data-text": typeof children === 'string' ? children : '',
|
|
2473
|
+
children: children
|
|
2474
|
+
});
|
|
2475
|
+
}
|
|
2476
|
+
/**
|
|
2477
|
+
* The content area that displays the selected tab's content.
|
|
2478
|
+
*/ function TabPanel(props) {
|
|
2479
|
+
const { className, children, ...restProps } = props;
|
|
2480
|
+
return /*#__PURE__*/ jsx(TabPanel$1, {
|
|
2481
|
+
...restProps,
|
|
2482
|
+
className: cx(className, 'flex-1 data-focus-visible:outline-focus-offset'),
|
|
2483
|
+
children: children
|
|
2484
|
+
});
|
|
2485
|
+
}
|
|
2486
|
+
|
|
2487
|
+
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, DisclosureStateContext, ErrorMessage, Footer, GrunnmurenProvider, Heading, HeadingContext, Label, Media, MediaContext, NumberField, Radio, RadioGroup, Select, ListBoxHeader as SelectHeader, ListBoxItem as SelectItem, ListBoxSection as SelectSection, TextArea, TextField, Carousel as UNSAFE_Carousel, CarouselItem as UNSAFE_CarouselItem, CarouselItems as UNSAFE_CarouselItems, Dialog as UNSAFE_Dialog, DialogTrigger as UNSAFE_DialogTrigger, Disclosure as UNSAFE_Disclosure, DisclosureButton as UNSAFE_DisclosureButton, DisclosurePanel as UNSAFE_DisclosurePanel, FileUpload as UNSAFE_FileUpload, Hero as UNSAFE_Hero, Modal as UNSAFE_Modal, Tab as UNSAFE_Tab, TabList as UNSAFE_TabList, TabPanel as UNSAFE_TabPanel, Tabs as UNSAFE_Tabs, Tag as UNSAFE_Tag, TagGroup as UNSAFE_TagGroup, TagList as UNSAFE_TagList, VideoLoop, _useLocale as useLocale };
|