@obosbbl/grunnmuren-react 3.0.0 → 3.0.2
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 +49 -4
- package/dist/index.mjs +225 -15
- 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';
|
|
@@ -642,7 +642,7 @@ type CarouselItemsProps = {
|
|
|
642
642
|
declare const CarouselItems: ({ className, children }: CarouselItemsProps) => react_jsx_runtime.JSX.Element;
|
|
643
643
|
type CarouselItemProps = {
|
|
644
644
|
/** The component/components to display as the <CarouselItem/>. */
|
|
645
|
-
children:
|
|
645
|
+
children: JSX.Element | JSX.Element[];
|
|
646
646
|
/** Additional CSS className for the element. */
|
|
647
647
|
className?: string;
|
|
648
648
|
id?: string;
|
|
@@ -657,4 +657,49 @@ type CarouselItem = Pick<CarouselItemProps, 'id'> & {
|
|
|
657
657
|
};
|
|
658
658
|
declare const CarouselItem: ({ className, children, id }: CarouselItemProps) => react_jsx_runtime.JSX.Element;
|
|
659
659
|
|
|
660
|
-
|
|
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';
|
|
@@ -174,7 +174,7 @@ function AccordionItem(props) {
|
|
|
174
174
|
_innerWrapper: (children)=>/*#__PURE__*/ jsxs("button", {
|
|
175
175
|
"aria-controls": contentId,
|
|
176
176
|
"aria-expanded": isOpen,
|
|
177
|
-
// Use outline with offset as focus indicator, this does not cover the left
|
|
177
|
+
// Use outline with offset as focus indicator, this does not cover the left sky border on the expanded content and works with or without a background color on the accordion container
|
|
178
178
|
className: "flex min-h-[44px] w-full cursor-pointer items-center justify-between gap-1.5 rounded-lg px-2 py-3.5 text-left focus-visible:outline-focus focus-visible:outline-focus-inset",
|
|
179
179
|
id: buttonId,
|
|
180
180
|
onClick: handleOpenChange,
|
|
@@ -192,7 +192,7 @@ function AccordionItem(props) {
|
|
|
192
192
|
ContentContext,
|
|
193
193
|
{
|
|
194
194
|
className: // Uses pseudo element for vertical padding, since that doesn't affect the height when the accordion is closed
|
|
195
|
-
'text-sm font-light leading-6 px-3.5 relative overflow-hidden border-
|
|
195
|
+
'text-sm font-light leading-6 px-3.5 relative overflow-hidden border-sky border-l-[3px] before:relative before:block before:h-1.5 after:relative after:block after:h-1.5',
|
|
196
196
|
role: 'region',
|
|
197
197
|
inert: !isOpen,
|
|
198
198
|
'aria-labelledby': buttonId,
|
|
@@ -401,7 +401,6 @@ function Button({ ref = null, ...props }) {
|
|
|
401
401
|
}) : _children;
|
|
402
402
|
return isLinkProps$1(restProps) ? /*#__PURE__*/ jsx(Link, {
|
|
403
403
|
...restProps,
|
|
404
|
-
routerOptions: restProps.routerOptions,
|
|
405
404
|
className: className,
|
|
406
405
|
ref: ref,
|
|
407
406
|
children: children
|
|
@@ -482,17 +481,22 @@ function CheckmarkBox() {
|
|
|
482
481
|
// TODO: 1.75 here is the unit less lineheight, altough we use 1.75rem as the line height, so there is a mismatch here. Revisit this when we've worked on typography in v2. Should this be a CSS custom property instead?
|
|
483
482
|
'mt-[calc((1em_*_1.75_-_24px)_/_2)] h-[24px] w-[24px]',
|
|
484
483
|
// selected
|
|
485
|
-
'group-data-selected
|
|
484
|
+
'group-data-selected:group-not-data-hovered:group-not-data-invalid:border-blue group-data-selected:group-not-data-hovered:group-not-data-invalid:bg-blue',
|
|
485
|
+
'group-data-selected:group-not-data-hovered:group-data-invalid:border-red group-data-selected:group-not-data-hovered:group-data-invalid:bg-red',
|
|
486
486
|
// focus
|
|
487
487
|
'group-data-focus-visible:outline-focus-offset',
|
|
488
488
|
// hovered
|
|
489
|
-
'group-data-hovered:group-data-invalid:
|
|
489
|
+
'group-data-hovered:group-data-invalid:bg-red-light',
|
|
490
|
+
'group-data-hovered:border-blue',
|
|
491
|
+
'group-data-hovered:bg-sky',
|
|
492
|
+
'group-data-hovered:group-data-selected:group-not-data-invalid:border-blue-dark',
|
|
493
|
+
'group-data-hovered:group-data-selected:group-not-data-invalid:bg-blue-dark',
|
|
490
494
|
// invalid - The border is 1 px thicker when invalid. We don't actually want to change the border width, as that causes the element's size to change
|
|
491
495
|
// so we use an inner shadow of 1 px instead to pad the actual border
|
|
492
|
-
'group-data-invalid:
|
|
496
|
+
'group-data-invalid:border-red group-data-invalid:shadow-[inset_0_0_0_1px] group-data-invalid:shadow-red'
|
|
493
497
|
]),
|
|
494
498
|
children: /*#__PURE__*/ jsx(Check, {
|
|
495
|
-
className: "h-full w-full opacity-0 group-data-selected:opacity-100"
|
|
499
|
+
className: "h-full w-full opacity-0 group-data-invalid:group-data-hovered:group-data-selected:text-red group-data-selected:opacity-100"
|
|
496
500
|
})
|
|
497
501
|
});
|
|
498
502
|
}
|
|
@@ -726,9 +730,9 @@ const defaultClasses = cx([
|
|
|
726
730
|
// TODO: 1.75 here is the unit less lineheight, altough we use 1.75rem as the line height, so there is a mismatch here. Revisit this when we've worked on typography in v2. Should this be a CSS custom property instead?
|
|
727
731
|
'before:mt-[calc((1em_*_1.75_-_24px)_/_2)] before:h-[24px] before:w-[24px]',
|
|
728
732
|
// selected
|
|
729
|
-
'data-selected:before:border-black data-selected:before:bg-
|
|
733
|
+
'data-selected:before:border-black data-selected:before:bg-blue data-selected:before:shadow-[inset_0_0_0_4px_rgb(255,255,255)]',
|
|
730
734
|
// hover
|
|
731
|
-
'data-hovered:data-invalid:before:bg-red-light data-hovered:before:border-
|
|
735
|
+
'data-hovered:data-selected:before:border-blue-dark data-hovered:data-invalid:before:bg-red-light data-hovered:data-selected:before:bg-blue-dark data-hovered:before:border-blue data-hovered:before:bg-sky',
|
|
732
736
|
// focus
|
|
733
737
|
'data-focus-visible:before:ring-focus-offset',
|
|
734
738
|
// invalid - The border is 1 px thicker when invalid. We don't actually want to change the border width, as that causes the element's size to change
|
|
@@ -1948,12 +1952,23 @@ const Dialog = ({ className, children, ...restProps })=>{
|
|
|
1948
1952
|
const tagVariants = cva({
|
|
1949
1953
|
base: [
|
|
1950
1954
|
'relative flex cursor-pointer items-center gap-1 rounded-lg px-2 py-1 font-medium text-sm transition-colors duration-200',
|
|
1955
|
+
// Resting
|
|
1956
|
+
'border-2 border-black bg-white text-black',
|
|
1951
1957
|
//Focus
|
|
1952
1958
|
'focus-visible:outline-focus-offset',
|
|
1953
|
-
//
|
|
1954
|
-
'
|
|
1955
|
-
//
|
|
1956
|
-
|
|
1959
|
+
// Hover
|
|
1960
|
+
' data-hovered:bg-sky',
|
|
1961
|
+
// Selected
|
|
1962
|
+
// Allows removing
|
|
1963
|
+
'data-allows-removing:border-transparent',
|
|
1964
|
+
'data-allows-removing:bg-blue',
|
|
1965
|
+
'data-allows-removing:data-hovered:bg-blue-dark',
|
|
1966
|
+
'data-allows-removing:text-white',
|
|
1967
|
+
// Selected
|
|
1968
|
+
'aria-selected:border-transparent',
|
|
1969
|
+
'aria-selected:bg-blue',
|
|
1970
|
+
'aria-selected:data-hovered:bg-blue-dark',
|
|
1971
|
+
'aria-selected:text-white',
|
|
1957
1972
|
//Icons
|
|
1958
1973
|
'[&_svg]:h-4 [&_svg]:w-4'
|
|
1959
1974
|
]
|
|
@@ -2290,4 +2305,199 @@ const CarouselItem = ({ className, children, id })=>{
|
|
|
2290
2305
|
});
|
|
2291
2306
|
};
|
|
2292
2307
|
|
|
2293
|
-
|
|
2308
|
+
const tabsVariants = cva({
|
|
2309
|
+
base: [
|
|
2310
|
+
'grid gap-4'
|
|
2311
|
+
],
|
|
2312
|
+
variants: {
|
|
2313
|
+
orientation: {
|
|
2314
|
+
horizontal: '',
|
|
2315
|
+
vertical: 'grid-cols-[auto_1fr]'
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
});
|
|
2319
|
+
/**
|
|
2320
|
+
* A container component that organizes content into multiple sections
|
|
2321
|
+
* and allows users to navigate between them.
|
|
2322
|
+
*/ function Tabs(props) {
|
|
2323
|
+
const { className, children, orientation = 'horizontal', ...restProps } = props;
|
|
2324
|
+
return /*#__PURE__*/ jsx(Tabs$1, {
|
|
2325
|
+
...restProps,
|
|
2326
|
+
orientation: orientation,
|
|
2327
|
+
className: tabsVariants({
|
|
2328
|
+
className,
|
|
2329
|
+
orientation
|
|
2330
|
+
}),
|
|
2331
|
+
children: children
|
|
2332
|
+
});
|
|
2333
|
+
}
|
|
2334
|
+
/**
|
|
2335
|
+
* A container component for Tab components within Tabs.
|
|
2336
|
+
*/ function TabList({ className, children, ...restProps }) {
|
|
2337
|
+
const scrollContainerRef = useRef(null);
|
|
2338
|
+
const [canScrollLeft, setCanScrollLeft] = useState(false);
|
|
2339
|
+
const [canScrollRight, setCanScrollRight] = useState(false);
|
|
2340
|
+
const checkScrollOverflow = useCallback(()=>{
|
|
2341
|
+
const container = scrollContainerRef.current;
|
|
2342
|
+
if (!container) return;
|
|
2343
|
+
const { scrollLeft, scrollWidth, clientWidth } = container;
|
|
2344
|
+
setCanScrollLeft(scrollLeft > 0);
|
|
2345
|
+
setCanScrollRight(scrollLeft < scrollWidth - clientWidth - 1);
|
|
2346
|
+
}, []);
|
|
2347
|
+
const state = useContext(TabListStateContext);
|
|
2348
|
+
const prevKey = state?.selectedKey && state?.collection.getKeyBefore(state.selectedKey);
|
|
2349
|
+
const onPrev = prevKey ? ()=>state?.setSelectedKey(prevKey) : ()=>{
|
|
2350
|
+
if (canScrollLeft && state?.selectedKey === state?.collection.firstKey) {
|
|
2351
|
+
// Scroll to the start of the tab list if we are at the first tab but it is scrolled out of view
|
|
2352
|
+
scrollContainerRef.current?.scrollTo({
|
|
2353
|
+
left: 0,
|
|
2354
|
+
behavior: 'smooth'
|
|
2355
|
+
});
|
|
2356
|
+
}
|
|
2357
|
+
};
|
|
2358
|
+
const nextKey = state?.selectedKey && state?.collection.getKeyAfter(state.selectedKey);
|
|
2359
|
+
const onNext = nextKey ? ()=>state?.setSelectedKey(nextKey) : ()=>{
|
|
2360
|
+
if (canScrollRight && state?.selectedKey === state?.collection.lastKey) {
|
|
2361
|
+
// Scroll to the end of the tab list if we are at the last tab but it is scrolled out of view
|
|
2362
|
+
scrollContainerRef.current?.scrollTo({
|
|
2363
|
+
left: scrollContainerRef.current.scrollWidth,
|
|
2364
|
+
behavior: 'smooth'
|
|
2365
|
+
});
|
|
2366
|
+
}
|
|
2367
|
+
};
|
|
2368
|
+
// To controll if the animation for the scroll buttons and the scrolling behavior
|
|
2369
|
+
// This is used to prevent animations from running when the component mounts
|
|
2370
|
+
// We use a ref here to prevent redundant render cycles and potentially uninteded scrolling.
|
|
2371
|
+
const hasScrollingOccurredRef = useRef(false);
|
|
2372
|
+
// Debounce the scroll handler to avoid performance issues with frequent scroll events
|
|
2373
|
+
const scrollHandler = useDebouncedCallback(()=>{
|
|
2374
|
+
checkScrollOverflow();
|
|
2375
|
+
hasScrollingOccurredRef.current = true;
|
|
2376
|
+
}, 100);
|
|
2377
|
+
useEffect(()=>{
|
|
2378
|
+
const container = scrollContainerRef.current;
|
|
2379
|
+
if (!container) return;
|
|
2380
|
+
checkScrollOverflow();
|
|
2381
|
+
container.addEventListener('scroll', scrollHandler);
|
|
2382
|
+
const resizeObserver = new ResizeObserver(checkScrollOverflow);
|
|
2383
|
+
resizeObserver.observe(container);
|
|
2384
|
+
return ()=>{
|
|
2385
|
+
container.removeEventListener('scroll', scrollHandler);
|
|
2386
|
+
resizeObserver.disconnect();
|
|
2387
|
+
};
|
|
2388
|
+
}, [
|
|
2389
|
+
checkScrollOverflow,
|
|
2390
|
+
scrollHandler
|
|
2391
|
+
]);
|
|
2392
|
+
// Scroll to the selected tab when the selected key changes
|
|
2393
|
+
// We use the state.selectedItem here instead of just the state.selectedKey, since state.selectedItem is set when the tab list is mounted
|
|
2394
|
+
// This way we can make sure the default selected tab is scrolled into view.
|
|
2395
|
+
useEffect(()=>{
|
|
2396
|
+
const container = scrollContainerRef.current;
|
|
2397
|
+
if (!container) return;
|
|
2398
|
+
const selectedKey = state?.selectedItem?.key;
|
|
2399
|
+
if (!selectedKey) return;
|
|
2400
|
+
// Scroll to the selected tab when it changes
|
|
2401
|
+
const selectedTab = container.querySelector(`[data-key="${selectedKey}"]`);
|
|
2402
|
+
if (!selectedTab) return;
|
|
2403
|
+
const offsetLeft = selectedTab.offsetLeft;
|
|
2404
|
+
const containerWidth = container.clientWidth;
|
|
2405
|
+
// Set the scroll position to try and ish center the selected tab
|
|
2406
|
+
const scrollLeft = offsetLeft - (containerWidth - selectedTab.clientWidth) / 2;
|
|
2407
|
+
// When the scroll is initiated by the user we want a smooth scroll
|
|
2408
|
+
if (hasScrollingOccurredRef.current) {
|
|
2409
|
+
// The RAC TabList component prevents us from using scroll snapping, so by using requestAnimationFrame, we can ensure the scroll position is set correctly.
|
|
2410
|
+
// 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.
|
|
2411
|
+
requestAnimationFrame(()=>{
|
|
2412
|
+
container.scrollTo({
|
|
2413
|
+
left: scrollLeft,
|
|
2414
|
+
behavior: 'smooth'
|
|
2415
|
+
});
|
|
2416
|
+
});
|
|
2417
|
+
} else {
|
|
2418
|
+
// When the scroll is done to ensure the default selected tab is in view, we want instant scrolling
|
|
2419
|
+
container.scrollTo({
|
|
2420
|
+
left: scrollLeft,
|
|
2421
|
+
behavior: 'instant'
|
|
2422
|
+
});
|
|
2423
|
+
}
|
|
2424
|
+
}, [
|
|
2425
|
+
state?.selectedItem
|
|
2426
|
+
]);
|
|
2427
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
2428
|
+
className: "relative overflow-hidden",
|
|
2429
|
+
children: [
|
|
2430
|
+
/*#__PURE__*/ jsx(TabList$1, {
|
|
2431
|
+
...restProps,
|
|
2432
|
+
ref: scrollContainerRef,
|
|
2433
|
+
"data-scroll-animation": false,
|
|
2434
|
+
className: cx(className, 'group/tablist', // Ensure the tab list is scrollable
|
|
2435
|
+
'scrollbar-hidden overflow-x-auto', 'flex w-fit max-w-full', // Ensure tabs don't shrink and maintain min-width
|
|
2436
|
+
'[&>*]:min-w-fit [&>*]:flex-shrink-0', // Divider line
|
|
2437
|
+
'border-gray-light', 'data-[orientation=horizontal]:border-b', 'data-[orientation=vertical]:border-r', // Selection highlight based on orientation
|
|
2438
|
+
'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
|
|
2439
|
+
'data-[orientation=vertical]:flex-col'),
|
|
2440
|
+
style: {
|
|
2441
|
+
WebkitOverflowScrolling: 'touch'
|
|
2442
|
+
},
|
|
2443
|
+
children: children
|
|
2444
|
+
}),
|
|
2445
|
+
// 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.
|
|
2446
|
+
/*#__PURE__*/ jsx("div", {
|
|
2447
|
+
onClick: onPrev,
|
|
2448
|
+
className: cx('cursor-pointer', 'flex items-center', // Ensure click are of 44px by 44px.
|
|
2449
|
+
'size-11', // Position the button at the left of the tab list, with a small (left) offset to avoid overlap with the tabs.
|
|
2450
|
+
// The bottom offset is to avoid overlap with the tab lists bottom border.
|
|
2451
|
+
'-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.
|
|
2452
|
+
'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
|
|
2453
|
+
// Wait until user started scrolling until animation is applied, to prevent the animation from running on mount
|
|
2454
|
+
hasScrollingOccurredRef.current && 'duration-100 ease-in motion-safe:transition-transform', !canScrollLeft && '-translate-x-full pointer-events-none'),
|
|
2455
|
+
children: /*#__PURE__*/ jsx(ChevronLeft, {
|
|
2456
|
+
className: "mt-0.25 h-6 w-full text-black"
|
|
2457
|
+
})
|
|
2458
|
+
}),
|
|
2459
|
+
// 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.
|
|
2460
|
+
/*#__PURE__*/ jsx("div", {
|
|
2461
|
+
onClick: onNext,
|
|
2462
|
+
className: cx('cursor-pointer', 'flex items-center', // Ensure click are of 44px by 44px.
|
|
2463
|
+
'size-11', // Position the button at the right of the tab list, with a small (right) offset to avoid overlap with the tabs.
|
|
2464
|
+
// The bottom offset is to avoid overlap with the tab lists bottom border.
|
|
2465
|
+
'-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.
|
|
2466
|
+
'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
|
|
2467
|
+
// Wait until user started scrolling until animation is applied, to prevent the animation from running on mount
|
|
2468
|
+
hasScrollingOccurredRef.current && 'duration-100 ease-in motion-safe:transition-transform', !canScrollRight && 'pointer-events-none translate-x-full'),
|
|
2469
|
+
children: /*#__PURE__*/ jsx(ChevronRight, {
|
|
2470
|
+
className: "mt-0.25 h-6 w-full text-black "
|
|
2471
|
+
})
|
|
2472
|
+
})
|
|
2473
|
+
]
|
|
2474
|
+
});
|
|
2475
|
+
}
|
|
2476
|
+
/**
|
|
2477
|
+
* An individual tab that can be selected to display its associated content.
|
|
2478
|
+
*/ function Tab(props) {
|
|
2479
|
+
const { className, children, ...restProps } = props;
|
|
2480
|
+
return /*#__PURE__*/ jsx(Tab$1, {
|
|
2481
|
+
...restProps,
|
|
2482
|
+
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
|
|
2483
|
+
'transition-colors duration-150 ease-out', // TODO: Should disabled tabs just be hidden?
|
|
2484
|
+
'data-disabled:cursor-not-allowed data-disabled:opacity-50', // Selection
|
|
2485
|
+
'data-selected:font-medium data-selected:text-blue-dark', // Hover with layout shift prevention using pseudo-element
|
|
2486
|
+
'after:invisible after:block after:h-0 after:overflow-hidden after:font-medium after:content-[attr(data-text)]', 'data-hovered:font-medium', // Pressed
|
|
2487
|
+
'data-pressed:font-medium data-pressed:text-blue-dark'),
|
|
2488
|
+
"data-text": typeof children === 'string' ? children : '',
|
|
2489
|
+
children: children
|
|
2490
|
+
});
|
|
2491
|
+
}
|
|
2492
|
+
/**
|
|
2493
|
+
* The content area that displays the selected tab's content.
|
|
2494
|
+
*/ function TabPanel(props) {
|
|
2495
|
+
const { className, children, ...restProps } = props;
|
|
2496
|
+
return /*#__PURE__*/ jsx(TabPanel$1, {
|
|
2497
|
+
...restProps,
|
|
2498
|
+
className: cx(className, 'flex-1 data-focus-visible:outline-focus-offset'),
|
|
2499
|
+
children: children
|
|
2500
|
+
});
|
|
2501
|
+
}
|
|
2502
|
+
|
|
2503
|
+
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 };
|